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 */
536 timestamp = g_ascii_strtoull (timestr, &end, 0);
537 if (errno == 0 && end != timestr)
545 startup_id_is_fake (const gchar* startup_id)
547 return strncmp (startup_id, "_TIME", 5) == 0;
551 gtk_window_class_init (GtkWindowClass *klass)
553 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
554 GtkWidgetClass *widget_class;
555 GtkContainerClass *container_class;
556 GtkBindingSet *binding_set;
558 widget_class = (GtkWidgetClass*) klass;
559 container_class = (GtkContainerClass*) klass;
561 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
562 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
563 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
564 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
566 gobject_class->dispose = gtk_window_dispose;
567 gobject_class->finalize = gtk_window_finalize;
569 gobject_class->set_property = gtk_window_set_property;
570 gobject_class->get_property = gtk_window_get_property;
572 widget_class->destroy = gtk_window_destroy;
573 widget_class->show = gtk_window_show;
574 widget_class->hide = gtk_window_hide;
575 widget_class->map = gtk_window_map;
576 widget_class->map_event = gtk_window_map_event;
577 widget_class->unmap = gtk_window_unmap;
578 widget_class->realize = gtk_window_realize;
579 widget_class->unrealize = gtk_window_unrealize;
580 widget_class->size_allocate = gtk_window_size_allocate;
581 widget_class->configure_event = gtk_window_configure_event;
582 widget_class->key_press_event = gtk_window_key_press_event;
583 widget_class->key_release_event = gtk_window_key_release_event;
584 widget_class->enter_notify_event = gtk_window_enter_notify_event;
585 widget_class->leave_notify_event = gtk_window_leave_notify_event;
586 widget_class->focus_in_event = gtk_window_focus_in_event;
587 widget_class->button_press_event = gtk_window_button_press_event;
588 widget_class->focus_out_event = gtk_window_focus_out_event;
589 widget_class->client_event = gtk_window_client_event;
590 widget_class->focus = gtk_window_focus;
591 widget_class->move_focus = gtk_window_move_focus;
592 widget_class->draw = gtk_window_draw;
593 widget_class->get_preferred_width = gtk_window_get_preferred_width;
594 widget_class->get_preferred_height = gtk_window_get_preferred_height;
595 widget_class->window_state_event = gtk_window_state_event;
596 widget_class->direction_changed = gtk_window_direction_changed;
597 widget_class->state_changed = gtk_window_state_changed;
598 widget_class->style_set = gtk_window_style_set;
600 container_class->check_resize = gtk_window_check_resize;
602 klass->set_focus = gtk_window_real_set_focus;
603 klass->frame_event = gtk_window_frame_event;
605 klass->activate_default = gtk_window_real_activate_default;
606 klass->activate_focus = gtk_window_real_activate_focus;
607 klass->keys_changed = gtk_window_keys_changed;
609 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
612 g_object_class_install_property (gobject_class,
614 g_param_spec_enum ("type",
616 P_("The type of the window"),
617 GTK_TYPE_WINDOW_TYPE,
619 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
621 g_object_class_install_property (gobject_class,
623 g_param_spec_string ("title",
625 P_("The title of the window"),
627 GTK_PARAM_READWRITE));
629 g_object_class_install_property (gobject_class,
631 g_param_spec_string ("role",
633 P_("Unique identifier for the window to be used when restoring a session"),
635 GTK_PARAM_READWRITE));
638 * GtkWindow:startup-id:
640 * The :startup-id is a write-only property for setting window's
641 * startup notification identifier. See gtk_window_set_startup_id()
646 g_object_class_install_property (gobject_class,
648 g_param_spec_string ("startup-id",
650 P_("Unique startup identifier for the window used by startup-notification"),
652 GTK_PARAM_WRITABLE));
654 g_object_class_install_property (gobject_class,
656 g_param_spec_boolean ("resizable",
658 P_("If TRUE, users can resize the window"),
660 GTK_PARAM_READWRITE));
662 g_object_class_install_property (gobject_class,
664 g_param_spec_boolean ("modal",
666 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
668 GTK_PARAM_READWRITE));
670 g_object_class_install_property (gobject_class,
672 g_param_spec_enum ("window-position",
673 P_("Window Position"),
674 P_("The initial position of the window"),
675 GTK_TYPE_WINDOW_POSITION,
677 GTK_PARAM_READWRITE));
679 g_object_class_install_property (gobject_class,
681 g_param_spec_int ("default-width",
683 P_("The default width of the window, used when initially showing the window"),
687 GTK_PARAM_READWRITE));
689 g_object_class_install_property (gobject_class,
691 g_param_spec_int ("default-height",
692 P_("Default Height"),
693 P_("The default height of the window, used when initially showing the window"),
697 GTK_PARAM_READWRITE));
699 g_object_class_install_property (gobject_class,
700 PROP_DESTROY_WITH_PARENT,
701 g_param_spec_boolean ("destroy-with-parent",
702 P_("Destroy with Parent"),
703 P_("If this window should be destroyed when the parent is destroyed"),
705 GTK_PARAM_READWRITE));
707 g_object_class_install_property (gobject_class,
709 g_param_spec_object ("icon",
711 P_("Icon for this window"),
713 GTK_PARAM_READWRITE));
714 g_object_class_install_property (gobject_class,
715 PROP_MNEMONICS_VISIBLE,
716 g_param_spec_boolean ("mnemonics-visible",
717 P_("Mnemonics Visible"),
718 P_("Whether mnemonics are currently visible in this window"),
720 GTK_PARAM_READWRITE));
723 * GtkWindow:icon-name:
725 * The :icon-name property specifies the name of the themed icon to
726 * use as the window icon. See #GtkIconTheme for more details.
730 g_object_class_install_property (gobject_class,
732 g_param_spec_string ("icon-name",
734 P_("Name of the themed icon for this window"),
736 GTK_PARAM_READWRITE));
738 g_object_class_install_property (gobject_class,
740 g_param_spec_object ("screen",
742 P_("The screen where this window will be displayed"),
744 GTK_PARAM_READWRITE));
746 g_object_class_install_property (gobject_class,
748 g_param_spec_boolean ("is-active",
750 P_("Whether the toplevel is the current active window"),
752 GTK_PARAM_READABLE));
754 g_object_class_install_property (gobject_class,
755 PROP_HAS_TOPLEVEL_FOCUS,
756 g_param_spec_boolean ("has-toplevel-focus",
757 P_("Focus in Toplevel"),
758 P_("Whether the input focus is within this GtkWindow"),
760 GTK_PARAM_READABLE));
762 g_object_class_install_property (gobject_class,
764 g_param_spec_enum ("type-hint",
766 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
767 GDK_TYPE_WINDOW_TYPE_HINT,
768 GDK_WINDOW_TYPE_HINT_NORMAL,
769 GTK_PARAM_READWRITE));
771 g_object_class_install_property (gobject_class,
772 PROP_SKIP_TASKBAR_HINT,
773 g_param_spec_boolean ("skip-taskbar-hint",
775 P_("TRUE if the window should not be in the task bar."),
777 GTK_PARAM_READWRITE));
779 g_object_class_install_property (gobject_class,
780 PROP_SKIP_PAGER_HINT,
781 g_param_spec_boolean ("skip-pager-hint",
783 P_("TRUE if the window should not be in the pager."),
785 GTK_PARAM_READWRITE));
787 g_object_class_install_property (gobject_class,
789 g_param_spec_boolean ("urgency-hint",
791 P_("TRUE if the window should be brought to the user's attention."),
793 GTK_PARAM_READWRITE));
796 * GtkWindow:accept-focus:
798 * Whether the window should receive the input focus.
802 g_object_class_install_property (gobject_class,
804 g_param_spec_boolean ("accept-focus",
806 P_("TRUE if the window should receive the input focus."),
808 GTK_PARAM_READWRITE));
811 * GtkWindow:focus-on-map:
813 * Whether the window should receive the input focus when mapped.
817 g_object_class_install_property (gobject_class,
819 g_param_spec_boolean ("focus-on-map",
821 P_("TRUE if the window should receive the input focus when mapped."),
823 GTK_PARAM_READWRITE));
826 * GtkWindow:decorated:
828 * Whether the window should be decorated by the window manager.
832 g_object_class_install_property (gobject_class,
834 g_param_spec_boolean ("decorated",
836 P_("Whether the window should be decorated by the window manager"),
838 GTK_PARAM_READWRITE));
841 * GtkWindow:deletable:
843 * Whether the window frame should have a close button.
847 g_object_class_install_property (gobject_class,
849 g_param_spec_boolean ("deletable",
851 P_("Whether the window frame should have a close button"),
853 GTK_PARAM_READWRITE));
856 * GtkWindow:has-resize-grip
858 * Whether the window has a corner resize grip.
860 * Note that the resize grip is only shown if the window is
861 * actually resizable and not maximized. Use
862 * #GtkWindow:resize-grip-visible to find out if the resize
863 * grip is currently shown.
867 g_object_class_install_property (gobject_class,
868 PROP_HAS_RESIZE_GRIP,
869 g_param_spec_boolean ("has-resize-grip",
871 P_("Specifies whether the window should have a resize grip"),
873 GTK_PARAM_READWRITE));
876 * GtkWindow: resize-grip-visible:
878 * Whether a corner resize grip is currently shown.
882 g_object_class_install_property (gobject_class,
883 PROP_RESIZE_GRIP_VISIBLE,
884 g_param_spec_boolean ("resize-grip-visible",
885 P_("Resize grip is visible"),
886 P_("Specifies whether the window's resize grip is visible."),
888 GTK_PARAM_READABLE));
894 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
895 * more details about window gravity.
899 g_object_class_install_property (gobject_class,
901 g_param_spec_enum ("gravity",
903 P_("The window gravity of the window"),
905 GDK_GRAVITY_NORTH_WEST,
906 GTK_PARAM_READWRITE));
910 * GtkWindow:transient-for:
912 * The transient parent of the window. See gtk_window_set_transient_for() for
913 * more details about transient windows.
917 g_object_class_install_property (gobject_class,
919 g_param_spec_object ("transient-for",
920 P_("Transient for Window"),
921 P_("The transient parent of the dialog"),
923 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
928 * The requested opacity of the window. See gtk_window_set_opacity() for
929 * more details about window opacity.
933 g_object_class_install_property (gobject_class,
935 g_param_spec_double ("opacity",
936 P_("Opacity for Window"),
937 P_("The opacity of the window, from 0 to 1"),
941 GTK_PARAM_READWRITE));
945 gtk_widget_class_install_style_property (widget_class,
946 g_param_spec_int ("resize-grip-width",
947 P_("Width of resize grip"),
948 P_("Width of resize grip"),
949 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
951 gtk_widget_class_install_style_property (widget_class,
952 g_param_spec_int ("resize-grip-height",
953 P_("Height of resize grip"),
954 P_("Height of resize grip"),
955 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
961 * GtkWindow:application:
963 * The #GtkApplication associated with the window.
965 * The application will be kept alive for at least as long as the
970 g_object_class_install_property (gobject_class,
972 g_param_spec_object ("application",
973 P_("GtkApplication"),
974 P_("The GtkApplication for the window"),
975 GTK_TYPE_APPLICATION,
976 GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
978 window_signals[SET_FOCUS] =
979 g_signal_new (I_("set-focus"),
980 G_TYPE_FROM_CLASS (gobject_class),
982 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
984 _gtk_marshal_VOID__OBJECT,
988 window_signals[FRAME_EVENT] =
989 g_signal_new (I_("frame-event"),
990 G_TYPE_FROM_CLASS (gobject_class),
992 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
993 _gtk_boolean_handled_accumulator, NULL,
994 _gtk_marshal_BOOLEAN__BOXED,
999 * GtkWindow::activate-focus:
1000 * @window: the window which received the signal
1002 * The ::activate-focus signal is a
1003 * <link linkend="keybinding-signals">keybinding signal</link>
1004 * which gets emitted when the user activates the currently
1005 * focused widget of @window.
1007 window_signals[ACTIVATE_FOCUS] =
1008 g_signal_new (I_("activate-focus"),
1009 G_TYPE_FROM_CLASS (gobject_class),
1010 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1011 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
1013 _gtk_marshal_VOID__VOID,
1018 * GtkWindow::activate-default:
1019 * @window: the window which received the signal
1021 * The ::activate-default signal is a
1022 * <link linkend="keybinding-signals">keybinding signal</link>
1023 * which gets emitted when the user activates the default widget
1026 window_signals[ACTIVATE_DEFAULT] =
1027 g_signal_new (I_("activate-default"),
1028 G_TYPE_FROM_CLASS (gobject_class),
1029 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1030 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1032 _gtk_marshal_VOID__VOID,
1037 * GtkWindow::keys-changed:
1038 * @window: the window which received the signal
1040 * The ::keys-changed signal gets emitted when the set of accelerators
1041 * or mnemonics that are associated with @window changes.
1043 window_signals[KEYS_CHANGED] =
1044 g_signal_new (I_("keys-changed"),
1045 G_TYPE_FROM_CLASS (gobject_class),
1047 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1049 _gtk_marshal_VOID__VOID,
1057 binding_set = gtk_binding_set_by_class (klass);
1059 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1060 "activate-focus", 0);
1061 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1062 "activate-focus", 0);
1064 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1065 "activate-default", 0);
1066 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1067 "activate-default", 0);
1068 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1069 "activate-default", 0);
1071 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1072 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1073 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1074 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1076 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1077 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1078 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1079 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1083 gtk_window_init (GtkWindow *window)
1085 GtkWindowPrivate *priv;
1087 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1090 priv = window->priv;
1092 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1093 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1095 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1097 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1100 priv->wmclass_name = g_strdup (g_get_prgname ());
1101 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1102 priv->wm_role = NULL;
1103 priv->geometry_info = NULL;
1104 priv->type = GTK_WINDOW_TOPLEVEL;
1105 priv->focus_widget = NULL;
1106 priv->default_widget = NULL;
1107 priv->configure_request_count = 0;
1108 priv->resizable = TRUE;
1109 priv->configure_notify_received = FALSE;
1110 priv->position = GTK_WIN_POS_NONE;
1111 priv->need_default_size = TRUE;
1112 priv->need_default_position = TRUE;
1113 priv->modal = FALSE;
1115 priv->has_frame = FALSE;
1116 priv->frame_left = 0;
1117 priv->frame_right = 0;
1118 priv->frame_top = 0;
1119 priv->frame_bottom = 0;
1120 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1121 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1122 priv->decorated = TRUE;
1123 priv->mnemonic_modifier = GDK_MOD1_MASK;
1124 priv->screen = gdk_screen_get_default ();
1126 priv->accept_focus = TRUE;
1127 priv->focus_on_map = TRUE;
1128 priv->deletable = TRUE;
1129 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1130 priv->opacity = 1.0;
1131 priv->startup_id = NULL;
1132 priv->has_resize_grip = TRUE;
1133 priv->mnemonics_visible = TRUE;
1135 g_object_ref_sink (window);
1136 priv->has_user_ref_count = TRUE;
1137 toplevel_list = g_slist_prepend (toplevel_list, window);
1139 gtk_decorated_window_init (window);
1141 g_signal_connect (priv->screen, "composited-changed",
1142 G_CALLBACK (gtk_window_on_composited_changed), window);
1146 gtk_window_set_property (GObject *object,
1148 const GValue *value,
1151 GtkWindow *window = GTK_WINDOW (object);
1152 GtkWindowPrivate *priv = window->priv;
1157 priv->type = g_value_get_enum (value);
1160 gtk_window_set_title (window, g_value_get_string (value));
1163 gtk_window_set_role (window, g_value_get_string (value));
1165 case PROP_STARTUP_ID:
1166 gtk_window_set_startup_id (window, g_value_get_string (value));
1168 case PROP_RESIZABLE:
1169 gtk_window_set_resizable (window, g_value_get_boolean (value));
1172 gtk_window_set_modal (window, g_value_get_boolean (value));
1175 gtk_window_set_position (window, g_value_get_enum (value));
1177 case PROP_DEFAULT_WIDTH:
1178 gtk_window_set_default_size_internal (window,
1179 TRUE, g_value_get_int (value),
1182 case PROP_DEFAULT_HEIGHT:
1183 gtk_window_set_default_size_internal (window,
1185 TRUE, g_value_get_int (value), FALSE);
1187 case PROP_DESTROY_WITH_PARENT:
1188 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1191 gtk_window_set_icon (window,
1192 g_value_get_object (value));
1194 case PROP_ICON_NAME:
1195 gtk_window_set_icon_name (window, g_value_get_string (value));
1198 gtk_window_set_screen (window, g_value_get_object (value));
1200 case PROP_TYPE_HINT:
1201 gtk_window_set_type_hint (window,
1202 g_value_get_enum (value));
1204 case PROP_SKIP_TASKBAR_HINT:
1205 gtk_window_set_skip_taskbar_hint (window,
1206 g_value_get_boolean (value));
1208 case PROP_SKIP_PAGER_HINT:
1209 gtk_window_set_skip_pager_hint (window,
1210 g_value_get_boolean (value));
1212 case PROP_URGENCY_HINT:
1213 gtk_window_set_urgency_hint (window,
1214 g_value_get_boolean (value));
1216 case PROP_ACCEPT_FOCUS:
1217 gtk_window_set_accept_focus (window,
1218 g_value_get_boolean (value));
1220 case PROP_FOCUS_ON_MAP:
1221 gtk_window_set_focus_on_map (window,
1222 g_value_get_boolean (value));
1224 case PROP_DECORATED:
1225 gtk_window_set_decorated (window, g_value_get_boolean (value));
1227 case PROP_DELETABLE:
1228 gtk_window_set_deletable (window, g_value_get_boolean (value));
1231 gtk_window_set_gravity (window, g_value_get_enum (value));
1233 case PROP_TRANSIENT_FOR:
1234 gtk_window_set_transient_for (window, g_value_get_object (value));
1237 gtk_window_set_opacity (window, g_value_get_double (value));
1239 case PROP_HAS_RESIZE_GRIP:
1240 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1242 case PROP_APPLICATION:
1243 gtk_window_set_application (window, g_value_get_object (value));
1245 case PROP_MNEMONICS_VISIBLE:
1246 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1249 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1255 gtk_window_get_property (GObject *object,
1260 GtkWindow *window = GTK_WINDOW (object);
1261 GtkWindowPrivate *priv = window->priv;
1265 GtkWindowGeometryInfo *info;
1267 g_value_set_enum (value, priv->type);
1270 g_value_set_string (value, priv->wm_role);
1273 g_value_set_string (value, priv->title);
1275 case PROP_RESIZABLE:
1276 g_value_set_boolean (value, priv->resizable);
1279 g_value_set_boolean (value, priv->modal);
1282 g_value_set_enum (value, priv->position);
1284 case PROP_DEFAULT_WIDTH:
1285 info = gtk_window_get_geometry_info (window, FALSE);
1287 g_value_set_int (value, -1);
1289 g_value_set_int (value, info->default_width);
1291 case PROP_DEFAULT_HEIGHT:
1292 info = gtk_window_get_geometry_info (window, FALSE);
1294 g_value_set_int (value, -1);
1296 g_value_set_int (value, info->default_height);
1298 case PROP_DESTROY_WITH_PARENT:
1299 g_value_set_boolean (value, priv->destroy_with_parent);
1302 g_value_set_object (value, gtk_window_get_icon (window));
1304 case PROP_ICON_NAME:
1305 g_value_set_string (value, gtk_window_get_icon_name (window));
1308 g_value_set_object (value, priv->screen);
1310 case PROP_IS_ACTIVE:
1311 g_value_set_boolean (value, priv->is_active);
1313 case PROP_HAS_TOPLEVEL_FOCUS:
1314 g_value_set_boolean (value, priv->has_toplevel_focus);
1316 case PROP_TYPE_HINT:
1317 g_value_set_enum (value, priv->type_hint);
1319 case PROP_SKIP_TASKBAR_HINT:
1320 g_value_set_boolean (value,
1321 gtk_window_get_skip_taskbar_hint (window));
1323 case PROP_SKIP_PAGER_HINT:
1324 g_value_set_boolean (value,
1325 gtk_window_get_skip_pager_hint (window));
1327 case PROP_URGENCY_HINT:
1328 g_value_set_boolean (value,
1329 gtk_window_get_urgency_hint (window));
1331 case PROP_ACCEPT_FOCUS:
1332 g_value_set_boolean (value,
1333 gtk_window_get_accept_focus (window));
1335 case PROP_FOCUS_ON_MAP:
1336 g_value_set_boolean (value,
1337 gtk_window_get_focus_on_map (window));
1339 case PROP_DECORATED:
1340 g_value_set_boolean (value, gtk_window_get_decorated (window));
1342 case PROP_DELETABLE:
1343 g_value_set_boolean (value, gtk_window_get_deletable (window));
1346 g_value_set_enum (value, gtk_window_get_gravity (window));
1348 case PROP_TRANSIENT_FOR:
1349 g_value_set_object (value, gtk_window_get_transient_for (window));
1352 g_value_set_double (value, gtk_window_get_opacity (window));
1354 case PROP_HAS_RESIZE_GRIP:
1355 g_value_set_boolean (value, priv->has_resize_grip);
1357 case PROP_RESIZE_GRIP_VISIBLE:
1358 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1360 case PROP_APPLICATION:
1361 g_value_set_object (value, gtk_window_get_application (window));
1363 case PROP_MNEMONICS_VISIBLE:
1364 g_value_set_boolean (value, priv->mnemonics_visible);
1367 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1373 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1375 parent_buildable_iface = g_type_interface_peek_parent (iface);
1376 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1377 iface->parser_finished = gtk_window_buildable_parser_finished;
1378 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1379 iface->custom_finished = gtk_window_buildable_custom_finished;
1383 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1384 GtkBuilder *builder,
1386 const GValue *value)
1388 GtkWindow *window = GTK_WINDOW (buildable);
1389 GtkWindowPrivate *priv = window->priv;
1391 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1392 priv->builder_visible = TRUE;
1394 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1398 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1399 GtkBuilder *builder)
1401 GtkWindow *window = GTK_WINDOW (buildable);
1402 GtkWindowPrivate *priv = window->priv;
1406 if (priv->builder_visible)
1407 gtk_widget_show (GTK_WIDGET (buildable));
1409 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1410 for (l = accels; l; l = l->next)
1412 object = gtk_builder_get_object (builder, l->data);
1415 g_warning ("Unknown accel group %s specified in window %s",
1416 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1419 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1420 GTK_ACCEL_GROUP (object));
1424 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1426 parent_buildable_iface->parser_finished (buildable, builder);
1432 } GSListSubParserData;
1435 window_start_element (GMarkupParseContext *context,
1436 const gchar *element_name,
1437 const gchar **names,
1438 const gchar **values,
1443 GSListSubParserData *data = (GSListSubParserData*)user_data;
1445 if (strcmp (element_name, "group") == 0)
1447 for (i = 0; names[i]; i++)
1449 if (strcmp (names[i], "name") == 0)
1450 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1453 else if (strcmp (element_name, "accel-groups") == 0)
1456 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1461 static const GMarkupParser window_parser =
1463 window_start_element
1467 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1468 GtkBuilder *builder,
1470 const gchar *tagname,
1471 GMarkupParser *parser,
1474 GSListSubParserData *parser_data;
1476 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1477 tagname, parser, data))
1480 if (strcmp (tagname, "accel-groups") == 0)
1482 parser_data = g_slice_new0 (GSListSubParserData);
1483 parser_data->items = NULL;
1484 parser_data->object = G_OBJECT (buildable);
1486 *parser = window_parser;
1487 *data = parser_data;
1495 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1496 GtkBuilder *builder,
1498 const gchar *tagname,
1501 GSListSubParserData *data;
1503 parent_buildable_iface->custom_finished (buildable, builder, child,
1504 tagname, user_data);
1506 if (strcmp (tagname, "accel-groups") != 0)
1509 data = (GSListSubParserData*)user_data;
1511 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1512 data->items, (GDestroyNotify) g_slist_free);
1514 g_slice_free (GSListSubParserData, data);
1519 * @type: type of window
1521 * Creates a new #GtkWindow, which is a toplevel window that can
1522 * contain other widgets. Nearly always, the type of the window should
1523 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1524 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1525 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1526 * dialogs, though in some other toolkits dialogs are called "popups".
1527 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1528 * On X11, popup windows are not controlled by the <link
1529 * linkend="gtk-X11-arch">window manager</link>.
1531 * If you simply want an undecorated window (no window borders), use
1532 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1534 * Return value: a new #GtkWindow.
1537 gtk_window_new (GtkWindowType type)
1539 GtkWindowPrivate *priv;
1542 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1544 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1545 priv = window->priv;
1549 return GTK_WIDGET (window);
1553 * gtk_window_set_title:
1554 * @window: a #GtkWindow
1555 * @title: title of the window
1557 * Sets the title of the #GtkWindow. The title of a window will be
1558 * displayed in its title bar; on the X Window System, the title bar
1559 * is rendered by the <link linkend="gtk-X11-arch">window
1560 * manager</link>, so exactly how the title appears to users may vary
1561 * according to a user's exact configuration. The title should help a
1562 * user distinguish this window from other windows they may have
1563 * open. A good title might include the application name and current
1564 * document filename, for example.
1568 gtk_window_set_title (GtkWindow *window,
1571 GtkWindowPrivate *priv;
1575 g_return_if_fail (GTK_IS_WINDOW (window));
1577 priv = window->priv;
1578 widget = GTK_WIDGET (window);
1580 new_title = g_strdup (title);
1581 g_free (priv->title);
1582 priv->title = new_title;
1584 if (gtk_widget_get_realized (widget))
1586 gdk_window_set_title (gtk_widget_get_window (widget),
1589 gtk_decorated_window_set_title (window, title);
1592 g_object_notify (G_OBJECT (window), "title");
1596 * gtk_window_get_title:
1597 * @window: a #GtkWindow
1599 * Retrieves the title of the window. See gtk_window_set_title().
1601 * Return value: the title of the window, or %NULL if none has
1602 * been set explicitely. The returned string is owned by the widget
1603 * and must not be modified or freed.
1605 G_CONST_RETURN gchar *
1606 gtk_window_get_title (GtkWindow *window)
1608 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1610 return window->priv->title;
1614 * gtk_window_set_wmclass:
1615 * @window: a #GtkWindow
1616 * @wmclass_name: window name hint
1617 * @wmclass_class: window class hint
1619 * Don't use this function. It sets the X Window System "class" and
1620 * "name" hints for a window. According to the ICCCM, you should
1621 * always set these to the same value for all windows in an
1622 * application, and GTK+ sets them to that value by default, so calling
1623 * this function is sort of pointless. However, you may want to call
1624 * gtk_window_set_role() on each window in your application, for the
1625 * benefit of the session manager. Setting the role allows the window
1626 * manager to restore window positions when loading a saved session.
1630 gtk_window_set_wmclass (GtkWindow *window,
1631 const gchar *wmclass_name,
1632 const gchar *wmclass_class)
1634 GtkWindowPrivate *priv;
1636 g_return_if_fail (GTK_IS_WINDOW (window));
1638 priv = window->priv;
1640 g_free (priv->wmclass_name);
1641 priv->wmclass_name = g_strdup (wmclass_name);
1643 g_free (priv->wmclass_class);
1644 priv->wmclass_class = g_strdup (wmclass_class);
1646 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1647 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1651 * gtk_window_set_role:
1652 * @window: a #GtkWindow
1653 * @role: unique identifier for the window to be used when restoring a session
1655 * This function is only useful on X11, not with other GTK+ targets.
1657 * In combination with the window title, the window role allows a
1658 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1659 * same" window when an application is restarted. So for example you
1660 * might set the "toolbox" role on your app's toolbox window, so that
1661 * when the user restarts their session, the window manager can put
1662 * the toolbox back in the same place.
1664 * If a window already has a unique title, you don't need to set the
1665 * role, since the WM can use the title to identify the window when
1666 * restoring the session.
1670 gtk_window_set_role (GtkWindow *window,
1673 GtkWindowPrivate *priv;
1676 g_return_if_fail (GTK_IS_WINDOW (window));
1678 priv = window->priv;
1680 new_role = g_strdup (role);
1681 g_free (priv->wm_role);
1682 priv->wm_role = new_role;
1684 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1685 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1688 g_object_notify (G_OBJECT (window), "role");
1692 * gtk_window_set_startup_id:
1693 * @window: a #GtkWindow
1694 * @startup_id: a string with startup-notification identifier
1696 * Startup notification identifiers are used by desktop environment to
1697 * track application startup, to provide user feedback and other
1698 * features. This function changes the corresponding property on the
1699 * underlying GdkWindow. Normally, startup identifier is managed
1700 * automatically and you should only use this function in special cases
1701 * like transferring focus from other processes. You should use this
1702 * function before calling gtk_window_present() or any equivalent
1703 * function generating a window map event.
1705 * This function is only useful on X11, not with other GTK+ targets.
1710 gtk_window_set_startup_id (GtkWindow *window,
1711 const gchar *startup_id)
1713 GtkWindowPrivate *priv;
1716 g_return_if_fail (GTK_IS_WINDOW (window));
1718 priv = window->priv;
1719 widget = GTK_WIDGET (window);
1721 g_free (priv->startup_id);
1722 priv->startup_id = g_strdup (startup_id);
1724 if (gtk_widget_get_realized (widget))
1726 GdkWindow *gdk_window;
1727 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1729 gdk_window = gtk_widget_get_window (widget);
1731 #ifdef GDK_WINDOWING_X11
1732 if (timestamp != GDK_CURRENT_TIME)
1733 gdk_x11_window_set_user_time (gdk_window, timestamp);
1736 /* Here we differentiate real and "fake" startup notification IDs,
1737 * constructed on purpose just to pass interaction timestamp
1739 if (startup_id_is_fake (priv->startup_id))
1740 gtk_window_present_with_time (window, timestamp);
1743 gdk_window_set_startup_id (gdk_window,
1746 /* If window is mapped, terminate the startup-notification too */
1747 if (gtk_widget_get_mapped (widget) &&
1748 !disable_startup_notification)
1749 gdk_notify_startup_complete_with_id (priv->startup_id);
1753 g_object_notify (G_OBJECT (window), "startup-id");
1757 * gtk_window_get_role:
1758 * @window: a #GtkWindow
1760 * Returns the role of the window. See gtk_window_set_role() for
1761 * further explanation.
1763 * Return value: the role of the window if set, or %NULL. The
1764 * returned is owned by the widget and must not be modified
1767 G_CONST_RETURN gchar *
1768 gtk_window_get_role (GtkWindow *window)
1770 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1772 return window->priv->wm_role;
1776 * gtk_window_set_focus:
1777 * @window: a #GtkWindow
1778 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1779 * any focus widget for the toplevel window.
1781 * If @focus is not the current focus widget, and is focusable, sets
1782 * it as the focus widget for the window. If @focus is %NULL, unsets
1783 * the focus widget for this window. To set the focus to a particular
1784 * widget in the toplevel, it is usually more convenient to use
1785 * gtk_widget_grab_focus() instead of this function.
1788 gtk_window_set_focus (GtkWindow *window,
1791 GtkWindowPrivate *priv;
1794 g_return_if_fail (GTK_IS_WINDOW (window));
1796 priv = window->priv;
1800 g_return_if_fail (GTK_IS_WIDGET (focus));
1801 g_return_if_fail (gtk_widget_get_can_focus (focus));
1805 gtk_widget_grab_focus (focus);
1808 /* Clear the existing focus chain, so that when we focus into
1809 * the window again, we start at the beginnning.
1811 GtkWidget *widget = priv->focus_widget;
1814 while ((parent = gtk_widget_get_parent (widget)))
1817 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1821 _gtk_window_internal_set_focus (window, NULL);
1826 _gtk_window_internal_set_focus (GtkWindow *window,
1829 GtkWindowPrivate *priv;
1831 g_return_if_fail (GTK_IS_WINDOW (window));
1833 priv = window->priv;
1835 if ((priv->focus_widget != focus) ||
1836 (focus && !gtk_widget_has_focus (focus)))
1837 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1841 * gtk_window_set_default:
1842 * @window: a #GtkWindow
1843 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1844 * default widget for the toplevel.
1846 * The default widget is the widget that's activated when the user
1847 * presses Enter in a dialog (for example). This function sets or
1848 * unsets the default widget for a #GtkWindow about. When setting
1849 * (rather than unsetting) the default widget it's generally easier to
1850 * call gtk_widget_grab_focus() on the widget. Before making a widget
1851 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1852 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1855 gtk_window_set_default (GtkWindow *window,
1856 GtkWidget *default_widget)
1858 GtkWindowPrivate *priv;
1860 g_return_if_fail (GTK_IS_WINDOW (window));
1862 priv = window->priv;
1865 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1867 if (priv->default_widget != default_widget)
1869 GtkWidget *old_default_widget = NULL;
1872 g_object_ref (default_widget);
1874 if (priv->default_widget)
1876 old_default_widget = priv->default_widget;
1878 if (priv->focus_widget != priv->default_widget ||
1879 !gtk_widget_get_receives_default (priv->default_widget))
1880 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1882 gtk_widget_queue_draw (priv->default_widget);
1885 priv->default_widget = default_widget;
1887 if (priv->default_widget)
1889 if (priv->focus_widget == NULL ||
1890 !gtk_widget_get_receives_default (priv->focus_widget))
1891 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1893 gtk_widget_queue_draw (priv->default_widget);
1896 if (old_default_widget)
1897 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1901 g_object_notify (G_OBJECT (default_widget), "has-default");
1902 g_object_unref (default_widget);
1908 * gtk_window_get_default_widget:
1909 * @window: a #GtkWindow
1911 * Returns the default widget for @window. See gtk_window_set_default()
1914 * Returns: (transfer none): the default widget, or %NULL if there is none.
1919 gtk_window_get_default_widget (GtkWindow *window)
1921 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1923 return window->priv->default_widget;
1927 handle_keys_changed (gpointer data)
1929 GtkWindow *window = GTK_WINDOW (data);
1930 GtkWindowPrivate *priv = window->priv;
1932 if (priv->keys_changed_handler)
1934 g_source_remove (priv->keys_changed_handler);
1935 priv->keys_changed_handler = 0;
1938 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1944 gtk_window_notify_keys_changed (GtkWindow *window)
1946 GtkWindowPrivate *priv = window->priv;
1948 if (!priv->keys_changed_handler)
1949 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1953 * gtk_window_add_accel_group:
1954 * @window: window to attach accelerator group to
1955 * @accel_group: a #GtkAccelGroup
1957 * Associate @accel_group with @window, such that calling
1958 * gtk_accel_groups_activate() on @window will activate accelerators
1962 gtk_window_add_accel_group (GtkWindow *window,
1963 GtkAccelGroup *accel_group)
1965 g_return_if_fail (GTK_IS_WINDOW (window));
1966 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1968 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1969 g_signal_connect_object (accel_group, "accel-changed",
1970 G_CALLBACK (gtk_window_notify_keys_changed),
1971 window, G_CONNECT_SWAPPED);
1972 gtk_window_notify_keys_changed (window);
1976 * gtk_window_remove_accel_group:
1977 * @window: a #GtkWindow
1978 * @accel_group: a #GtkAccelGroup
1980 * Reverses the effects of gtk_window_add_accel_group().
1983 gtk_window_remove_accel_group (GtkWindow *window,
1984 GtkAccelGroup *accel_group)
1986 g_return_if_fail (GTK_IS_WINDOW (window));
1987 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1989 g_signal_handlers_disconnect_by_func (accel_group,
1990 gtk_window_notify_keys_changed,
1992 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1993 gtk_window_notify_keys_changed (window);
1996 static GtkMnemonicHash *
1997 gtk_window_get_mnemonic_hash (GtkWindow *window,
2000 GtkWindowPrivate *private = window->priv;
2002 if (!private->mnemonic_hash && create)
2003 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
2005 return private->mnemonic_hash;
2009 * gtk_window_add_mnemonic:
2010 * @window: a #GtkWindow
2011 * @keyval: the mnemonic
2012 * @target: the widget that gets activated by the mnemonic
2014 * Adds a mnemonic to this window.
2017 gtk_window_add_mnemonic (GtkWindow *window,
2021 g_return_if_fail (GTK_IS_WINDOW (window));
2022 g_return_if_fail (GTK_IS_WIDGET (target));
2024 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
2026 gtk_window_notify_keys_changed (window);
2030 * gtk_window_remove_mnemonic:
2031 * @window: a #GtkWindow
2032 * @keyval: the mnemonic
2033 * @target: the widget that gets activated by the mnemonic
2035 * Removes a mnemonic from this window.
2038 gtk_window_remove_mnemonic (GtkWindow *window,
2042 g_return_if_fail (GTK_IS_WINDOW (window));
2043 g_return_if_fail (GTK_IS_WIDGET (target));
2045 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2047 gtk_window_notify_keys_changed (window);
2051 * gtk_window_mnemonic_activate:
2052 * @window: a #GtkWindow
2053 * @keyval: the mnemonic
2054 * @modifier: the modifiers
2055 * @returns: %TRUE if the activation is done.
2057 * Activates the targets associated with the mnemonic.
2060 gtk_window_mnemonic_activate (GtkWindow *window,
2062 GdkModifierType modifier)
2064 GtkWindowPrivate *priv;
2066 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2068 priv = window->priv;
2070 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2072 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2074 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2081 * gtk_window_set_mnemonic_modifier:
2082 * @window: a #GtkWindow
2083 * @modifier: the modifier mask used to activate
2084 * mnemonics on this window.
2086 * Sets the mnemonic modifier for this window.
2089 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2090 GdkModifierType modifier)
2092 GtkWindowPrivate *priv;
2094 g_return_if_fail (GTK_IS_WINDOW (window));
2095 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2097 priv = window->priv;
2099 priv->mnemonic_modifier = modifier;
2100 gtk_window_notify_keys_changed (window);
2104 * gtk_window_get_mnemonic_modifier:
2105 * @window: a #GtkWindow
2107 * Returns the mnemonic modifier for this window. See
2108 * gtk_window_set_mnemonic_modifier().
2110 * Return value: the modifier mask used to activate
2111 * mnemonics on this window.
2114 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2116 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2118 return window->priv->mnemonic_modifier;
2122 * gtk_window_set_position:
2123 * @window: a #GtkWindow.
2124 * @position: a position constraint.
2126 * Sets a position constraint for this window. If the old or new
2127 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2128 * the window to be repositioned to satisfy the new constraint.
2131 gtk_window_set_position (GtkWindow *window,
2132 GtkWindowPosition position)
2134 GtkWindowPrivate *priv;
2136 g_return_if_fail (GTK_IS_WINDOW (window));
2138 priv = window->priv;
2140 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2141 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2143 GtkWindowGeometryInfo *info;
2145 info = gtk_window_get_geometry_info (window, TRUE);
2147 /* this flag causes us to re-request the CENTER_ALWAYS
2148 * constraint in gtk_window_move_resize(), see
2149 * comment in that function.
2151 info->position_constraints_changed = TRUE;
2153 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2156 priv->position = position;
2158 g_object_notify (G_OBJECT (window), "window-position");
2162 * gtk_window_activate_focus:
2163 * @window: a #GtkWindow
2165 * Activates the current focused widget within the window.
2167 * Return value: %TRUE if a widget got activated.
2170 gtk_window_activate_focus (GtkWindow *window)
2172 GtkWindowPrivate *priv;
2174 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2176 priv = window->priv;
2178 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2179 return gtk_widget_activate (priv->focus_widget);
2185 * gtk_window_get_focus:
2186 * @window: a #GtkWindow
2188 * Retrieves the current focused widget within the window.
2189 * Note that this is the widget that would have the focus
2190 * if the toplevel window focused; if the toplevel window
2191 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2192 * not be %TRUE for the widget.
2194 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2197 gtk_window_get_focus (GtkWindow *window)
2199 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2201 return window->priv->focus_widget;
2205 * gtk_window_activate_default:
2206 * @window: a #GtkWindow
2208 * Activates the default widget for the window, unless the current
2209 * focused widget has been configured to receive the default action
2210 * (see gtk_widget_set_receives_default()), in which case the
2211 * focused widget is activated.
2213 * Return value: %TRUE if a widget got activated.
2216 gtk_window_activate_default (GtkWindow *window)
2218 GtkWindowPrivate *priv;
2220 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2222 priv = window->priv;
2224 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2225 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2226 return gtk_widget_activate (priv->default_widget);
2227 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2228 return gtk_widget_activate (priv->focus_widget);
2234 * gtk_window_set_modal:
2235 * @window: a #GtkWindow
2236 * @modal: whether the window is modal
2238 * Sets a window modal or non-modal. Modal windows prevent interaction
2239 * with other windows in the same application. To keep modal dialogs
2240 * on top of main application windows, use
2241 * gtk_window_set_transient_for() to make the dialog transient for the
2242 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2243 * will then disallow lowering the dialog below the parent.
2248 gtk_window_set_modal (GtkWindow *window,
2251 GtkWindowPrivate *priv;
2254 g_return_if_fail (GTK_IS_WINDOW (window));
2256 priv = window->priv;
2258 modal = modal != FALSE;
2259 if (priv->modal == modal)
2262 priv->modal = modal;
2263 widget = GTK_WIDGET (window);
2265 /* adjust desired modality state */
2266 if (gtk_widget_get_realized (widget))
2269 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2271 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2274 if (gtk_widget_get_visible (widget))
2277 gtk_grab_add (widget);
2279 gtk_grab_remove (widget);
2282 g_object_notify (G_OBJECT (window), "modal");
2286 * gtk_window_get_modal:
2287 * @window: a #GtkWindow
2289 * Returns whether the window is modal. See gtk_window_set_modal().
2291 * Return value: %TRUE if the window is set to be modal and
2292 * establishes a grab when shown
2295 gtk_window_get_modal (GtkWindow *window)
2297 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2299 return window->priv->modal;
2303 * gtk_window_list_toplevels:
2305 * Returns a list of all existing toplevel windows. The widgets
2306 * in the list are not individually referenced. If you want
2307 * to iterate through the list and perform actions involving
2308 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2309 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2310 * then unref all the widgets afterwards.
2312 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2315 gtk_window_list_toplevels (void)
2320 for (slist = toplevel_list; slist; slist = slist->next)
2321 list = g_list_prepend (list, slist->data);
2327 gtk_window_add_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2329 GList *embedded_windows;
2331 g_return_if_fail (GTK_IS_WINDOW (window));
2333 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2334 if (embedded_windows)
2335 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2336 embedded_windows = g_list_prepend (embedded_windows,
2337 GUINT_TO_POINTER (xid));
2339 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2342 (GDestroyNotify) g_list_free : NULL);
2346 gtk_window_remove_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2348 GList *embedded_windows;
2351 g_return_if_fail (GTK_IS_WINDOW (window));
2353 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2354 if (embedded_windows)
2355 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2357 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
2360 embedded_windows = g_list_remove_link (embedded_windows, node);
2361 g_list_free_1 (node);
2364 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2367 (GDestroyNotify) g_list_free : NULL);
2371 gtk_window_dispose (GObject *object)
2373 GtkWindow *window = GTK_WINDOW (object);
2375 gtk_window_set_focus (window, NULL);
2376 gtk_window_set_default (window, NULL);
2378 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2382 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2384 gtk_widget_destroy (GTK_WIDGET (child));
2388 connect_parent_destroyed (GtkWindow *window)
2390 GtkWindowPrivate *priv = window->priv;
2392 if (priv->transient_parent)
2394 g_signal_connect (priv->transient_parent,
2396 G_CALLBACK (parent_destroyed_callback),
2402 disconnect_parent_destroyed (GtkWindow *window)
2404 GtkWindowPrivate *priv = window->priv;
2406 if (priv->transient_parent)
2408 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2409 parent_destroyed_callback,
2415 gtk_window_transient_parent_realized (GtkWidget *parent,
2418 if (gtk_widget_get_realized (window))
2419 gdk_window_set_transient_for (gtk_widget_get_window (window),
2420 gtk_widget_get_window (parent));
2424 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2427 if (gtk_widget_get_realized (window))
2428 gdk_property_delete (gtk_widget_get_window (window),
2429 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2433 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2437 gtk_window_set_screen (window, parent->priv->screen);
2441 gtk_window_unset_transient_for (GtkWindow *window)
2443 GtkWindowPrivate *priv = window->priv;
2445 if (priv->transient_parent)
2447 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2448 gtk_window_transient_parent_realized,
2450 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2451 gtk_window_transient_parent_unrealized,
2453 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2454 gtk_window_transient_parent_screen_changed,
2456 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2457 gtk_widget_destroyed,
2458 &priv->transient_parent);
2460 if (priv->destroy_with_parent)
2461 disconnect_parent_destroyed (window);
2463 priv->transient_parent = NULL;
2465 if (priv->transient_parent_group)
2467 priv->transient_parent_group = FALSE;
2468 gtk_window_group_remove_window (priv->group,
2475 * gtk_window_set_transient_for:
2476 * @window: a #GtkWindow
2477 * @parent: (allow-none): parent window, or %NULL
2479 * Dialog windows should be set transient for the main application
2480 * window they were spawned from. This allows <link
2481 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2482 * dialog on top of the main window, or center the dialog over the
2483 * main window. gtk_dialog_new_with_buttons() and other convenience
2484 * functions in GTK+ will sometimes call
2485 * gtk_window_set_transient_for() on your behalf.
2487 * Passing %NULL for @parent unsets the current transient window.
2489 * On Windows, this function puts the child window on top of the parent,
2490 * much as the window manager would have done on X.
2493 gtk_window_set_transient_for (GtkWindow *window,
2496 GtkWindowPrivate *priv;
2498 g_return_if_fail (GTK_IS_WINDOW (window));
2499 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2500 g_return_if_fail (window != parent);
2502 priv = window->priv;
2504 if (priv->transient_parent)
2506 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2507 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2508 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2509 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2510 GTK_WIDGET (window));
2512 gtk_window_unset_transient_for (window);
2515 priv->transient_parent = parent;
2519 g_signal_connect (parent, "destroy",
2520 G_CALLBACK (gtk_widget_destroyed),
2521 &priv->transient_parent);
2522 g_signal_connect (parent, "realize",
2523 G_CALLBACK (gtk_window_transient_parent_realized),
2525 g_signal_connect (parent, "unrealize",
2526 G_CALLBACK (gtk_window_transient_parent_unrealized),
2528 g_signal_connect (parent, "notify::screen",
2529 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2532 gtk_window_set_screen (window, parent->priv->screen);
2534 if (priv->destroy_with_parent)
2535 connect_parent_destroyed (window);
2537 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2538 gtk_widget_get_realized (GTK_WIDGET (parent)))
2539 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2540 GTK_WIDGET (window));
2542 if (parent->priv->group)
2544 gtk_window_group_add_window (parent->priv->group, window);
2545 priv->transient_parent_group = TRUE;
2551 * gtk_window_get_transient_for:
2552 * @window: a #GtkWindow
2554 * Fetches the transient parent for this window. See
2555 * gtk_window_set_transient_for().
2557 * Return value: (transfer none): the transient parent for this window, or %NULL
2558 * if no transient parent has been set.
2561 gtk_window_get_transient_for (GtkWindow *window)
2563 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2565 return window->priv->transient_parent;
2569 * gtk_window_set_opacity:
2570 * @window: a #GtkWindow
2571 * @opacity: desired opacity, between 0 and 1
2573 * Request the windowing system to make @window partially transparent,
2574 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2575 * of the opacity parameter are clamped to the [0,1] range.) On X11
2576 * this has any effect only on X screens with a compositing manager
2577 * running. See gtk_widget_is_composited(). On Windows it should work
2580 * Note that setting a window's opacity after the window has been
2581 * shown causes it to flicker once on Windows.
2586 gtk_window_set_opacity (GtkWindow *window,
2589 GtkWindowPrivate *priv;
2591 g_return_if_fail (GTK_IS_WINDOW (window));
2593 priv = window->priv;
2597 else if (opacity > 1.0)
2600 priv->opacity_set = TRUE;
2601 priv->opacity = opacity;
2603 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2604 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2609 * gtk_window_get_opacity:
2610 * @window: a #GtkWindow
2612 * Fetches the requested opacity for this window. See
2613 * gtk_window_set_opacity().
2615 * Return value: the requested opacity for this window.
2620 gtk_window_get_opacity (GtkWindow *window)
2622 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2624 return window->priv->opacity;
2628 * gtk_window_get_application:
2629 * @window: a #GtkWindow
2631 * Gets the #GtkApplication associated with the window (if any).
2633 * Return value: a #GtkApplication, or %NULL
2638 gtk_window_get_application (GtkWindow *window)
2640 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2642 return window->priv->application;
2646 gtk_window_release_application (GtkWindow *window)
2648 if (window->priv->application)
2650 GtkApplication *application;
2652 /* steal reference into temp variable */
2653 application = window->priv->application;
2654 window->priv->application = NULL;
2656 gtk_application_remove_window (application, window);
2657 g_object_unref (application);
2662 * gtk_window_set_application:
2663 * @window: a #GtkWindow
2664 * @application: a #GtkApplication, or %NULL
2666 * Sets or unsets the #GtkApplication associated with the window.
2668 * The application will be kept alive for at least as long as the window
2674 gtk_window_set_application (GtkWindow *window,
2675 GtkApplication *application)
2677 GtkWindowPrivate *priv;
2679 g_return_if_fail (GTK_IS_WINDOW (window));
2681 priv = window->priv;
2682 if (priv->application != application)
2684 gtk_window_release_application (window);
2686 priv->application = application;
2688 if (priv->application != NULL)
2690 g_object_ref (priv->application);
2692 gtk_application_add_window (priv->application, window);
2695 g_object_notify (G_OBJECT (window), "application");
2700 * gtk_window_set_type_hint:
2701 * @window: a #GtkWindow
2702 * @hint: the window type
2704 * By setting the type hint for the window, you allow the window
2705 * manager to decorate and handle the window in a way which is
2706 * suitable to the function of the window in your application.
2708 * This function should be called before the window becomes visible.
2710 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2711 * will sometimes call gtk_window_set_type_hint() on your behalf.
2715 gtk_window_set_type_hint (GtkWindow *window,
2716 GdkWindowTypeHint hint)
2718 GtkWindowPrivate *priv;
2720 g_return_if_fail (GTK_IS_WINDOW (window));
2721 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2723 priv = window->priv;
2725 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2726 priv->gdk_type_hint = hint;
2728 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2730 priv->reset_type_hint = TRUE;
2731 priv->type_hint = hint;
2735 * gtk_window_get_type_hint:
2736 * @window: a #GtkWindow
2738 * Gets the type hint for this window. See gtk_window_set_type_hint().
2740 * Return value: the type hint for @window.
2743 gtk_window_get_type_hint (GtkWindow *window)
2745 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2747 return window->priv->type_hint;
2751 * gtk_window_set_skip_taskbar_hint:
2752 * @window: a #GtkWindow
2753 * @setting: %TRUE to keep this window from appearing in the task bar
2755 * Windows may set a hint asking the desktop environment not to display
2756 * the window in the task bar. This function sets this hint.
2761 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2764 GtkWindowPrivate *priv;
2766 g_return_if_fail (GTK_IS_WINDOW (window));
2768 priv = window->priv;
2770 setting = setting != FALSE;
2772 if (priv->skips_taskbar != setting)
2774 priv->skips_taskbar = setting;
2775 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2776 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2777 priv->skips_taskbar);
2778 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2783 * gtk_window_get_skip_taskbar_hint:
2784 * @window: a #GtkWindow
2786 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2788 * Return value: %TRUE if window shouldn't be in taskbar
2793 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2795 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2797 return window->priv->skips_taskbar;
2801 * gtk_window_set_skip_pager_hint:
2802 * @window: a #GtkWindow
2803 * @setting: %TRUE to keep this window from appearing in the pager
2805 * Windows may set a hint asking the desktop environment not to display
2806 * the window in the pager. This function sets this hint.
2807 * (A "pager" is any desktop navigation tool such as a workspace
2808 * switcher that displays a thumbnail representation of the windows
2814 gtk_window_set_skip_pager_hint (GtkWindow *window,
2817 GtkWindowPrivate *priv;
2819 g_return_if_fail (GTK_IS_WINDOW (window));
2821 priv = window->priv;
2823 setting = setting != FALSE;
2825 if (priv->skips_pager != setting)
2827 priv->skips_pager = setting;
2828 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2829 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2831 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2836 * gtk_window_get_skip_pager_hint:
2837 * @window: a #GtkWindow
2839 * Gets the value set by gtk_window_set_skip_pager_hint().
2841 * Return value: %TRUE if window shouldn't be in pager
2846 gtk_window_get_skip_pager_hint (GtkWindow *window)
2848 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2850 return window->priv->skips_pager;
2854 * gtk_window_set_urgency_hint:
2855 * @window: a #GtkWindow
2856 * @setting: %TRUE to mark this window as urgent
2858 * Windows may set a hint asking the desktop environment to draw
2859 * the users attention to the window. This function sets this hint.
2864 gtk_window_set_urgency_hint (GtkWindow *window,
2867 GtkWindowPrivate *priv;
2869 g_return_if_fail (GTK_IS_WINDOW (window));
2871 priv = window->priv;
2873 setting = setting != FALSE;
2875 if (priv->urgent != setting)
2877 priv->urgent = setting;
2878 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2879 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2881 g_object_notify (G_OBJECT (window), "urgency-hint");
2886 * gtk_window_get_urgency_hint:
2887 * @window: a #GtkWindow
2889 * Gets the value set by gtk_window_set_urgency_hint()
2891 * Return value: %TRUE if window is urgent
2896 gtk_window_get_urgency_hint (GtkWindow *window)
2898 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2900 return window->priv->urgent;
2904 * gtk_window_set_accept_focus:
2905 * @window: a #GtkWindow
2906 * @setting: %TRUE to let this window receive input focus
2908 * Windows may set a hint asking the desktop environment not to receive
2909 * the input focus. This function sets this hint.
2914 gtk_window_set_accept_focus (GtkWindow *window,
2917 GtkWindowPrivate *priv;
2919 g_return_if_fail (GTK_IS_WINDOW (window));
2921 priv = window->priv;
2923 setting = setting != FALSE;
2925 if (priv->accept_focus != setting)
2927 priv->accept_focus = setting;
2928 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2929 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2930 priv->accept_focus);
2931 g_object_notify (G_OBJECT (window), "accept-focus");
2936 * gtk_window_get_accept_focus:
2937 * @window: a #GtkWindow
2939 * Gets the value set by gtk_window_set_accept_focus().
2941 * Return value: %TRUE if window should receive the input focus
2946 gtk_window_get_accept_focus (GtkWindow *window)
2948 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2950 return window->priv->accept_focus;
2954 * gtk_window_set_focus_on_map:
2955 * @window: a #GtkWindow
2956 * @setting: %TRUE to let this window receive input focus on map
2958 * Windows may set a hint asking the desktop environment not to receive
2959 * the input focus when the window is mapped. This function sets this
2965 gtk_window_set_focus_on_map (GtkWindow *window,
2968 GtkWindowPrivate *priv;
2970 g_return_if_fail (GTK_IS_WINDOW (window));
2972 priv = window->priv;
2974 setting = setting != FALSE;
2976 if (priv->focus_on_map != setting)
2978 priv->focus_on_map = setting;
2979 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2980 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2981 priv->focus_on_map);
2982 g_object_notify (G_OBJECT (window), "focus-on-map");
2987 * gtk_window_get_focus_on_map:
2988 * @window: a #GtkWindow
2990 * Gets the value set by gtk_window_set_focus_on_map().
2992 * Return value: %TRUE if window should receive the input focus when
2998 gtk_window_get_focus_on_map (GtkWindow *window)
3000 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3002 return window->priv->focus_on_map;
3006 * gtk_window_set_destroy_with_parent:
3007 * @window: a #GtkWindow
3008 * @setting: whether to destroy @window with its transient parent
3010 * If @setting is %TRUE, then destroying the transient parent of @window
3011 * will also destroy @window itself. This is useful for dialogs that
3012 * shouldn't persist beyond the lifetime of the main window they're
3013 * associated with, for example.
3016 gtk_window_set_destroy_with_parent (GtkWindow *window,
3019 GtkWindowPrivate *priv;
3021 g_return_if_fail (GTK_IS_WINDOW (window));
3023 priv = window->priv;
3025 if (priv->destroy_with_parent == (setting != FALSE))
3028 if (priv->destroy_with_parent)
3030 disconnect_parent_destroyed (window);
3034 connect_parent_destroyed (window);
3037 priv->destroy_with_parent = setting;
3039 g_object_notify (G_OBJECT (window), "destroy-with-parent");
3043 * gtk_window_get_destroy_with_parent:
3044 * @window: a #GtkWindow
3046 * Returns whether the window will be destroyed with its transient parent. See
3047 * gtk_window_set_destroy_with_parent ().
3049 * Return value: %TRUE if the window will be destroyed with its transient parent.
3052 gtk_window_get_destroy_with_parent (GtkWindow *window)
3054 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3056 return window->priv->destroy_with_parent;
3059 static GtkWindowGeometryInfo*
3060 gtk_window_get_geometry_info (GtkWindow *window,
3063 GtkWindowPrivate *priv = window->priv;
3064 GtkWindowGeometryInfo *info;
3066 info = priv->geometry_info;
3067 if (!info && create)
3069 info = g_new0 (GtkWindowGeometryInfo, 1);
3071 info->default_width = -1;
3072 info->default_height = -1;
3073 info->resize_width = -1;
3074 info->resize_height = -1;
3075 info->initial_x = 0;
3076 info->initial_y = 0;
3077 info->initial_pos_set = FALSE;
3078 info->default_is_geometry = FALSE;
3079 info->position_constraints_changed = FALSE;
3080 info->last.configure_request.x = 0;
3081 info->last.configure_request.y = 0;
3082 info->last.configure_request.width = -1;
3083 info->last.configure_request.height = -1;
3084 info->widget = NULL;
3086 priv->geometry_info = info;
3093 * gtk_window_set_geometry_hints:
3094 * @window: a #GtkWindow
3095 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3096 * @geometry: (allow-none): struct containing geometry information or %NULL
3097 * @geom_mask: mask indicating which struct fields should be paid attention to
3099 * This function sets up hints about how a window can be resized by
3100 * the user. You can set a minimum and maximum size; allowed resize
3101 * increments (e.g. for xterm, you can only resize by the size of a
3102 * character); aspect ratios; and more. See the #GdkGeometry struct.
3106 gtk_window_set_geometry_hints (GtkWindow *window,
3107 GtkWidget *geometry_widget,
3108 GdkGeometry *geometry,
3109 GdkWindowHints geom_mask)
3111 GtkWindowGeometryInfo *info;
3113 g_return_if_fail (GTK_IS_WINDOW (window));
3114 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3116 info = gtk_window_get_geometry_info (window, TRUE);
3119 g_signal_handlers_disconnect_by_func (info->widget,
3120 gtk_widget_destroyed,
3123 info->widget = geometry_widget;
3125 g_signal_connect (geometry_widget, "destroy",
3126 G_CALLBACK (gtk_widget_destroyed),
3130 info->geometry = *geometry;
3132 /* We store gravity in priv->gravity not in the hints. */
3133 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3135 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3137 gtk_window_set_gravity (window, geometry->win_gravity);
3140 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3144 * gtk_window_set_decorated:
3145 * @window: a #GtkWindow
3146 * @setting: %TRUE to decorate the window
3148 * By default, windows are decorated with a title bar, resize
3149 * controls, etc. Some <link linkend="gtk-X11-arch">window
3150 * managers</link> allow GTK+ to disable these decorations, creating a
3151 * borderless window. If you set the decorated property to %FALSE
3152 * using this function, GTK+ will do its best to convince the window
3153 * manager not to decorate the window. Depending on the system, this
3154 * function may not have any effect when called on a window that is
3155 * already visible, so you should call it before calling gtk_window_show().
3157 * On Windows, this function always works, since there's no window manager
3162 gtk_window_set_decorated (GtkWindow *window,
3165 GtkWindowPrivate *priv;
3166 GdkWindow *gdk_window;
3168 g_return_if_fail (GTK_IS_WINDOW (window));
3170 priv = window->priv;
3172 setting = setting != FALSE;
3174 if (setting == priv->decorated)
3177 priv->decorated = setting;
3179 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3182 if (priv->decorated)
3183 gdk_window_set_decorations (gdk_window,
3186 gdk_window_set_decorations (gdk_window,
3190 g_object_notify (G_OBJECT (window), "decorated");
3194 * gtk_window_get_decorated:
3195 * @window: a #GtkWindow
3197 * Returns whether the window has been set to have decorations
3198 * such as a title bar via gtk_window_set_decorated().
3200 * Return value: %TRUE if the window has been set to have decorations
3203 gtk_window_get_decorated (GtkWindow *window)
3205 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3207 return window->priv->decorated;
3211 * gtk_window_set_deletable:
3212 * @window: a #GtkWindow
3213 * @setting: %TRUE to decorate the window as deletable
3215 * By default, windows have a close button in the window frame. Some
3216 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3217 * disable this button. If you set the deletable property to %FALSE
3218 * using this function, GTK+ will do its best to convince the window
3219 * manager not to show a close button. Depending on the system, this
3220 * function may not have any effect when called on a window that is
3221 * already visible, so you should call it before calling gtk_window_show().
3223 * On Windows, this function always works, since there's no window manager
3229 gtk_window_set_deletable (GtkWindow *window,
3232 GtkWindowPrivate *priv;
3233 GdkWindow *gdk_window;
3235 g_return_if_fail (GTK_IS_WINDOW (window));
3237 priv = window->priv;
3239 setting = setting != FALSE;
3241 if (setting == priv->deletable)
3244 priv->deletable = setting;
3246 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3249 if (priv->deletable)
3250 gdk_window_set_functions (gdk_window,
3253 gdk_window_set_functions (gdk_window,
3254 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3257 g_object_notify (G_OBJECT (window), "deletable");
3261 * gtk_window_get_deletable:
3262 * @window: a #GtkWindow
3264 * Returns whether the window has been set to have a close button
3265 * via gtk_window_set_deletable().
3267 * Return value: %TRUE if the window has been set to have a close button
3272 gtk_window_get_deletable (GtkWindow *window)
3274 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3276 return window->priv->deletable;
3279 static GtkWindowIconInfo*
3280 get_icon_info (GtkWindow *window)
3282 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3286 free_icon_info (GtkWindowIconInfo *info)
3288 g_free (info->icon_name);
3289 g_slice_free (GtkWindowIconInfo, info);
3293 static GtkWindowIconInfo*
3294 ensure_icon_info (GtkWindow *window)
3296 GtkWindowIconInfo *info;
3298 info = get_icon_info (window);
3302 info = g_slice_new0 (GtkWindowIconInfo);
3303 g_object_set_qdata_full (G_OBJECT (window),
3304 quark_gtk_window_icon_info,
3306 (GDestroyNotify)free_icon_info);
3313 icon_list_from_theme (GtkWidget *widget,
3318 GtkIconTheme *icon_theme;
3323 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3325 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3328 for (i = 0; sizes[i]; i++)
3331 * We need an EWMH extension to handle scalable icons
3332 * by passing their name to the WM. For now just use a
3336 icon = gtk_icon_theme_load_icon (icon_theme, name,
3339 icon = gtk_icon_theme_load_icon (icon_theme, name,
3342 list = g_list_append (list, icon);
3352 gtk_window_realize_icon (GtkWindow *window)
3354 GtkWindowPrivate *priv = window->priv;
3356 GtkWindowIconInfo *info;
3357 GdkWindow *gdk_window;
3360 widget = GTK_WIDGET (window);
3361 gdk_window = gtk_widget_get_window (widget);
3363 g_return_if_fail (gdk_window != NULL);
3365 /* no point setting an icon on override-redirect */
3366 if (priv->type == GTK_WINDOW_POPUP)
3371 info = ensure_icon_info (window);
3376 info->using_default_icon = FALSE;
3377 info->using_parent_icon = FALSE;
3378 info->using_themed_icon = FALSE;
3380 icon_list = info->icon_list;
3382 /* Look up themed icon */
3383 if (icon_list == NULL && info->icon_name)
3385 icon_list = icon_list_from_theme (widget, info->icon_name);
3387 info->using_themed_icon = TRUE;
3390 /* Inherit from transient parent */
3391 if (icon_list == NULL && priv->transient_parent)
3393 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3395 info->using_parent_icon = TRUE;
3398 /* Inherit from default */
3399 if (icon_list == NULL)
3401 icon_list = default_icon_list;
3403 info->using_default_icon = TRUE;
3406 /* Look up themed icon */
3407 if (icon_list == NULL && default_icon_name)
3409 icon_list = icon_list_from_theme (widget, default_icon_name);
3410 info->using_default_icon = TRUE;
3411 info->using_themed_icon = TRUE;
3414 info->realized = TRUE;
3416 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3418 if (info->using_themed_icon)
3420 GtkIconTheme *icon_theme;
3422 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3423 g_list_free (icon_list);
3425 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3426 g_signal_connect (icon_theme, "changed",
3427 G_CALLBACK (update_themed_icon), window);
3432 gtk_window_unrealize_icon (GtkWindow *window)
3434 GtkWindowIconInfo *info;
3436 info = get_icon_info (window);
3441 if (info->using_themed_icon)
3443 GtkIconTheme *icon_theme;
3445 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3447 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3450 /* We don't clear the properties on the window, just figure the
3451 * window is going away.
3454 info->realized = FALSE;
3459 * gtk_window_set_icon_list:
3460 * @window: a #GtkWindow
3461 * @list: (element-type GdkPixbuf) (transfer container): list of #GdkPixbuf
3463 * Sets up the icon representing a #GtkWindow. The icon is used when
3464 * the window is minimized (also known as iconified). Some window
3465 * managers or desktop environments may also place it in the window
3466 * frame, or display it in other contexts.
3468 * gtk_window_set_icon_list() allows you to pass in the same icon in
3469 * several hand-drawn sizes. The list should contain the natural sizes
3470 * your icon is available in; that is, don't scale the image before
3471 * passing it to GTK+. Scaling is postponed until the last minute,
3472 * when the desired final size is known, to allow best quality.
3474 * By passing several sizes, you may improve the final image quality
3475 * of the icon, by reducing or eliminating automatic image scaling.
3477 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3478 * larger images (64x64, 128x128) if you have them.
3480 * See also gtk_window_set_default_icon_list() to set the icon
3481 * for all windows in your application in one go.
3483 * Note that transient windows (those who have been set transient for another
3484 * window using gtk_window_set_transient_for()) will inherit their
3485 * icon from their transient parent. So there's no need to explicitly
3486 * set the icon on transient windows.
3489 gtk_window_set_icon_list (GtkWindow *window,
3492 GtkWindowIconInfo *info;
3494 g_return_if_fail (GTK_IS_WINDOW (window));
3496 info = ensure_icon_info (window);
3498 if (info->icon_list == list) /* check for NULL mostly */
3501 g_list_foreach (list,
3502 (GFunc) g_object_ref, NULL);
3504 g_list_foreach (info->icon_list,
3505 (GFunc) g_object_unref, NULL);
3507 g_list_free (info->icon_list);
3509 info->icon_list = g_list_copy (list);
3511 g_object_notify (G_OBJECT (window), "icon");
3513 gtk_window_unrealize_icon (window);
3515 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3516 gtk_window_realize_icon (window);
3518 /* We could try to update our transient children, but I don't think
3519 * it's really worth it. If we did it, the best way would probably
3520 * be to have children connect to notify::icon-list
3525 * gtk_window_get_icon_list:
3526 * @window: a #GtkWindow
3528 * Retrieves the list of icons set by gtk_window_set_icon_list().
3529 * The list is copied, but the reference count on each
3530 * member won't be incremented.
3532 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3535 gtk_window_get_icon_list (GtkWindow *window)
3537 GtkWindowIconInfo *info;
3539 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3541 info = get_icon_info (window);
3544 return g_list_copy (info->icon_list);
3550 * gtk_window_set_icon:
3551 * @window: a #GtkWindow
3552 * @icon: (allow-none): icon image, or %NULL
3554 * Sets up the icon representing a #GtkWindow. This icon is used when
3555 * the window is minimized (also known as iconified). Some window
3556 * managers or desktop environments may also place it in the window
3557 * frame, or display it in other contexts.
3559 * The icon should be provided in whatever size it was naturally
3560 * drawn; that is, don't scale the image before passing it to
3561 * GTK+. Scaling is postponed until the last minute, when the desired
3562 * final size is known, to allow best quality.
3564 * If you have your icon hand-drawn in multiple sizes, use
3565 * gtk_window_set_icon_list(). Then the best size will be used.
3567 * This function is equivalent to calling gtk_window_set_icon_list()
3568 * with a 1-element list.
3570 * See also gtk_window_set_default_icon_list() to set the icon
3571 * for all windows in your application in one go.
3574 gtk_window_set_icon (GtkWindow *window,
3579 g_return_if_fail (GTK_IS_WINDOW (window));
3580 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3585 list = g_list_append (list, icon);
3587 gtk_window_set_icon_list (window, list);
3593 update_themed_icon (GtkIconTheme *icon_theme,
3596 g_object_notify (G_OBJECT (window), "icon");
3598 gtk_window_unrealize_icon (window);
3600 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3601 gtk_window_realize_icon (window);
3605 * gtk_window_set_icon_name:
3606 * @window: a #GtkWindow
3607 * @name: (allow-none): the name of the themed icon
3609 * Sets the icon for the window from a named themed icon. See
3610 * the docs for #GtkIconTheme for more details.
3612 * Note that this has nothing to do with the WM_ICON_NAME
3613 * property which is mentioned in the ICCCM.
3618 gtk_window_set_icon_name (GtkWindow *window,
3621 GtkWindowIconInfo *info;
3624 g_return_if_fail (GTK_IS_WINDOW (window));
3626 info = ensure_icon_info (window);
3628 if (g_strcmp0 (info->icon_name, name) == 0)
3631 tmp = info->icon_name;
3632 info->icon_name = g_strdup (name);
3635 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3636 g_list_free (info->icon_list);
3637 info->icon_list = NULL;
3639 update_themed_icon (NULL, window);
3641 g_object_notify (G_OBJECT (window), "icon-name");
3645 * gtk_window_get_icon_name:
3646 * @window: a #GtkWindow
3648 * Returns the name of the themed icon for the window,
3649 * see gtk_window_set_icon_name().
3651 * Returns: the icon name or %NULL if the window has
3657 gtk_window_get_icon_name (GtkWindow *window)
3659 GtkWindowIconInfo *info;
3661 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3663 info = ensure_icon_info (window);
3665 return info->icon_name;
3669 * gtk_window_get_icon:
3670 * @window: a #GtkWindow
3672 * Gets the value set by gtk_window_set_icon() (or if you've
3673 * called gtk_window_set_icon_list(), gets the first icon in
3676 * Return value: (transfer none): icon for window
3679 gtk_window_get_icon (GtkWindow *window)
3681 GtkWindowIconInfo *info;
3683 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3685 info = get_icon_info (window);
3686 if (info && info->icon_list)
3687 return GDK_PIXBUF (info->icon_list->data);
3692 /* Load pixbuf, printing warning on failure if error == NULL
3695 load_pixbuf_verbosely (const char *filename,
3698 GError *local_err = NULL;
3701 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3709 g_warning ("Error loading icon from file '%s':\n\t%s",
3710 filename, local_err->message);
3711 g_error_free (local_err);
3719 * gtk_window_set_icon_from_file:
3720 * @window: a #GtkWindow
3721 * @filename: location of icon file
3722 * @err: (allow-none): location to store error, or %NULL.
3724 * Sets the icon for @window.
3725 * Warns on failure if @err is %NULL.
3727 * This function is equivalent to calling gtk_window_set_icon()
3728 * with a pixbuf created by loading the image from @filename.
3730 * Returns: %TRUE if setting the icon succeeded.
3735 gtk_window_set_icon_from_file (GtkWindow *window,
3736 const gchar *filename,
3739 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3743 gtk_window_set_icon (window, pixbuf);
3744 g_object_unref (pixbuf);
3753 * gtk_window_set_default_icon_list:
3754 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3756 * Sets an icon list to be used as fallback for windows that haven't
3757 * had gtk_window_set_icon_list() called on them to set up a
3758 * window-specific icon list. This function allows you to set up the
3759 * icon for all windows in your app at once.
3761 * See gtk_window_set_icon_list() for more details.
3765 gtk_window_set_default_icon_list (GList *list)
3769 if (list == default_icon_list)
3772 /* Update serial so we don't used cached pixmaps/masks
3774 default_icon_serial++;
3776 g_list_foreach (list,
3777 (GFunc) g_object_ref, NULL);
3779 g_list_foreach (default_icon_list,
3780 (GFunc) g_object_unref, NULL);
3782 g_list_free (default_icon_list);
3784 default_icon_list = g_list_copy (list);
3786 /* Update all toplevels */
3787 toplevels = gtk_window_list_toplevels ();
3788 tmp_list = toplevels;
3789 while (tmp_list != NULL)
3791 GtkWindowIconInfo *info;
3792 GtkWindow *w = tmp_list->data;
3794 info = get_icon_info (w);
3795 if (info && info->using_default_icon)
3797 gtk_window_unrealize_icon (w);
3798 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3799 gtk_window_realize_icon (w);
3802 tmp_list = tmp_list->next;
3804 g_list_free (toplevels);
3808 * gtk_window_set_default_icon:
3811 * Sets an icon to be used as fallback for windows that haven't
3812 * had gtk_window_set_icon() called on them from a pixbuf.
3817 gtk_window_set_default_icon (GdkPixbuf *icon)
3821 g_return_if_fail (GDK_IS_PIXBUF (icon));
3823 list = g_list_prepend (NULL, icon);
3824 gtk_window_set_default_icon_list (list);
3829 * gtk_window_set_default_icon_name:
3830 * @name: the name of the themed icon
3832 * Sets an icon to be used as fallback for windows that haven't
3833 * had gtk_window_set_icon_list() called on them from a named
3834 * themed icon, see gtk_window_set_icon_name().
3839 gtk_window_set_default_icon_name (const gchar *name)
3844 /* Update serial so we don't used cached pixmaps/masks
3846 default_icon_serial++;
3848 g_free (default_icon_name);
3849 default_icon_name = g_strdup (name);
3851 g_list_foreach (default_icon_list,
3852 (GFunc) g_object_unref, NULL);
3854 g_list_free (default_icon_list);
3855 default_icon_list = NULL;
3857 /* Update all toplevels */
3858 toplevels = gtk_window_list_toplevels ();
3859 tmp_list = toplevels;
3860 while (tmp_list != NULL)
3862 GtkWindowIconInfo *info;
3863 GtkWindow *w = tmp_list->data;
3865 info = get_icon_info (w);
3866 if (info && info->using_default_icon && info->using_themed_icon)
3868 gtk_window_unrealize_icon (w);
3869 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3870 gtk_window_realize_icon (w);
3873 tmp_list = tmp_list->next;
3875 g_list_free (toplevels);
3879 * gtk_window_get_default_icon_name:
3881 * Returns the fallback icon name for windows that has been set
3882 * with gtk_window_set_default_icon_name(). The returned
3883 * string is owned by GTK+ and should not be modified. It
3884 * is only valid until the next call to
3885 * gtk_window_set_default_icon_name().
3887 * Returns: the fallback icon name for windows
3892 gtk_window_get_default_icon_name (void)
3894 return default_icon_name;
3898 * gtk_window_set_default_icon_from_file:
3899 * @filename: location of icon file
3900 * @err: (allow-none): location to store error, or %NULL.
3902 * Sets an icon to be used as fallback for windows that haven't
3903 * had gtk_window_set_icon_list() called on them from a file
3904 * on disk. Warns on failure if @err is %NULL.
3906 * Returns: %TRUE if setting the icon succeeded.
3911 gtk_window_set_default_icon_from_file (const gchar *filename,
3914 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3918 gtk_window_set_default_icon (pixbuf);
3919 g_object_unref (pixbuf);
3928 * gtk_window_get_default_icon_list:
3930 * Gets the value set by gtk_window_set_default_icon_list().
3931 * The list is a copy and should be freed with g_list_free(),
3932 * but the pixbufs in the list have not had their reference count
3935 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3938 gtk_window_get_default_icon_list (void)
3940 return g_list_copy (default_icon_list);
3944 gtk_window_set_default_size_internal (GtkWindow *window,
3945 gboolean change_width,
3947 gboolean change_height,
3949 gboolean is_geometry)
3951 GtkWindowGeometryInfo *info;
3953 g_return_if_fail (change_width == FALSE || width >= -1);
3954 g_return_if_fail (change_height == FALSE || height >= -1);
3956 info = gtk_window_get_geometry_info (window, TRUE);
3958 g_object_freeze_notify (G_OBJECT (window));
3960 info->default_is_geometry = is_geometry != FALSE;
3970 info->default_width = width;
3972 g_object_notify (G_OBJECT (window), "default-width");
3983 info->default_height = height;
3985 g_object_notify (G_OBJECT (window), "default-height");
3988 g_object_thaw_notify (G_OBJECT (window));
3990 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3994 * gtk_window_set_default_size:
3995 * @window: a #GtkWindow
3996 * @width: width in pixels, or -1 to unset the default width
3997 * @height: height in pixels, or -1 to unset the default height
3999 * Sets the default size of a window. If the window's "natural" size
4000 * (its size request) is larger than the default, the default will be
4001 * ignored. More generally, if the default size does not obey the
4002 * geometry hints for the window (gtk_window_set_geometry_hints() can
4003 * be used to set these explicitly), the default size will be clamped
4004 * to the nearest permitted size.
4006 * Unlike gtk_widget_set_size_request(), which sets a size request for
4007 * a widget and thus would keep users from shrinking the window, this
4008 * function only sets the initial size, just as if the user had
4009 * resized the window themselves. Users can still shrink the window
4010 * again as they normally would. Setting a default size of -1 means to
4011 * use the "natural" default size (the size request of the window).
4013 * For more control over a window's initial size and how resizing works,
4014 * investigate gtk_window_set_geometry_hints().
4016 * For some uses, gtk_window_resize() is a more appropriate function.
4017 * gtk_window_resize() changes the current size of the window, rather
4018 * than the size to be used on initial display. gtk_window_resize() always
4019 * affects the window itself, not the geometry widget.
4021 * The default size of a window only affects the first time a window is
4022 * shown; if a window is hidden and re-shown, it will remember the size
4023 * it had prior to hiding, rather than using the default size.
4025 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
4026 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
4029 gtk_window_set_default_size (GtkWindow *window,
4033 g_return_if_fail (GTK_IS_WINDOW (window));
4034 g_return_if_fail (width >= -1);
4035 g_return_if_fail (height >= -1);
4037 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
4041 * gtk_window_set_default_geometry:
4042 * @window: a #GtkWindow
4043 * @width: width in resize increments, or -1 to unset the default width
4044 * @height: height in resize increments, or -1 to unset the default height
4046 * Like gtk_window_set_default_size(), but @width and @height are interpreted
4047 * in terms of the base size and increment set with
4048 * gtk_window_set_geometry_hints.
4053 gtk_window_set_default_geometry (GtkWindow *window,
4057 g_return_if_fail (GTK_IS_WINDOW (window));
4058 g_return_if_fail (width >= -1);
4059 g_return_if_fail (height >= -1);
4061 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
4065 * gtk_window_get_default_size:
4066 * @window: a #GtkWindow
4067 * @width: (out) (allow-none): location to store the default width, or %NULL
4068 * @height: (out) (allow-none): location to store the default height, or %NULL
4070 * Gets the default size of the window. A value of -1 for the width or
4071 * height indicates that a default size has not been explicitly set
4072 * for that dimension, so the "natural" size of the window will be
4077 gtk_window_get_default_size (GtkWindow *window,
4081 GtkWindowGeometryInfo *info;
4083 g_return_if_fail (GTK_IS_WINDOW (window));
4085 info = gtk_window_get_geometry_info (window, FALSE);
4088 *width = info ? info->default_width : -1;
4091 *height = info ? info->default_height : -1;
4095 * gtk_window_resize:
4096 * @window: a #GtkWindow
4097 * @width: width in pixels to resize the window to
4098 * @height: height in pixels to resize the window to
4100 * Resizes the window as if the user had done so, obeying geometry
4101 * constraints. The default geometry constraint is that windows may
4102 * not be smaller than their size request; to override this
4103 * constraint, call gtk_widget_set_size_request() to set the window's
4104 * request to a smaller value.
4106 * If gtk_window_resize() is called before showing a window for the
4107 * first time, it overrides any default size set with
4108 * gtk_window_set_default_size().
4110 * Windows may not be resized smaller than 1 by 1 pixels.
4114 gtk_window_resize (GtkWindow *window,
4118 GtkWindowGeometryInfo *info;
4120 g_return_if_fail (GTK_IS_WINDOW (window));
4121 g_return_if_fail (width > 0);
4122 g_return_if_fail (height > 0);
4124 info = gtk_window_get_geometry_info (window, TRUE);
4126 info->resize_width = width;
4127 info->resize_height = height;
4128 info->resize_is_geometry = FALSE;
4130 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4134 * gtk_window_resize_to_geometry:
4135 * @window: a #GtkWindow
4136 * @width: width in resize increments to resize the window to
4137 * @height: height in resize increments to resize the window to
4139 * Like gtk_window_resize(), but @width and @height are interpreted
4140 * in terms of the base size and increment set with
4141 * gtk_window_set_geometry_hints.
4146 gtk_window_resize_to_geometry (GtkWindow *window,
4150 GtkWindowGeometryInfo *info;
4152 g_return_if_fail (GTK_IS_WINDOW (window));
4153 g_return_if_fail (width > 0);
4154 g_return_if_fail (height > 0);
4156 info = gtk_window_get_geometry_info (window, TRUE);
4158 info->resize_width = width;
4159 info->resize_height = height;
4160 info->resize_is_geometry = TRUE;
4162 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4166 * gtk_window_get_size:
4167 * @window: a #GtkWindow
4168 * @width: (out) (allow-none): return location for width, or %NULL
4169 * @height: (out) (allow-none): return location for height, or %NULL
4171 * Obtains the current size of @window. If @window is not onscreen,
4172 * it returns the size GTK+ will suggest to the <link
4173 * linkend="gtk-X11-arch">window manager</link> for the initial window
4174 * size (but this is not reliably the same as the size the window
4175 * manager will actually select). The size obtained by
4176 * gtk_window_get_size() is the last size received in a
4177 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4178 * rather than querying the X server for the size. As a result, if you
4179 * call gtk_window_resize() then immediately call
4180 * gtk_window_get_size(), the size won't have taken effect yet. After
4181 * the window manager processes the resize request, GTK+ receives
4182 * notification that the size has changed via a configure event, and
4183 * the size of the window gets updated.
4185 * Note 1: Nearly any use of this function creates a race condition,
4186 * because the size of the window may change between the time that you
4187 * get the size and the time that you perform some action assuming
4188 * that size is the current size. To avoid race conditions, connect to
4189 * "configure-event" on the window and adjust your size-dependent
4190 * state to match the size delivered in the #GdkEventConfigure.
4192 * Note 2: The returned size does <emphasis>not</emphasis> include the
4193 * size of the window manager decorations (aka the window frame or
4194 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4195 * method of determining their size.
4197 * Note 3: If you are getting a window size in order to position
4198 * the window onscreen, there may be a better way. The preferred
4199 * way is to simply set the window's semantic type with
4200 * gtk_window_set_type_hint(), which allows the window manager to
4201 * e.g. center dialogs. Also, if you set the transient parent of
4202 * dialogs with gtk_window_set_transient_for() window managers
4203 * will often center the dialog over its parent window. It's
4204 * much preferred to let the window manager handle these
4205 * things rather than doing it yourself, because all apps will
4206 * behave consistently and according to user prefs if the window
4207 * manager handles it. Also, the window manager can take the size
4208 * of the window decorations/border into account, while your
4209 * application cannot.
4211 * In any case, if you insist on application-specified window
4212 * positioning, there's <emphasis>still</emphasis> a better way than
4213 * doing it yourself - gtk_window_set_position() will frequently
4214 * handle the details for you.
4218 gtk_window_get_size (GtkWindow *window,
4224 g_return_if_fail (GTK_IS_WINDOW (window));
4226 if (width == NULL && height == NULL)
4229 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4231 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4232 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4236 GdkRectangle configure_request;
4238 gtk_window_compute_configure_request (window,
4242 w = configure_request.width;
4243 h = configure_request.height;
4254 * @window: a #GtkWindow
4255 * @x: X coordinate to move window to
4256 * @y: Y coordinate to move window to
4258 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4259 * @window to the given position. Window managers are free to ignore
4260 * this; most window managers ignore requests for initial window
4261 * positions (instead using a user-defined placement algorithm) and
4262 * honor requests after the window has already been shown.
4264 * Note: the position is the position of the gravity-determined
4265 * reference point for the window. The gravity determines two things:
4266 * first, the location of the reference point in root window
4267 * coordinates; and second, which point on the window is positioned at
4268 * the reference point.
4270 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4271 * point is simply the @x, @y supplied to gtk_window_move(). The
4272 * top-left corner of the window decorations (aka window frame or
4273 * border) will be placed at @x, @y. Therefore, to position a window
4274 * at the top left of the screen, you want to use the default gravity
4275 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4277 * To position a window at the bottom right corner of the screen, you
4278 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4279 * point is at @x + the window width and @y + the window height, and
4280 * the bottom-right corner of the window border will be placed at that
4281 * reference point. So, to place a window in the bottom right corner
4282 * you would first set gravity to south east, then write:
4283 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4284 * gdk_screen_height () - window_height)</literal> (note that this
4285 * example does not take multi-head scenarios into account).
4287 * The Extended Window Manager Hints specification at <ulink
4288 * url="http://www.freedesktop.org/Standards/wm-spec">
4289 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4290 * nice table of gravities in the "implementation notes" section.
4292 * The gtk_window_get_position() documentation may also be relevant.
4295 gtk_window_move (GtkWindow *window,
4299 GtkWindowPrivate *priv;
4300 GtkWindowGeometryInfo *info;
4303 g_return_if_fail (GTK_IS_WINDOW (window));
4305 priv = window->priv;
4306 widget = GTK_WIDGET (window);
4308 info = gtk_window_get_geometry_info (window, TRUE);
4310 if (gtk_widget_get_mapped (widget))
4312 GtkAllocation allocation;
4314 gtk_widget_get_allocation (widget, &allocation);
4316 /* we have now sent a request with this position
4317 * with currently-active constraints, so toggle flag.
4319 info->position_constraints_changed = FALSE;
4321 /* we only constrain if mapped - if not mapped,
4322 * then gtk_window_compute_configure_request()
4323 * will apply the constraints later, and we
4324 * don't want to lose information about
4325 * what position the user set before then.
4326 * i.e. if you do a move() then turn off POS_CENTER
4327 * then show the window, your move() will work.
4329 gtk_window_constrain_position (window,
4330 allocation.width, allocation.height,
4333 /* Note that this request doesn't go through our standard request
4334 * framework, e.g. doesn't increment configure_request_count,
4335 * doesn't set info->last, etc.; that's because
4336 * we don't save the info needed to arrive at this same request
4339 * To gtk_window_move_resize(), this will end up looking exactly
4340 * the same as the position being changed by the window
4344 /* FIXME are we handling gravity properly for framed windows? */
4346 gdk_window_move (priv->frame,
4347 x - priv->frame_left,
4348 y - priv->frame_top);
4350 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)),
4355 /* Save this position to apply on mapping */
4356 info->initial_x = x;
4357 info->initial_y = y;
4358 info->initial_pos_set = TRUE;
4363 * gtk_window_get_position:
4364 * @window: a #GtkWindow
4365 * @root_x: (out): return location for X coordinate of gravity-determined reference point
4366 * @root_y: (out): return location for Y coordinate of gravity-determined reference point
4368 * This function returns the position you need to pass to
4369 * gtk_window_move() to keep @window in its current position. This
4370 * means that the meaning of the returned value varies with window
4371 * gravity. See gtk_window_move() for more details.
4373 * If you haven't changed the window gravity, its gravity will be
4374 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4375 * gets the position of the top-left corner of the window manager
4376 * frame for the window. gtk_window_move() sets the position of this
4377 * same top-left corner.
4379 * gtk_window_get_position() is not 100% reliable because the X Window System
4380 * does not specify a way to obtain the geometry of the
4381 * decorations placed on a window by the window manager.
4382 * Thus GTK+ is using a "best guess" that works with most
4385 * Moreover, nearly all window managers are historically broken with
4386 * respect to their handling of window gravity. So moving a window to
4387 * its current position as returned by gtk_window_get_position() tends
4388 * to result in moving the window slightly. Window managers are
4389 * slowly getting better over time.
4391 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4392 * frame is not relevant, and thus gtk_window_get_position() will
4393 * always produce accurate results. However you can't use static
4394 * gravity to do things like place a window in a corner of the screen,
4395 * because static gravity ignores the window manager decorations.
4397 * If you are saving and restoring your application's window
4398 * positions, you should know that it's impossible for applications to
4399 * do this without getting it somewhat wrong because applications do
4400 * not have sufficient knowledge of window manager state. The Correct
4401 * Mechanism is to support the session management protocol (see the
4402 * "GnomeClient" object in the GNOME libraries for example) and allow
4403 * the window manager to save your window sizes and positions.
4408 gtk_window_get_position (GtkWindow *window,
4412 GtkWindowPrivate *priv;
4414 GdkWindow *gdk_window;
4416 g_return_if_fail (GTK_IS_WINDOW (window));
4418 priv = window->priv;
4419 widget = GTK_WIDGET (window);
4420 gdk_window = gtk_widget_get_window (widget);
4422 if (priv->gravity == GDK_GRAVITY_STATIC)
4424 if (gtk_widget_get_mapped (widget))
4426 /* This does a server round-trip, which is sort of wrong;
4427 * but a server round-trip is inevitable for
4428 * gdk_window_get_frame_extents() in the usual
4429 * NorthWestGravity case below, so not sure what else to
4430 * do. We should likely be consistent about whether we get
4431 * the client-side info or the server-side info.
4433 gdk_window_get_origin (gdk_window, root_x, root_y);
4437 GdkRectangle configure_request;
4439 gtk_window_compute_configure_request (window,
4443 *root_x = configure_request.x;
4444 *root_y = configure_request.y;
4449 GdkRectangle frame_extents;
4454 if (gtk_widget_get_mapped (widget))
4457 gdk_window_get_frame_extents (priv->frame, &frame_extents);
4459 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4460 x = frame_extents.x;
4461 y = frame_extents.y;
4462 gtk_window_get_size (window, &w, &h);
4466 /* We just say the frame has 0 size on all sides.
4467 * Not sure what else to do.
4469 gtk_window_compute_configure_request (window,
4472 x = frame_extents.x;
4473 y = frame_extents.y;
4474 w = frame_extents.width;
4475 h = frame_extents.height;
4478 switch (priv->gravity)
4480 case GDK_GRAVITY_NORTH:
4481 case GDK_GRAVITY_CENTER:
4482 case GDK_GRAVITY_SOUTH:
4483 /* Find center of frame. */
4484 x += frame_extents.width / 2;
4485 /* Center client window on that point. */
4489 case GDK_GRAVITY_SOUTH_EAST:
4490 case GDK_GRAVITY_EAST:
4491 case GDK_GRAVITY_NORTH_EAST:
4492 /* Find right edge of frame */
4493 x += frame_extents.width;
4494 /* Align left edge of client at that point. */
4501 switch (priv->gravity)
4503 case GDK_GRAVITY_WEST:
4504 case GDK_GRAVITY_CENTER:
4505 case GDK_GRAVITY_EAST:
4506 /* Find center of frame. */
4507 y += frame_extents.height / 2;
4508 /* Center client window there. */
4511 case GDK_GRAVITY_SOUTH_WEST:
4512 case GDK_GRAVITY_SOUTH:
4513 case GDK_GRAVITY_SOUTH_EAST:
4514 /* Find south edge of frame */
4515 y += frame_extents.height;
4516 /* Place bottom edge of client there */
4531 * gtk_window_reshow_with_initial_size:
4532 * @window: a #GtkWindow
4534 * Hides @window, then reshows it, resetting the
4535 * default size and position of the window. Used
4536 * by GUI builders only.
4539 gtk_window_reshow_with_initial_size (GtkWindow *window)
4543 g_return_if_fail (GTK_IS_WINDOW (window));
4545 widget = GTK_WIDGET (window);
4547 gtk_widget_hide (widget);
4548 gtk_widget_unrealize (widget);
4549 gtk_widget_show (widget);
4553 gtk_window_destroy (GtkWidget *widget)
4555 GtkWindow *window = GTK_WINDOW (widget);
4556 GtkWindowPrivate *priv = window->priv;
4558 toplevel_list = g_slist_remove (toplevel_list, window);
4560 if (priv->transient_parent)
4561 gtk_window_set_transient_for (window, NULL);
4563 /* frees the icons */
4564 gtk_window_set_icon_list (window, NULL);
4566 if (priv->has_user_ref_count)
4568 priv->has_user_ref_count = FALSE;
4569 g_object_unref (window);
4573 gtk_window_group_remove_window (priv->group, window);
4575 gtk_window_free_key_hash (window);
4577 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4581 gtk_window_finalize (GObject *object)
4583 GtkWindow *window = GTK_WINDOW (object);
4584 GtkWindowPrivate *priv = window->priv;
4585 GtkMnemonicHash *mnemonic_hash;
4587 g_free (priv->title);
4588 g_free (priv->wmclass_name);
4589 g_free (priv->wmclass_class);
4590 g_free (priv->wm_role);
4591 gtk_window_release_application (window);
4593 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4595 _gtk_mnemonic_hash_free (mnemonic_hash);
4597 if (priv->geometry_info)
4599 if (priv->geometry_info->widget)
4600 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4601 gtk_widget_destroyed,
4602 &priv->geometry_info->widget);
4603 g_free (priv->geometry_info);
4606 if (priv->keys_changed_handler)
4608 g_source_remove (priv->keys_changed_handler);
4609 priv->keys_changed_handler = 0;
4613 g_signal_handlers_disconnect_by_func (priv->screen,
4614 gtk_window_on_composited_changed, window);
4616 g_free (priv->startup_id);
4618 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4622 gtk_window_show (GtkWidget *widget)
4624 GtkWindow *window = GTK_WINDOW (widget);
4625 GtkWindowPrivate *priv = window->priv;
4626 GtkContainer *container = GTK_CONTAINER (window);
4627 gboolean need_resize;
4629 _gtk_widget_set_visible_flag (widget, TRUE);
4631 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4632 _gtk_container_set_need_resize (container, FALSE);
4636 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4637 GtkAllocation allocation = { 0, 0 };
4638 GdkRectangle configure_request;
4639 GdkGeometry new_geometry;
4641 gboolean was_realized;
4643 /* We are going to go ahead and perform this configure request
4644 * and then emulate a configure notify by going ahead and
4645 * doing a size allocate. Sort of a synchronous
4646 * mini-copy of gtk_window_move_resize() here.
4648 gtk_window_compute_configure_request (window,
4653 /* We update this because we are going to go ahead
4654 * and gdk_window_resize() below, rather than
4657 info->last.configure_request.width = configure_request.width;
4658 info->last.configure_request.height = configure_request.height;
4660 /* and allocate the window - this is normally done
4661 * in move_resize in response to configure notify
4663 allocation.width = configure_request.width;
4664 allocation.height = configure_request.height;
4665 gtk_widget_size_allocate (widget, &allocation);
4667 /* Then we guarantee we have a realize */
4668 was_realized = FALSE;
4669 if (!gtk_widget_get_realized (widget))
4671 gtk_widget_realize (widget);
4672 was_realized = TRUE;
4675 /* Must be done after the windows are realized,
4676 * so that the decorations can be read
4678 gtk_decorated_window_calculate_frame_size (window);
4680 /* We only send configure request if we didn't just finish
4681 * creating the window; if we just created the window
4682 * then we created it with widget->allocation anyhow.
4685 gdk_window_move_resize (gtk_widget_get_window (widget),
4686 configure_request.x,
4687 configure_request.y,
4688 configure_request.width,
4689 configure_request.height);
4692 gtk_container_check_resize (container);
4694 gtk_widget_map (widget);
4696 /* Try to make sure that we have some focused widget
4698 if (!priv->focus_widget && !GTK_IS_PLUG (window))
4699 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4702 gtk_grab_add (widget);
4706 gtk_window_hide (GtkWidget *widget)
4708 GtkWindow *window = GTK_WINDOW (widget);
4709 GtkWindowPrivate *priv = window->priv;
4711 _gtk_widget_set_visible_flag (widget, FALSE);
4712 gtk_widget_unmap (widget);
4715 gtk_grab_remove (widget);
4719 gtk_window_map (GtkWidget *widget)
4722 GtkWindow *window = GTK_WINDOW (widget);
4723 GtkWindowPrivate *priv = window->priv;
4724 GdkWindow *toplevel;
4725 GdkWindow *gdk_window;
4726 gboolean auto_mnemonics;
4728 gdk_window = gtk_widget_get_window (widget);
4730 gtk_widget_set_mapped (widget, TRUE);
4732 child = gtk_bin_get_child (&(window->bin));
4734 gtk_widget_get_visible (child) &&
4735 !gtk_widget_get_mapped (child))
4736 gtk_widget_map (child);
4739 toplevel = priv->frame;
4741 toplevel = gdk_window;
4743 if (priv->maximize_initially)
4744 gdk_window_maximize (toplevel);
4746 gdk_window_unmaximize (toplevel);
4748 if (priv->stick_initially)
4749 gdk_window_stick (toplevel);
4751 gdk_window_unstick (toplevel);
4753 if (priv->iconify_initially)
4754 gdk_window_iconify (toplevel);
4756 gdk_window_deiconify (toplevel);
4758 if (priv->fullscreen_initially)
4759 gdk_window_fullscreen (toplevel);
4761 gdk_window_unfullscreen (toplevel);
4763 gdk_window_set_keep_above (toplevel, priv->above_initially);
4765 gdk_window_set_keep_below (toplevel, priv->below_initially);
4767 /* No longer use the default settings */
4768 priv->need_default_size = FALSE;
4769 priv->need_default_position = FALSE;
4771 if (priv->reset_type_hint)
4773 /* We should only reset the type hint when the application
4774 * used gtk_window_set_type_hint() to change the hint.
4775 * Some applications use X directly to change the properties;
4776 * in that case, we shouldn't overwrite what they did.
4778 gdk_window_set_type_hint (gdk_window, priv->type_hint);
4779 priv->reset_type_hint = FALSE;
4782 gdk_window_show (gdk_window);
4785 gdk_window_show (priv->frame);
4787 if (priv->grip_window)
4788 gdk_window_show (priv->grip_window);
4790 if (!disable_startup_notification)
4792 /* Do we have a custom startup-notification id? */
4793 if (priv->startup_id != NULL)
4795 /* Make sure we have a "real" id */
4796 if (!startup_id_is_fake (priv->startup_id))
4797 gdk_notify_startup_complete_with_id (priv->startup_id);
4799 g_free (priv->startup_id);
4800 priv->startup_id = NULL;
4802 else if (!sent_startup_notification)
4804 sent_startup_notification = TRUE;
4805 gdk_notify_startup_complete ();
4809 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4810 * (as in the case of popup menus), then hide mnemonics initially
4812 g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
4813 &auto_mnemonics, NULL);
4814 if (auto_mnemonics && !priv->mnemonics_visible_set)
4815 gtk_window_set_mnemonics_visible (window, FALSE);
4819 gtk_window_map_event (GtkWidget *widget,
4822 if (!gtk_widget_get_mapped (widget))
4824 /* we should be be unmapped, but are getting a MapEvent, this may happen
4825 * to toplevel XWindows if mapping was intercepted by a window manager
4826 * and an unmap request occoured while the MapRequestEvent was still
4827 * being handled. we work around this situaiton here by re-requesting
4828 * the window being unmapped. more details can be found in:
4829 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4831 gdk_window_hide (gtk_widget_get_window (widget));
4837 gtk_window_unmap (GtkWidget *widget)
4839 GtkWindow *window = GTK_WINDOW (widget);
4840 GtkWindowPrivate *priv = window->priv;
4841 GtkWindowGeometryInfo *info;
4842 GdkWindow *gdk_window;
4843 GdkWindowState state;
4845 gdk_window = gtk_widget_get_window (widget);
4847 gtk_widget_set_mapped (widget, FALSE);
4849 gdk_window_withdraw (priv->frame);
4851 gdk_window_withdraw (gdk_window);
4853 priv->configure_request_count = 0;
4854 priv->configure_notify_received = FALSE;
4856 /* on unmap, we reset the default positioning of the window,
4857 * so it's placed again, but we don't reset the default
4858 * size of the window, so it's remembered.
4860 priv->need_default_position = TRUE;
4862 info = gtk_window_get_geometry_info (window, FALSE);
4865 info->initial_pos_set = FALSE;
4866 info->position_constraints_changed = FALSE;
4869 state = gdk_window_get_state (gdk_window);
4870 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4871 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4872 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4873 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4874 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4878 gtk_window_realize (GtkWidget *widget)
4880 GtkAllocation allocation;
4883 GdkWindow *parent_window;
4884 GdkWindow *gdk_window;
4885 GdkWindowAttr attributes;
4886 gint attributes_mask;
4887 GtkWindowPrivate *priv;
4889 window = GTK_WINDOW (widget);
4890 priv = window->priv;
4892 gtk_widget_get_allocation (widget, &allocation);
4894 /* ensure widget tree is properly size allocated */
4895 if (allocation.x == -1 &&
4896 allocation.y == -1 &&
4897 allocation.width == 1 &&
4898 allocation.height == 1)
4900 GtkRequisition requisition;
4904 allocation.width = 200;
4905 allocation.height = 200;
4907 gtk_widget_get_preferred_size (widget, &requisition, NULL);
4908 if (requisition.width || requisition.height)
4910 /* non-empty window */
4911 allocation.width = requisition.width;
4912 allocation.height = requisition.height;
4914 gtk_widget_size_allocate (widget, &allocation);
4916 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4918 g_return_if_fail (!gtk_widget_get_realized (widget));
4921 gtk_widget_set_realized (widget, TRUE);
4925 case GTK_WINDOW_TOPLEVEL:
4926 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4928 case GTK_WINDOW_POPUP:
4929 attributes.window_type = GDK_WINDOW_TEMP;
4932 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
4936 attributes.title = priv->title;
4937 attributes.wmclass_name = priv->wmclass_name;
4938 attributes.wmclass_class = priv->wmclass_class;
4939 attributes.wclass = GDK_INPUT_OUTPUT;
4940 attributes.visual = gtk_widget_get_visual (widget);
4942 if (priv->has_frame)
4944 gtk_widget_get_allocation (widget, &allocation);
4945 attributes.width = allocation.width + priv->frame_left + priv->frame_right;
4946 attributes.height = allocation.height + priv->frame_top + priv->frame_bottom;
4947 attributes.event_mask = (GDK_EXPOSURE_MASK |
4948 GDK_KEY_PRESS_MASK |
4949 GDK_ENTER_NOTIFY_MASK |
4950 GDK_LEAVE_NOTIFY_MASK |
4951 GDK_FOCUS_CHANGE_MASK |
4952 GDK_STRUCTURE_MASK |
4953 GDK_BUTTON_MOTION_MASK |
4954 GDK_POINTER_MOTION_HINT_MASK |
4955 GDK_BUTTON_PRESS_MASK |
4956 GDK_BUTTON_RELEASE_MASK);
4958 attributes_mask = GDK_WA_VISUAL;
4960 priv->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4961 &attributes, attributes_mask);
4963 if (priv->opacity_set)
4964 gdk_window_set_opacity (priv->frame, priv->opacity);
4966 gdk_window_set_user_data (priv->frame, widget);
4968 attributes.window_type = GDK_WINDOW_CHILD;
4969 attributes.x = priv->frame_left;
4970 attributes.y = priv->frame_top;
4972 attributes_mask = GDK_WA_X | GDK_WA_Y;
4974 parent_window = priv->frame;
4976 g_signal_connect (window,
4978 G_CALLBACK (gtk_window_event),
4983 attributes_mask = 0;
4984 parent_window = gtk_widget_get_root_window (widget);
4987 gtk_widget_get_allocation (widget, &allocation);
4988 attributes.width = allocation.width;
4989 attributes.height = allocation.height;
4990 attributes.event_mask = gtk_widget_get_events (widget);
4991 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4992 GDK_KEY_PRESS_MASK |
4993 GDK_KEY_RELEASE_MASK |
4994 GDK_ENTER_NOTIFY_MASK |
4995 GDK_LEAVE_NOTIFY_MASK |
4996 GDK_FOCUS_CHANGE_MASK |
4997 GDK_STRUCTURE_MASK);
4998 attributes.type_hint = priv->type_hint;
5000 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
5001 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
5002 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
5004 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
5005 gtk_widget_set_window (widget, gdk_window);
5007 if (!priv->has_frame && priv->opacity_set)
5008 gdk_window_set_opacity (gdk_window, priv->opacity);
5010 gdk_window_enable_synchronized_configure (gdk_window);
5012 gdk_window_set_user_data (gdk_window, window);
5014 gtk_widget_style_attach (widget);
5015 style = gtk_widget_get_style (widget);
5016 gtk_style_set_background (style, gdk_window, GTK_STATE_NORMAL);
5018 gtk_style_set_background (style, priv->frame, GTK_STATE_NORMAL);
5020 if (priv->transient_parent &&
5021 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
5022 gdk_window_set_transient_for (gdk_window,
5023 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
5026 gdk_window_set_role (gdk_window, priv->wm_role);
5028 if (!priv->decorated)
5029 gdk_window_set_decorations (gdk_window, 0);
5031 if (!priv->deletable)
5032 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
5034 if (gtk_window_get_skip_pager_hint (window))
5035 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
5037 if (gtk_window_get_skip_taskbar_hint (window))
5038 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
5040 if (gtk_window_get_accept_focus (window))
5041 gdk_window_set_accept_focus (gdk_window, TRUE);
5043 gdk_window_set_accept_focus (gdk_window, FALSE);
5045 if (gtk_window_get_focus_on_map (window))
5046 gdk_window_set_focus_on_map (gdk_window, TRUE);
5048 gdk_window_set_focus_on_map (gdk_window, FALSE);
5051 gdk_window_set_modal_hint (gdk_window, TRUE);
5053 gdk_window_set_modal_hint (gdk_window, FALSE);
5055 if (priv->startup_id)
5057 #ifdef GDK_WINDOWING_X11
5058 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
5059 if (timestamp != GDK_CURRENT_TIME)
5060 gdk_x11_window_set_user_time (gdk_window, timestamp);
5062 if (!startup_id_is_fake (priv->startup_id))
5063 gdk_window_set_startup_id (gdk_window, priv->startup_id);
5067 gtk_window_realize_icon (window);
5069 if (priv->has_resize_grip)
5070 resize_grip_create_window (window);
5074 gtk_window_unrealize (GtkWidget *widget)
5076 GtkWindow *window = GTK_WINDOW (widget);
5077 GtkWindowPrivate *priv = window->priv;
5078 GtkWindowGeometryInfo *info;
5080 /* On unrealize, we reset the size of the window such
5081 * that we will re-apply the default sizing stuff
5082 * next time we show the window.
5084 * Default positioning is reset on unmap, instead of unrealize.
5086 priv->need_default_size = TRUE;
5087 info = gtk_window_get_geometry_info (window, FALSE);
5090 info->resize_width = -1;
5091 info->resize_height = -1;
5092 info->last.configure_request.x = 0;
5093 info->last.configure_request.y = 0;
5094 info->last.configure_request.width = -1;
5095 info->last.configure_request.height = -1;
5096 /* be sure we reset geom hints on re-realize */
5097 info->last.flags = 0;
5102 gdk_window_set_user_data (priv->frame, NULL);
5103 gdk_window_destroy (priv->frame);
5108 gtk_window_unrealize_icon (window);
5110 if (priv->grip_window != NULL)
5111 resize_grip_destroy_window (window);
5113 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5116 static GdkWindowEdge
5117 get_grip_edge (GtkWidget *widget)
5119 return gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR
5120 ? GDK_WINDOW_EDGE_SOUTH_EAST
5121 : GDK_WINDOW_EDGE_SOUTH_WEST;
5125 get_drag_edge (GtkWidget *widget,
5126 GdkWindowEdge *edge)
5128 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5129 gboolean hresizable;
5130 gboolean vresizable;
5131 GtkTextDirection dir;
5132 GtkWindowGeometryInfo *info;
5137 info = priv->geometry_info;
5140 GdkWindowHints flags = info->last.flags;
5141 GdkGeometry *geometry = &info->last.geometry;
5143 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5145 hresizable = geometry->min_width < geometry->max_width;
5146 vresizable = geometry->min_height < geometry->max_height;
5150 dir = gtk_widget_get_direction (widget);
5152 if (hresizable && vresizable)
5153 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5154 else if (hresizable)
5155 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5156 else if (vresizable)
5157 *edge = GDK_WINDOW_EDGE_SOUTH;
5165 set_grip_cursor (GtkWindow *window)
5167 GtkWidget *widget = GTK_WIDGET (window);
5168 GtkWindowPrivate *priv = window->priv;
5170 if (priv->grip_window == NULL)
5173 if (gtk_widget_is_sensitive (widget))
5176 GdkDisplay *display;
5177 GdkCursorType cursor_type;
5180 cursor_type = GDK_LEFT_PTR;
5182 if (get_drag_edge (widget, &edge))
5186 case GDK_WINDOW_EDGE_EAST:
5187 cursor_type = GDK_RIGHT_SIDE;
5189 case GDK_WINDOW_EDGE_SOUTH_EAST:
5190 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5192 case GDK_WINDOW_EDGE_SOUTH:
5193 cursor_type = GDK_BOTTOM_SIDE;
5195 case GDK_WINDOW_EDGE_SOUTH_WEST:
5196 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5198 case GDK_WINDOW_EDGE_WEST:
5199 cursor_type = GDK_LEFT_SIDE;
5205 display = gtk_widget_get_display (widget);
5206 cursor = gdk_cursor_new_for_display (display, cursor_type);
5207 gdk_window_set_cursor (priv->grip_window, cursor);
5208 gdk_cursor_unref (cursor);
5211 gdk_window_set_cursor (priv->grip_window, NULL);
5215 set_grip_shape (GtkWindow *window)
5217 GtkWindowPrivate *priv = window->priv;
5218 cairo_region_t *region;
5219 cairo_surface_t *surface;
5221 double width, height;
5223 if (priv->grip_window == NULL)
5226 width = gdk_window_get_width (priv->grip_window);
5227 height = gdk_window_get_height (priv->grip_window);
5228 surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
5230 cr = cairo_create (surface);
5231 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5233 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5234 if (get_grip_edge (GTK_WIDGET (window)) == GDK_WINDOW_EDGE_SOUTH_EAST)
5236 cairo_move_to (cr, width, 0.0);
5237 cairo_line_to (cr, width, height);
5238 cairo_line_to (cr, 0.0, height);
5242 cairo_move_to (cr, 0.0, 0.0);
5243 cairo_line_to (cr, width, height);
5244 cairo_line_to (cr, 0.0, height);
5246 cairo_close_path (cr);
5249 region = gdk_cairo_region_create_from_surface (surface);
5250 cairo_surface_destroy (surface);
5252 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5253 cairo_region_destroy (region);
5257 set_grip_position (GtkWindow *window)
5259 GtkWindowPrivate *priv = window->priv;
5262 if (priv->grip_window == NULL)
5265 gtk_window_get_resize_grip_area (window, &rect);
5266 gdk_window_raise (priv->grip_window);
5267 gdk_window_move_resize (priv->grip_window,
5269 rect.width, rect.height);
5273 gtk_window_size_allocate (GtkWidget *widget,
5274 GtkAllocation *allocation)
5276 GtkWindow *window = GTK_WINDOW (widget);
5277 GtkWindowPrivate *priv = window->priv;
5278 GtkAllocation child_allocation;
5282 gtk_widget_set_allocation (widget, allocation);
5284 child = gtk_bin_get_child (&(window->bin));
5285 if (child && gtk_widget_get_visible (child))
5287 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5288 child_allocation.x = border_width;
5289 child_allocation.y = border_width;
5290 child_allocation.width =
5291 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5292 child_allocation.height =
5293 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5295 gtk_widget_size_allocate (child, &child_allocation);
5298 if (gtk_widget_get_realized (widget))
5301 gdk_window_resize (priv->frame,
5302 allocation->width + priv->frame_left + priv->frame_right,
5303 allocation->height + priv->frame_top + priv->frame_bottom);
5304 update_grip_visibility (window);
5305 set_grip_position (window);
5310 gtk_window_event (GtkWidget *widget, GdkEvent *event)
5312 GtkWindow *window = GTK_WINDOW (widget);
5313 GtkWindowPrivate *priv = window->priv;
5314 gboolean return_val;
5316 if (priv->frame && (event->any.window == priv->frame))
5318 if ((event->type != GDK_KEY_PRESS) &&
5319 (event->type != GDK_KEY_RELEASE) &&
5320 (event->type != GDK_FOCUS_CHANGE))
5322 g_signal_stop_emission_by_name (widget, "event");
5324 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
5329 g_object_unref (event->any.window);
5330 event->any.window = g_object_ref (gtk_widget_get_window (widget));
5338 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
5340 GtkWindowPrivate *priv = window->priv;
5341 GdkEventConfigure *configure_event;
5344 switch (event->type)
5347 configure_event = (GdkEventConfigure *)event;
5349 /* Invalidate the decorations */
5352 rect.width = configure_event->width;
5353 rect.height = configure_event->height;
5355 gdk_window_invalidate_rect (priv->frame, &rect, FALSE);
5357 /* Pass on the (modified) configure event */
5358 configure_event->width -= priv->frame_left + priv->frame_right;
5359 configure_event->height -= priv->frame_top + priv->frame_bottom;
5360 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
5369 gtk_window_configure_event (GtkWidget *widget,
5370 GdkEventConfigure *event)
5372 GtkAllocation allocation;
5373 GtkWindow *window = GTK_WINDOW (widget);
5374 GtkWindowPrivate *priv = window->priv;
5375 gboolean expected_reply = priv->configure_request_count > 0;
5377 /* priv->configure_request_count incremented for each
5378 * configure request, and decremented to a min of 0 for
5379 * each configure notify.
5381 * All it means is that we know we will get at least
5382 * priv->configure_request_count more configure notifies.
5383 * We could get more configure notifies than that; some
5384 * of the configure notifies we get may be unrelated to
5385 * the configure requests. But we will get at least
5386 * priv->configure_request_count notifies.
5389 if (priv->configure_request_count > 0)
5391 priv->configure_request_count -= 1;
5392 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5395 /* As an optimization, we avoid a resize when possible.
5397 * The only times we can avoid a resize are:
5398 * - we know only the position changed, not the size
5399 * - we know we have made more requests and so will get more
5400 * notifies and can wait to resize when we get them
5402 gtk_widget_get_allocation (widget, &allocation);
5403 if (!expected_reply &&
5404 (allocation.width == event->width &&
5405 allocation.height == event->height))
5407 gdk_window_configure_finished (gtk_widget_get_window (widget));
5412 * If we do need to resize, we do that by:
5413 * - filling in widget->allocation with the new size
5414 * - setting configure_notify_received to TRUE
5415 * for use in gtk_window_move_resize()
5416 * - queueing a resize, leading to invocation of
5417 * gtk_window_move_resize() in an idle handler
5421 priv->configure_notify_received = TRUE;
5423 allocation.width = event->width;
5424 allocation.height = event->height;
5425 gtk_widget_set_allocation (widget, &allocation);
5427 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5429 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5435 gtk_window_state_event (GtkWidget *widget,
5436 GdkEventWindowState *event)
5438 update_grip_visibility (GTK_WINDOW (widget));
5444 gtk_window_direction_changed (GtkWidget *widget,
5445 GtkTextDirection prev_dir)
5447 GtkWindow *window = GTK_WINDOW (widget);
5449 set_grip_cursor (window);
5450 set_grip_position (window);
5451 set_grip_shape (window);
5455 gtk_window_state_changed (GtkWidget *widget,
5456 GtkStateType previous_state)
5458 GtkWindow *window = GTK_WINDOW (widget);
5460 update_grip_visibility (window);
5464 gtk_window_style_set (GtkWidget *widget,
5467 GtkWindow *window = GTK_WINDOW (widget);
5468 GtkWindowPrivate *priv = window->priv;
5471 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5473 gdk_window_move_resize (priv->grip_window,
5475 rect.width, rect.height);
5477 set_grip_shape (window);
5478 gtk_widget_queue_resize (widget);
5483 resize_grip_create_window (GtkWindow *window)
5486 GtkWindowPrivate *priv;
5487 GdkWindowAttr attributes;
5488 gint attributes_mask;
5491 priv = window->priv;
5492 widget = GTK_WIDGET (window);
5494 g_return_if_fail (gtk_widget_get_realized (widget));
5495 g_return_if_fail (priv->grip_window == NULL);
5497 gtk_window_get_resize_grip_area (window, &rect);
5499 attributes.x = rect.x;
5500 attributes.y = rect.y;
5501 attributes.width = rect.width;
5502 attributes.height = rect.height;
5503 attributes.window_type = GDK_WINDOW_CHILD;
5504 attributes.wclass = GDK_INPUT_OUTPUT;
5505 attributes.event_mask = gtk_widget_get_events (widget) |
5507 GDK_BUTTON_PRESS_MASK;
5509 attributes_mask = GDK_WA_X | GDK_WA_Y;
5511 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5515 gdk_window_set_user_data (priv->grip_window, widget);
5517 gdk_window_raise (priv->grip_window);
5519 set_grip_shape (window);
5520 update_grip_visibility (window);
5524 resize_grip_destroy_window (GtkWindow *window)
5526 GtkWindowPrivate *priv = window->priv;
5528 gdk_window_set_user_data (priv->grip_window, NULL);
5529 gdk_window_destroy (priv->grip_window);
5530 priv->grip_window = NULL;
5531 update_grip_visibility (window);
5535 * gtk_window_set_has_resize_grip:
5536 * @window: a #GtkWindow
5537 * @value: %TRUE to allow a resize grip
5539 * Sets whether @window has a corner resize grip.
5541 * Note that the resize grip is only shown if the window
5542 * is actually resizable and not maximized. Use
5543 * gtk_window_resize_grip_is_visible() to find out if the
5544 * resize grip is currently shown.
5549 gtk_window_set_has_resize_grip (GtkWindow *window,
5552 GtkWidget *widget = GTK_WIDGET (window);
5553 GtkWindowPrivate *priv = window->priv;
5555 value = value != FALSE;
5557 if (value != priv->has_resize_grip)
5559 priv->has_resize_grip = value;
5560 gtk_widget_queue_draw (widget);
5562 if (gtk_widget_get_realized (widget))
5564 if (priv->has_resize_grip && priv->grip_window == NULL)
5565 resize_grip_create_window (window);
5566 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5567 resize_grip_destroy_window (window);
5570 g_object_notify (G_OBJECT (window), "has-resize-grip");
5575 update_grip_visibility (GtkWindow *window)
5577 GtkWindowPrivate *priv = window->priv;
5580 val = gtk_window_resize_grip_is_visible (window);
5582 if (priv->grip_window != NULL)
5586 gdk_window_show (priv->grip_window);
5587 set_grip_cursor (window);
5591 gdk_window_hide (priv->grip_window);
5595 if (priv->resize_grip_visible != val)
5597 priv->resize_grip_visible = val;
5599 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5604 * gtk_window_resize_grip_is_visible:
5605 * @window: a #GtkWindow
5607 * Determines whether a resize grip is visible for the specified window.
5609 * Returns %TRUE if a resize grip exists and is visible.
5614 gtk_window_resize_grip_is_visible (GtkWindow *window)
5617 GtkWindowPrivate *priv;
5620 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5622 priv = window->priv;
5623 widget = GTK_WIDGET (window);
5625 if (priv->type == GTK_WINDOW_POPUP)
5628 if (!priv->resizable)
5631 if (gtk_widget_get_realized (widget))
5633 GdkWindowState state;
5635 state = gdk_window_get_state (gtk_widget_get_window (widget));
5637 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5641 if (!get_drag_edge (widget, &edge))
5644 return window->priv->has_resize_grip;
5648 * gtk_window_get_has_resize_grip:
5649 * @window: a #GtkWindow
5651 * Determines whether the window may have a resize grip.
5653 * Returns: %TRUE if the window has a resize grip.
5658 gtk_window_get_has_resize_grip (GtkWindow *window)
5660 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5662 return window->priv->has_resize_grip;
5666 * gtk_window_get_resize_grip_area:
5667 * @window: a #GtkWindow
5668 * @rect: a pointer to a #GdkRectangle which we should store the
5671 * If a window has a resize grip, this will retrieve the grip
5672 * position, width and height into the specified #GdkRectangle.
5674 * Returns: %TRUE if the resize grip's area was retrieved.
5679 gtk_window_get_resize_grip_area (GtkWindow *window,
5682 GtkWidget *widget = GTK_WIDGET (window);
5683 GtkAllocation allocation;
5688 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5690 if (!window->priv->has_resize_grip)
5693 gtk_widget_get_allocation (widget, &allocation);
5694 style = gtk_widget_get_style (widget);
5696 gtk_widget_style_get (widget,
5697 "resize-grip-width", &grip_width,
5698 "resize-grip-height", &grip_height,
5701 if (grip_width > allocation.width)
5702 grip_width = allocation.width;
5704 if (grip_height > allocation.height)
5705 grip_height = allocation.height;
5707 rect->width = grip_width;
5708 rect->height = grip_height;
5709 rect->y = allocation.y + allocation.height - grip_height;
5711 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5712 rect->x = allocation.x + allocation.width - grip_width;
5714 rect->x = allocation.x;
5719 /* the accel_key and accel_mods fields of the key have to be setup
5720 * upon calling this function. it'll then return whether that key
5721 * is at all used as accelerator, and if so will OR in the
5722 * accel_flags member of the key.
5725 _gtk_window_query_nonaccels (GtkWindow *window,
5727 GdkModifierType accel_mods)
5729 GtkWindowPrivate *priv;
5731 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5733 priv = window->priv;
5735 /* movement keys are considered locked accels */
5738 static const guint bindings[] = {
5739 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,
5740 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,
5744 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5745 if (bindings[i] == accel_key)
5749 /* mnemonics are considered locked accels */
5750 if (accel_mods == priv->mnemonic_modifier)
5752 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5753 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5761 * gtk_window_propagate_key_event:
5762 * @window: a #GtkWindow
5763 * @event: a #GdkEventKey
5765 * Propagate a key press or release event to the focus widget and
5766 * up the focus container chain until a widget handles @event.
5767 * This is normally called by the default ::key_press_event and
5768 * ::key_release_event handlers for toplevel windows,
5769 * however in some cases it may be useful to call this directly when
5770 * overriding the standard key handling for a toplevel window.
5772 * Return value: %TRUE if a widget in the focus chain handled the event.
5777 gtk_window_propagate_key_event (GtkWindow *window,
5780 GtkWindowPrivate *priv;
5781 gboolean handled = FALSE;
5782 GtkWidget *widget, *focus;
5784 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5786 priv = window->priv;
5787 widget = GTK_WIDGET (window);
5789 focus = priv->focus_widget;
5791 g_object_ref (focus);
5794 focus && focus != widget &&
5795 gtk_widget_get_toplevel (focus) == widget)
5799 if (gtk_widget_is_sensitive (focus))
5800 handled = gtk_widget_event (focus, (GdkEvent*) event);
5802 parent = gtk_widget_get_parent (focus);
5804 g_object_ref (parent);
5806 g_object_unref (focus);
5812 g_object_unref (focus);
5818 gtk_window_key_press_event (GtkWidget *widget,
5821 GtkWindow *window = GTK_WINDOW (widget);
5822 gboolean handled = FALSE;
5824 /* handle mnemonics and accelerators */
5826 handled = gtk_window_activate_key (window, event);
5828 /* handle focus widget key events */
5830 handled = gtk_window_propagate_key_event (window, event);
5832 /* Chain up, invokes binding set */
5834 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5840 gtk_window_key_release_event (GtkWidget *widget,
5843 GtkWindow *window = GTK_WINDOW (widget);
5844 gboolean handled = FALSE;
5846 /* handle focus widget key events */
5848 handled = gtk_window_propagate_key_event (window, event);
5850 /* Chain up, invokes binding set */
5852 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5858 gtk_window_button_press_event (GtkWidget *widget,
5859 GdkEventButton *event)
5861 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5864 if (event->window == priv->grip_window)
5866 if (get_drag_edge (widget, &edge))
5867 gtk_window_begin_resize_drag (GTK_WINDOW (widget),
5881 gtk_window_real_activate_default (GtkWindow *window)
5883 gtk_window_activate_default (window);
5887 gtk_window_real_activate_focus (GtkWindow *window)
5889 gtk_window_activate_focus (window);
5893 gtk_window_enter_notify_event (GtkWidget *widget,
5894 GdkEventCrossing *event)
5900 gtk_window_leave_notify_event (GtkWidget *widget,
5901 GdkEventCrossing *event)
5907 do_focus_change (GtkWidget *widget,
5911 GdkDeviceManager *device_manager;
5914 g_object_ref (widget);
5916 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5917 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5918 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5919 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5921 for (d = devices; d; d = d->next)
5923 GdkDevice *dev = d->data;
5926 if (dev->source != GDK_SOURCE_KEYBOARD)
5929 /* Skip non-master keyboards that haven't
5930 * selected for events from this window
5932 window = gtk_widget_get_window (widget);
5933 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5934 window && !gdk_window_get_device_events (window, dev))
5937 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5939 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5940 fevent->focus_change.window = window;
5942 g_object_ref (window);
5943 fevent->focus_change.in = in;
5944 gdk_event_set_device (fevent, dev);
5946 gtk_widget_send_focus_change (widget, fevent);
5948 gdk_event_free (fevent);
5951 g_list_free (devices);
5952 g_object_unref (widget);
5956 gtk_window_focus_in_event (GtkWidget *widget,
5957 GdkEventFocus *event)
5959 GtkWindow *window = GTK_WINDOW (widget);
5961 /* It appears spurious focus in events can occur when
5962 * the window is hidden. So we'll just check to see if
5963 * the window is visible before actually handling the
5966 if (gtk_widget_get_visible (widget))
5968 _gtk_window_set_has_toplevel_focus (window, TRUE);
5969 _gtk_window_set_is_active (window, TRUE);
5976 gtk_window_focus_out_event (GtkWidget *widget,
5977 GdkEventFocus *event)
5979 GtkWindow *window = GTK_WINDOW (widget);
5980 gboolean auto_mnemonics;
5982 _gtk_window_set_has_toplevel_focus (window, FALSE);
5983 _gtk_window_set_is_active (window, FALSE);
5985 /* set the mnemonic-visible property to false */
5986 g_object_get (gtk_widget_get_settings (widget),
5987 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
5989 gtk_window_set_mnemonics_visible (window, FALSE);
5994 static GdkAtom atom_rcfiles = GDK_NONE;
5995 static GdkAtom atom_iconthemes = GDK_NONE;
5998 send_client_message_to_embedded_windows (GtkWidget *widget,
5999 GdkAtom message_type)
6001 GList *embedded_windows;
6003 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
6004 if (embedded_windows)
6006 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
6009 for (i = 0; i < 5; i++)
6010 send_event->client.data.l[i] = 0;
6011 send_event->client.data_format = 32;
6012 send_event->client.message_type = message_type;
6014 while (embedded_windows)
6016 GdkNativeWindow xid = GDK_GPOINTER_TO_NATIVE_WINDOW(embedded_windows->data);
6017 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
6018 embedded_windows = embedded_windows->next;
6021 gdk_event_free (send_event);
6026 gtk_window_client_event (GtkWidget *widget,
6027 GdkEventClient *event)
6031 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
6032 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
6035 if (event->message_type == atom_rcfiles)
6037 send_client_message_to_embedded_windows (widget, atom_rcfiles);
6038 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
6041 if (event->message_type == atom_iconthemes)
6043 send_client_message_to_embedded_windows (widget, atom_iconthemes);
6044 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
6051 gtk_window_check_resize (GtkContainer *container)
6053 if (gtk_widget_get_visible (GTK_WIDGET (container)))
6054 gtk_window_move_resize (GTK_WINDOW (container));
6058 gtk_window_focus (GtkWidget *widget,
6059 GtkDirectionType direction)
6061 GtkWindowPrivate *priv;
6064 GtkContainer *container;
6066 GtkWidget *old_focus_child;
6069 container = GTK_CONTAINER (widget);
6070 window = GTK_WINDOW (widget);
6071 priv = window->priv;
6072 bin = GTK_BIN (widget);
6074 old_focus_child = gtk_container_get_focus_child (container);
6076 /* We need a special implementation here to deal properly with wrapping
6077 * around in the tab chain without the danger of going into an
6080 if (old_focus_child)
6082 if (gtk_widget_child_focus (old_focus_child, direction))
6086 if (priv->focus_widget)
6088 if (direction == GTK_DIR_LEFT ||
6089 direction == GTK_DIR_RIGHT ||
6090 direction == GTK_DIR_UP ||
6091 direction == GTK_DIR_DOWN)
6096 /* Wrapped off the end, clear the focus setting for the toplpevel */
6097 parent = gtk_widget_get_parent (priv->focus_widget);
6100 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
6101 parent = gtk_widget_get_parent (parent);
6104 gtk_window_set_focus (GTK_WINDOW (container), NULL);
6107 /* Now try to focus the first widget in the window */
6108 child = gtk_bin_get_child (bin);
6111 if (gtk_widget_child_focus (child, direction))
6119 gtk_window_move_focus (GtkWidget *widget,
6120 GtkDirectionType dir)
6122 gtk_widget_child_focus (widget, dir);
6124 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
6125 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
6129 gtk_window_real_set_focus (GtkWindow *window,
6132 GtkWindowPrivate *priv = window->priv;
6133 GtkWidget *old_focus = priv->focus_widget;
6134 gboolean had_default = FALSE;
6135 gboolean focus_had_default = FALSE;
6136 gboolean old_focus_had_default = FALSE;
6140 g_object_ref (old_focus);
6141 g_object_freeze_notify (G_OBJECT (old_focus));
6142 old_focus_had_default = gtk_widget_has_default (old_focus);
6146 g_object_ref (focus);
6147 g_object_freeze_notify (G_OBJECT (focus));
6148 focus_had_default = gtk_widget_has_default (focus);
6151 if (priv->default_widget)
6152 had_default = gtk_widget_has_default (priv->default_widget);
6154 if (priv->focus_widget)
6156 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6157 (priv->focus_widget != priv->default_widget))
6159 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6160 gtk_widget_queue_draw (priv->focus_widget);
6162 if (priv->default_widget)
6163 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6166 priv->focus_widget = NULL;
6168 if (priv->has_focus)
6169 do_focus_change (old_focus, FALSE);
6171 g_object_notify (G_OBJECT (old_focus), "is-focus");
6174 /* The above notifications may have set a new focus widget,
6175 * if so, we don't want to override it.
6177 if (focus && !priv->focus_widget)
6179 priv->focus_widget = focus;
6181 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6182 (priv->focus_widget != priv->default_widget))
6184 if (gtk_widget_get_can_default (priv->focus_widget))
6185 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6187 if (priv->default_widget)
6188 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6191 if (priv->has_focus)
6192 do_focus_change (priv->focus_widget, TRUE);
6194 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6197 /* If the default widget changed, a redraw will have been queued
6198 * on the old and new default widgets by gtk_window_set_default(), so
6199 * we only have to worry about the case where it didn't change.
6200 * We'll sometimes queue a draw twice on the new widget but that
6203 if (priv->default_widget &&
6204 (had_default != gtk_widget_has_default (priv->default_widget)))
6205 gtk_widget_queue_draw (priv->default_widget);
6209 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6210 gtk_widget_queue_draw (old_focus);
6212 g_object_thaw_notify (G_OBJECT (old_focus));
6213 g_object_unref (old_focus);
6217 if (focus_had_default != gtk_widget_has_default (focus))
6218 gtk_widget_queue_draw (focus);
6220 g_object_thaw_notify (G_OBJECT (focus));
6221 g_object_unref (focus);
6227 gtk_window_get_preferred_width (GtkWidget *widget,
6235 window = GTK_WINDOW (widget);
6236 child = gtk_bin_get_child (GTK_BIN (window));
6238 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6239 *minimum_size = border_width * 2;
6240 *natural_size = border_width * 2;
6242 if (child && gtk_widget_get_visible (child))
6244 gint child_min, child_nat;
6245 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6247 *minimum_size += child_min;
6248 *natural_size += child_nat;
6253 gtk_window_get_preferred_height (GtkWidget *widget,
6261 window = GTK_WINDOW (widget);
6262 child = gtk_bin_get_child (GTK_BIN (window));
6264 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6265 *minimum_size = border_width * 2;
6266 *natural_size = border_width * 2;
6268 if (child && gtk_widget_get_visible (child))
6270 gint child_min, child_nat;
6271 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6273 *minimum_size += child_min;
6274 *natural_size += child_nat;
6280 * _gtk_window_unset_focus_and_default:
6281 * @window: a #GtkWindow
6282 * @widget: a widget inside of @window
6284 * Checks whether the focus and default widgets of @window are
6285 * @widget or a descendent of @widget, and if so, unset them.
6288 _gtk_window_unset_focus_and_default (GtkWindow *window,
6292 GtkWindowPrivate *priv = window->priv;
6296 g_object_ref (window);
6297 g_object_ref (widget);
6299 parent = gtk_widget_get_parent (widget);
6300 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6302 child = priv->focus_widget;
6304 while (child && child != widget)
6305 child = gtk_widget_get_parent (child);
6307 if (child == widget)
6308 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6311 child = priv->default_widget;
6313 while (child && child != widget)
6314 child = gtk_widget_get_parent (child);
6316 if (child == widget)
6317 gtk_window_set_default (window, NULL);
6319 g_object_unref (widget);
6320 g_object_unref (window);
6323 /*********************************
6324 * Functions related to resizing *
6325 *********************************/
6328 geometry_size_to_pixels (GdkGeometry *geometry,
6333 gint base_width = 0;
6334 gint base_height = 0;
6336 gint min_height = 0;
6338 gint height_inc = 1;
6340 if (flags & GDK_HINT_BASE_SIZE)
6342 base_width = geometry->base_width;
6343 base_height = geometry->base_height;
6345 if (flags & GDK_HINT_MIN_SIZE)
6347 min_width = geometry->min_width;
6348 min_height = geometry->min_height;
6350 if (flags & GDK_HINT_RESIZE_INC)
6352 width_inc = geometry->width_inc;
6353 height_inc = geometry->height_inc;
6357 *width = MAX (*width * width_inc + base_width, min_width);
6359 *height = MAX (*height * height_inc + base_height, min_height);
6362 /* This function doesn't constrain to geometry hints */
6364 gtk_window_compute_configure_request_size (GtkWindow *window,
6365 GdkGeometry *geometry,
6370 GtkWindowPrivate *priv = window->priv;
6371 GtkRequisition requisition;
6372 GtkWindowGeometryInfo *info;
6376 * - we've done a size request
6379 widget = GTK_WIDGET (window);
6381 info = gtk_window_get_geometry_info (window, FALSE);
6383 if (priv->need_default_size)
6385 gtk_widget_get_preferred_size (widget, &requisition, NULL);
6387 /* Default to requisition */
6388 *width = requisition.width;
6389 *height = requisition.height;
6391 /* If window is empty so requests 0, default to random nonzero size */
6392 if (*width == 0 && *height == 0)
6398 /* Override requisition with default size */
6402 if (info->default_width > 0)
6403 *width = info->default_width;
6404 if (info->default_height > 0)
6405 *height = info->default_height;
6407 if (info->default_is_geometry)
6408 geometry_size_to_pixels (geometry, flags,
6409 info->default_width > 0 ? width : NULL,
6410 info->default_height > 0 ? height : NULL);
6415 GtkAllocation allocation;
6417 gtk_widget_get_allocation (widget, &allocation);
6419 /* Default to keeping current size */
6420 *width = allocation.width;
6421 *height = allocation.height;
6424 /* Override any size with gtk_window_resize() values */
6427 if (info->resize_width > 0)
6428 *width = info->resize_width;
6429 if (info->resize_height > 0)
6430 *height = info->resize_height;
6432 if (info->resize_is_geometry)
6433 geometry_size_to_pixels (geometry, flags,
6434 info->resize_width > 0 ? width : NULL,
6435 info->resize_height > 0 ? height : NULL);
6438 /* Don't ever request zero width or height, its not supported by
6439 gdk. The size allocation code will round it to 1 anyway but if
6440 we do it then the value returned from this function will is
6441 not comparable to the size allocation read from the GtkWindow. */
6442 *width = MAX (*width, 1);
6443 *height = MAX (*height, 1);
6446 static GtkWindowPosition
6447 get_effective_position (GtkWindow *window)
6449 GtkWindowPrivate *priv = window->priv;
6450 GtkWindowPosition pos = priv->position;
6452 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6453 (priv->transient_parent == NULL ||
6454 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6455 pos = GTK_WIN_POS_NONE;
6461 get_center_monitor_of_window (GtkWindow *window)
6463 /* We could try to sort out the relative positions of the monitors and
6464 * stuff, or we could just be losers and assume you have a row
6465 * or column of monitors.
6467 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6471 get_monitor_containing_pointer (GtkWindow *window)
6475 GdkScreen *window_screen;
6476 GdkScreen *pointer_screen;
6477 GdkDisplay *display;
6478 GdkDeviceManager *device_manager;
6481 window_screen = gtk_window_check_screen (window);
6482 display = gdk_screen_get_display (window_screen);
6483 device_manager = gdk_display_get_device_manager (display);
6484 pointer = gdk_device_manager_get_client_pointer (device_manager);
6486 gdk_display_get_device_state (display, pointer,
6490 if (pointer_screen == window_screen)
6491 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6499 center_window_on_monitor (GtkWindow *window,
6505 GdkRectangle monitor;
6508 monitor_num = get_monitor_containing_pointer (window);
6510 if (monitor_num == -1)
6511 monitor_num = get_center_monitor_of_window (window);
6513 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
6514 monitor_num, &monitor);
6516 *x = (monitor.width - w) / 2 + monitor.x;
6517 *y = (monitor.height - h) / 2 + monitor.y;
6519 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6520 * and WM decorations.
6534 if (extent > clamp_extent)
6536 *base = clamp_base + clamp_extent/2 - extent/2;
6537 else if (*base < clamp_base)
6539 else if (*base + extent > clamp_base + clamp_extent)
6540 *base = clamp_base + clamp_extent - extent;
6544 clamp_window_to_rectangle (gint *x,
6548 const GdkRectangle *rect)
6550 #ifdef DEBUGGING_OUTPUT
6551 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);
6554 /* If it is too large, center it. If it fits on the monitor but is
6555 * partially outside, move it to the closest edge. Do this
6556 * separately in x and y directions.
6558 clamp (x, w, rect->x, rect->width);
6559 clamp (y, h, rect->y, rect->height);
6560 #ifdef DEBUGGING_OUTPUT
6561 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6567 gtk_window_compute_configure_request (GtkWindow *window,
6568 GdkRectangle *request,
6569 GdkGeometry *geometry,
6572 GtkWindowPrivate *priv = window->priv;
6573 GdkGeometry new_geometry;
6577 GtkWindowPosition pos;
6578 GtkWidget *parent_widget;
6579 GtkWindowGeometryInfo *info;
6583 widget = GTK_WIDGET (window);
6585 screen = gtk_window_check_screen (window);
6587 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6588 gtk_window_compute_configure_request_size (window,
6589 &new_geometry, new_flags,
6590 (guint *)&w, (guint *)&h);
6592 gtk_window_constrain_size (window,
6593 &new_geometry, new_flags,
6597 parent_widget = (GtkWidget*) priv->transient_parent;
6599 pos = get_effective_position (window);
6600 info = gtk_window_get_geometry_info (window, FALSE);
6602 /* by default, don't change position requested */
6605 x = info->last.configure_request.x;
6606 y = info->last.configure_request.y;
6615 if (priv->need_default_position)
6618 /* FIXME this all interrelates with window gravity.
6619 * For most of them I think we want to set GRAVITY_CENTER.
6621 * Not sure how to go about that.
6626 /* here we are only handling CENTER_ALWAYS
6627 * as it relates to default positioning,
6628 * where it's equivalent to simply CENTER
6630 case GTK_WIN_POS_CENTER_ALWAYS:
6631 case GTK_WIN_POS_CENTER:
6632 center_window_on_monitor (window, w, h, &x, &y);
6635 case GTK_WIN_POS_CENTER_ON_PARENT:
6637 GtkAllocation allocation;
6638 GdkWindow *gdk_window;
6640 GdkRectangle monitor;
6643 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6645 gdk_window = gtk_widget_get_window (parent_widget);
6647 if (gdk_window != NULL)
6648 monitor_num = gdk_screen_get_monitor_at_window (screen,
6653 gdk_window_get_origin (gdk_window,
6656 gtk_widget_get_allocation (parent_widget, &allocation);
6657 x = ox + (allocation.width - w) / 2;
6658 y = oy + (allocation.height - h) / 2;
6660 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6661 * WM decorations. If parent wasn't on a monitor, just
6664 if (monitor_num >= 0)
6666 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6667 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6672 case GTK_WIN_POS_MOUSE:
6674 gint screen_width = gdk_screen_get_width (screen);
6675 gint screen_height = gdk_screen_get_height (screen);
6677 GdkRectangle monitor;
6678 GdkDisplay *display;
6679 GdkDeviceManager *device_manager;
6681 GdkScreen *pointer_screen;
6684 display = gdk_screen_get_display (screen);
6685 device_manager = gdk_display_get_device_manager (display);
6686 pointer = gdk_device_manager_get_client_pointer (device_manager);
6688 gdk_display_get_device_state (display, pointer,
6692 if (pointer_screen == screen)
6693 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6699 x = CLAMP (x, 0, screen_width - w);
6700 y = CLAMP (y, 0, screen_height - h);
6702 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6703 * WM decorations. Don't try to figure out what's going
6704 * on if the mouse wasn't inside a monitor.
6706 if (monitor_num >= 0)
6708 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6709 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6717 } /* if (priv->need_default_position) */
6719 if (priv->need_default_position && info &&
6720 info->initial_pos_set)
6722 x = info->initial_x;
6723 y = info->initial_y;
6724 gtk_window_constrain_position (window, w, h, &x, &y);
6730 request->height = h;
6733 *geometry = new_geometry;
6739 gtk_window_constrain_position (GtkWindow *window,
6745 GtkWindowPrivate *priv = window->priv;
6747 /* See long comments in gtk_window_move_resize()
6748 * on when it's safe to call this function.
6750 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6752 gint center_x, center_y;
6754 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6762 gtk_window_move_resize (GtkWindow *window)
6766 * First we determine whether any information has changed that would
6767 * cause us to revise our last configure request. If we would send
6768 * a different configure request from last time, then
6769 * configure_request_size_changed = TRUE or
6770 * configure_request_pos_changed = TRUE. configure_request_size_changed
6771 * may be true due to new hints, a gtk_window_resize(), or whatever.
6772 * configure_request_pos_changed may be true due to gtk_window_set_position()
6773 * or gtk_window_move().
6775 * If the configure request has changed, we send off a new one. To
6776 * ensure GTK+ invariants are maintained (resize queue does what it
6777 * should), we go ahead and size_allocate the requested size in this
6780 * If the configure request has not changed, we don't ever resend
6781 * it, because it could mean fighting the user or window manager.
6784 * To prepare the configure request, we come up with a base size/pos:
6785 * - the one from gtk_window_move()/gtk_window_resize()
6786 * - else default_width, default_height if we haven't ever
6788 * - else the size request if we haven't ever been mapped,
6789 * as a substitute default size
6790 * - else the current size of the window, as received from
6791 * configure notifies (i.e. the current allocation)
6793 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6794 * the position request to be centered.
6796 GtkWindowPrivate *priv = window->priv;
6797 GtkAllocation allocation;
6799 GtkContainer *container;
6800 GtkWindowGeometryInfo *info;
6801 GdkGeometry new_geometry;
6802 GdkWindow *gdk_window;
6804 GdkRectangle new_request;
6805 gboolean configure_request_size_changed;
6806 gboolean configure_request_pos_changed;
6807 gboolean hints_changed; /* do we need to send these again */
6808 GtkWindowLastGeometryInfo saved_last_info;
6810 widget = GTK_WIDGET (window);
6811 gdk_window = gtk_widget_get_window (widget);
6812 container = GTK_CONTAINER (widget);
6813 info = gtk_window_get_geometry_info (window, TRUE);
6815 configure_request_size_changed = FALSE;
6816 configure_request_pos_changed = FALSE;
6818 gtk_window_compute_configure_request (window, &new_request,
6819 &new_geometry, &new_flags);
6821 /* This check implies the invariant that we never set info->last
6822 * without setting the hints and sending off a configure request.
6824 * If we change info->last without sending the request, we may
6827 if (info->last.configure_request.x != new_request.x ||
6828 info->last.configure_request.y != new_request.y)
6829 configure_request_pos_changed = TRUE;
6831 if ((info->last.configure_request.width != new_request.width ||
6832 info->last.configure_request.height != new_request.height))
6833 configure_request_size_changed = TRUE;
6835 hints_changed = FALSE;
6837 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6838 &new_geometry, new_flags))
6840 hints_changed = TRUE;
6843 /* Position Constraints
6844 * ====================
6846 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6847 * a default. The other POS_ values are used only when the
6848 * window is shown, not after that.
6850 * However, we can't implement a position constraint as
6851 * "anytime the window size changes, center the window"
6852 * because this may well end up fighting the WM or user. In
6853 * fact it gets in an infinite loop with at least one WM.
6855 * Basically, applications are in no way in a position to
6856 * constrain the position of a window, with one exception:
6857 * override redirect windows. (Really the intended purpose
6858 * of CENTER_ALWAYS anyhow, I would think.)
6860 * So the way we implement this "constraint" is to say that when WE
6861 * cause a move or resize, i.e. we make a configure request changing
6862 * window size, we recompute the CENTER_ALWAYS position to reflect
6863 * the new window size, and include it in our request. Also, if we
6864 * just turned on CENTER_ALWAYS we snap to center with a new
6865 * request. Otherwise, if we are just NOTIFIED of a move or resize
6866 * done by someone else e.g. the window manager, we do NOT send a
6867 * new configure request.
6869 * For override redirect windows, this works fine; all window
6870 * sizes are from our configure requests. For managed windows,
6871 * it is at least semi-sane, though who knows what the
6872 * app author is thinking.
6875 /* This condition should be kept in sync with the condition later on
6876 * that determines whether we send a configure request. i.e. we
6877 * should do this position constraining anytime we were going to
6878 * send a configure request anyhow, plus when constraints have
6881 if (configure_request_pos_changed ||
6882 configure_request_size_changed ||
6884 info->position_constraints_changed)
6886 /* We request the constrained position if:
6887 * - we were changing position, and need to clamp
6888 * the change to the constraint
6889 * - we're changing the size anyway
6890 * - set_position() was called to toggle CENTER_ALWAYS on
6893 gtk_window_constrain_position (window,
6899 /* Update whether we need to request a move */
6900 if (info->last.configure_request.x != new_request.x ||
6901 info->last.configure_request.y != new_request.y)
6902 configure_request_pos_changed = TRUE;
6904 configure_request_pos_changed = FALSE;
6908 if (priv->type == GTK_WINDOW_TOPLEVEL)
6910 int notify_x, notify_y;
6912 /* this is the position from the last configure notify */
6913 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6915 g_message ("--- %s ---\n"
6916 "last : %d,%d\t%d x %d\n"
6917 "this : %d,%d\t%d x %d\n"
6918 "alloc : %d,%d\t%d x %d\n"
6920 "resize: \t%d x %d\n"
6921 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6922 "configure_notify_received: %d\n"
6923 "configure_request_count: %d\n"
6924 "position_constraints_changed: %d\n",
6925 priv->title ? priv->title : "(no title)",
6926 info->last.configure_request.x,
6927 info->last.configure_request.y,
6928 info->last.configure_request.width,
6929 info->last.configure_request.height,
6935 widget->allocation.width,
6936 widget->allocation.height,
6937 widget->requisition.width,
6938 widget->requisition.height,
6940 info->resize_height,
6941 configure_request_pos_changed,
6942 configure_request_size_changed,
6944 priv->configure_notify_received,
6945 priv->configure_request_count,
6946 info->position_constraints_changed);
6950 saved_last_info = info->last;
6951 info->last.geometry = new_geometry;
6952 info->last.flags = new_flags;
6953 info->last.configure_request = new_request;
6955 /* need to set PPosition so the WM will look at our position,
6956 * but we don't want to count PPosition coming and going as a hints
6957 * change for future iterations. So we saved info->last prior to
6961 /* Also, if the initial position was explicitly set, then we always
6962 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6966 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6967 * this is an initial map
6970 if ((configure_request_pos_changed ||
6971 info->initial_pos_set ||
6972 (priv->need_default_position &&
6973 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6974 (new_flags & GDK_HINT_POS) == 0)
6976 new_flags |= GDK_HINT_POS;
6977 hints_changed = TRUE;
6980 /* Set hints if necessary
6983 gdk_window_set_geometry_hints (gdk_window,
6987 gtk_widget_get_allocation (widget, &allocation);
6989 /* handle resizing/moving and widget tree allocation
6991 if (priv->configure_notify_received)
6993 /* If we have received a configure event since
6994 * the last time in this function, we need to
6995 * accept our new size and size_allocate child widgets.
6996 * (see gtk_window_configure_event() for more details).
6998 * 1 or more configure notifies may have been received.
6999 * Also, configure_notify_received will only be TRUE
7000 * if all expected configure notifies have been received
7001 * (one per configure request), as an optimization.
7004 priv->configure_notify_received = FALSE;
7006 /* gtk_window_configure_event() filled in widget->allocation */
7007 gtk_widget_size_allocate (widget, &allocation);
7009 set_grip_position (window);
7010 update_grip_visibility (window);
7012 gdk_window_process_updates (gdk_window, TRUE);
7014 gdk_window_configure_finished (gdk_window);
7016 /* If the configure request changed, it means that
7018 * 1) coincidentally changed hints or widget properties
7019 * impacting the configure request before getting
7020 * a configure notify, or
7021 * 2) some broken widget is changing its size request
7022 * during size allocation, resulting in
7023 * a false appearance of changed configure request.
7025 * For 1), we could just go ahead and ask for the
7026 * new size right now, but doing that for 2)
7027 * might well be fighting the user (and can even
7028 * trigger a loop). Since we really don't want to
7029 * do that, we requeue a resize in hopes that
7030 * by the time it gets handled, the child has seen
7031 * the light and is willing to go along with the
7032 * new size. (this happens for the zvt widget, since
7033 * the size_allocate() above will have stored the
7034 * requisition corresponding to the new size in the
7037 * This doesn't buy us anything for 1), but it shouldn't
7038 * hurt us too badly, since it is what would have
7039 * happened if we had gotten the configure event before
7040 * the new size had been set.
7043 if (configure_request_size_changed ||
7044 configure_request_pos_changed)
7046 /* Don't change the recorded last info after all, because we
7047 * haven't actually updated to the new info yet - we decided
7048 * to postpone our configure request until later.
7050 info->last = saved_last_info;
7052 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
7055 return; /* Bail out, we didn't really process the move/resize */
7057 else if ((configure_request_size_changed || hints_changed) &&
7058 (allocation.width != new_request.width || allocation.height != new_request.height))
7061 /* We are in one of the following situations:
7062 * A. configure_request_size_changed
7063 * our requisition has changed and we need a different window size,
7064 * so we request it from the window manager.
7065 * B. !configure_request_size_changed && hints_changed
7066 * the window manager rejects our size, but we have just changed the
7067 * window manager hints, so there's a chance our request will
7068 * be honoured this time, so we try again.
7070 * However, if the new requisition is the same as the current allocation,
7071 * we don't request it again, since we won't get a ConfigureNotify back from
7072 * the window manager unless it decides to change our requisition. If
7073 * we don't get the ConfigureNotify back, the resize queue will never be run.
7076 /* Now send the configure request */
7077 if (configure_request_pos_changed)
7081 gdk_window_move_resize (priv->frame,
7082 new_request.x - priv->frame_left,
7083 new_request.y - priv->frame_top,
7084 new_request.width + priv->frame_left + priv->frame_right,
7085 new_request.height + priv->frame_top + priv->frame_bottom);
7086 gdk_window_resize (gdk_window,
7087 new_request.width, new_request.height);
7090 gdk_window_move_resize (gdk_window,
7091 new_request.x, new_request.y,
7092 new_request.width, new_request.height);
7094 else /* only size changed */
7097 gdk_window_resize (priv->frame,
7098 new_request.width + priv->frame_left + priv->frame_right,
7099 new_request.height + priv->frame_top + priv->frame_bottom);
7100 gdk_window_resize (gdk_window,
7101 new_request.width, new_request.height);
7104 if (priv->type == GTK_WINDOW_POPUP)
7106 GtkAllocation allocation;
7108 /* Directly size allocate for override redirect (popup) windows. */
7111 allocation.width = new_request.width;
7112 allocation.height = new_request.height;
7114 gtk_widget_size_allocate (widget, &allocation);
7116 gdk_window_process_updates (gdk_window, TRUE);
7118 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7119 gtk_widget_queue_draw (widget);
7123 /* Increment the number of have-not-yet-received-notify requests */
7124 priv->configure_request_count += 1;
7125 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7127 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7128 * configure event in response to our resizing request.
7129 * the configure event will cause a new resize with
7130 * ->configure_notify_received=TRUE.
7131 * until then, we want to
7132 * - discard expose events
7133 * - coalesce resizes for our children
7134 * - defer any window resizes until the configure event arrived
7135 * to achieve this, we queue a resize for the window, but remove its
7136 * resizing handler, so resizing will not be handled from the next
7137 * idle handler but when the configure event arrives.
7139 * FIXME: we should also dequeue the pending redraws here, since
7140 * we handle those ourselves upon ->configure_notify_received==TRUE.
7142 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7144 gtk_widget_queue_resize_no_redraw (widget);
7145 _gtk_container_dequeue_resize_handler (container);
7151 /* Handle any position changes.
7153 if (configure_request_pos_changed)
7157 gdk_window_move (priv->frame,
7158 new_request.x - priv->frame_left,
7159 new_request.y - priv->frame_top);
7162 gdk_window_move (gdk_window,
7163 new_request.x, new_request.y);
7166 /* And run the resize queue.
7168 gtk_container_resize_children (container);
7171 /* We have now processed a move/resize since the last position
7172 * constraint change, setting of the initial position, or resize.
7173 * (Not resetting these flags here can lead to infinite loops for
7174 * GTK_RESIZE_IMMEDIATE containers)
7176 info->position_constraints_changed = FALSE;
7177 info->initial_pos_set = FALSE;
7178 info->resize_width = -1;
7179 info->resize_height = -1;
7182 /* Compare two sets of Geometry hints for equality.
7185 gtk_window_compare_hints (GdkGeometry *geometry_a,
7187 GdkGeometry *geometry_b,
7190 if (flags_a != flags_b)
7193 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7194 (geometry_a->min_width != geometry_b->min_width ||
7195 geometry_a->min_height != geometry_b->min_height))
7198 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7199 (geometry_a->max_width != geometry_b->max_width ||
7200 geometry_a->max_height != geometry_b->max_height))
7203 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7204 (geometry_a->base_width != geometry_b->base_width ||
7205 geometry_a->base_height != geometry_b->base_height))
7208 if ((flags_a & GDK_HINT_ASPECT) &&
7209 (geometry_a->min_aspect != geometry_b->min_aspect ||
7210 geometry_a->max_aspect != geometry_b->max_aspect))
7213 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7214 (geometry_a->width_inc != geometry_b->width_inc ||
7215 geometry_a->height_inc != geometry_b->height_inc))
7218 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7219 geometry_a->win_gravity != geometry_b->win_gravity)
7226 _gtk_window_constrain_size (GtkWindow *window,
7232 GtkWindowPrivate *priv;
7233 GtkWindowGeometryInfo *info;
7235 g_return_if_fail (GTK_IS_WINDOW (window));
7237 priv = window->priv;
7239 info = priv->geometry_info;
7242 GdkWindowHints flags = info->last.flags;
7243 GdkGeometry *geometry = &info->last.geometry;
7245 gtk_window_constrain_size (window,
7256 gtk_window_constrain_size (GtkWindow *window,
7257 GdkGeometry *geometry,
7264 gdk_window_constrain_size (geometry, flags, width, height,
7265 new_width, new_height);
7268 /* Compute the set of geometry hints and flags for a window
7269 * based on the application set geometry, and requisition
7270 * of the window. gtk_widget_get_preferred_size() must have been
7274 gtk_window_compute_hints (GtkWindow *window,
7275 GdkGeometry *new_geometry,
7278 GtkWindowPrivate *priv = window->priv;
7280 gint extra_width = 0;
7281 gint extra_height = 0;
7282 GtkWindowGeometryInfo *geometry_info;
7283 GtkRequisition requisition;
7285 widget = GTK_WIDGET (window);
7287 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7288 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7292 *new_flags = geometry_info->mask;
7293 *new_geometry = geometry_info->geometry;
7300 if (geometry_info && geometry_info->widget)
7302 /* If the geometry widget is set, then the hints really apply to that
7303 * widget. This is pretty much meaningless unless the window layout
7304 * is such that the rest of the window adds fixed size borders to
7305 * the geometry widget. Our job is to figure the size of the borders;
7306 * We do that by asking how big the toplevel would be if the
7307 * geometry widget was *really big*.
7310 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7311 * |GGGGG B| in the border can confuse things
7317 * |AAAAAAAAA | When the geometry widget is large, things are
7318 * |GGGGGGGGGGB| clearer.
7323 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7324 GtkRequisition requisition;
7325 int current_width, current_height;
7327 _gtk_widget_override_size_request (geometry_info->widget,
7328 TEMPORARY_SIZE, TEMPORARY_SIZE,
7329 ¤t_width, ¤t_height);
7330 gtk_widget_get_preferred_size (widget,
7331 &requisition, NULL);
7332 _gtk_widget_restore_size_request (geometry_info->widget,
7333 current_width, current_height);
7335 extra_width = requisition.width - TEMPORARY_SIZE;
7336 extra_height = requisition.height - TEMPORARY_SIZE;
7338 if (extra_width < 0 || extra_width < 0)
7340 g_warning("Toplevel size doesn't seem to directly depend on the "
7341 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7342 "The geometry widget might not be in the window, or it might not "
7343 "be packed into the window appropriately");
7344 extra_width = MAX(extra_width, 0);
7345 extra_height = MAX(extra_height, 0);
7347 #undef TEMPORARY_SIZE
7350 /* We don't want to set GDK_HINT_POS in here, we just set it
7351 * in gtk_window_move_resize() when we want the position
7355 if (*new_flags & GDK_HINT_BASE_SIZE)
7357 new_geometry->base_width += extra_width;
7358 new_geometry->base_height += extra_height;
7362 /* For simplicity, we always set the base hint, even when we
7363 * don't expect it to have any visible effect.
7364 * (Note: geometry_size_to_pixels() depends on this.)
7366 *new_flags |= GDK_HINT_BASE_SIZE;
7368 new_geometry->base_width = extra_width;
7369 new_geometry->base_height = extra_height;
7371 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7372 * base size is the minimum size */
7373 if (*new_flags & GDK_HINT_MIN_SIZE)
7375 if (new_geometry->min_width > 0)
7376 new_geometry->base_width += new_geometry->min_width;
7377 if (new_geometry->min_height > 0)
7378 new_geometry->base_height += new_geometry->min_height;
7382 if (*new_flags & GDK_HINT_MIN_SIZE)
7384 if (new_geometry->min_width < 0)
7385 new_geometry->min_width = requisition.width;
7387 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7389 if (new_geometry->min_height < 0)
7390 new_geometry->min_height = requisition.height;
7392 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7396 *new_flags |= GDK_HINT_MIN_SIZE;
7398 new_geometry->min_width = requisition.width;
7399 new_geometry->min_height = requisition.height;
7402 if (*new_flags & GDK_HINT_MAX_SIZE)
7404 if (new_geometry->max_width < 0)
7405 new_geometry->max_width = requisition.width;
7407 new_geometry->max_width += extra_width;
7409 if (new_geometry->max_height < 0)
7410 new_geometry->max_height = requisition.height;
7412 new_geometry->max_height += extra_height;
7414 else if (!priv->resizable)
7416 *new_flags |= GDK_HINT_MAX_SIZE;
7418 new_geometry->max_width = requisition.width;
7419 new_geometry->max_height = requisition.height;
7422 *new_flags |= GDK_HINT_WIN_GRAVITY;
7423 new_geometry->win_gravity = priv->gravity;
7426 /***********************
7427 * Redrawing functions *
7428 ***********************/
7431 gtk_window_draw (GtkWidget *widget,
7434 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7435 gboolean ret = FALSE;
7437 if (!gtk_widget_get_app_paintable (widget))
7438 gtk_paint_flat_box (gtk_widget_get_style (widget),
7441 GTK_SHADOW_NONE, widget, "base",
7443 gtk_widget_get_allocated_width (widget),
7444 gtk_widget_get_allocated_height (widget));
7446 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7447 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7449 if (priv->grip_window != NULL &&
7450 gtk_cairo_should_draw_window (cr, priv->grip_window))
7455 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7456 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7457 gtk_paint_resize_grip (gtk_widget_get_style (widget),
7459 gtk_widget_get_state (widget),
7462 get_grip_edge (widget),
7464 rect.width, rect.height);
7472 * gtk_window_set_has_frame:
7473 * @window: a #GtkWindow
7474 * @setting: a boolean
7476 * (Note: this is a special-purpose function for the framebuffer port,
7477 * that causes GTK+ to draw its own window border. For most applications,
7478 * you want gtk_window_set_decorated() instead, which tells the window
7479 * manager whether to draw the window border.)
7481 * If this function is called on a window with setting of %TRUE, before
7482 * it is realized or showed, it will have a "frame" window around
7483 * @window->window, accessible in @window->frame. Using the signal
7484 * frame_event you can receive all events targeted at the frame.
7486 * This function is used by the linux-fb port to implement managed
7487 * windows, but it could conceivably be used by X-programs that
7488 * want to do their own window decorations.
7492 gtk_window_set_has_frame (GtkWindow *window,
7495 GtkWindowPrivate *priv;
7497 g_return_if_fail (GTK_IS_WINDOW (window));
7498 g_return_if_fail (!gtk_widget_get_realized (GTK_WIDGET (window)));
7500 priv = window->priv;
7502 priv->has_frame = setting != FALSE;
7506 * gtk_window_get_has_frame:
7507 * @window: a #GtkWindow
7509 * Accessor for whether the window has a frame window exterior to
7510 * @window->window. Gets the value set by gtk_window_set_has_frame ().
7512 * Return value: %TRUE if a frame has been added to the window
7513 * via gtk_window_set_has_frame().
7516 gtk_window_get_has_frame (GtkWindow *window)
7518 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7520 return window->priv->has_frame;
7524 * gtk_window_set_frame_dimensions:
7525 * @window: a #GtkWindow that has a frame
7526 * @left: The width of the left border
7527 * @top: The height of the top border
7528 * @right: The width of the right border
7529 * @bottom: The height of the bottom border
7531 * (Note: this is a special-purpose function intended for the framebuffer
7532 * port; see gtk_window_set_has_frame(). It will have no effect on the
7533 * window border drawn by the window manager, which is the normal
7534 * case when using the X Window system.)
7536 * For windows with frames (see gtk_window_set_has_frame()) this function
7537 * can be used to change the size of the frame border.
7540 gtk_window_set_frame_dimensions (GtkWindow *window,
7546 GtkWindowPrivate *priv;
7547 GtkAllocation allocation;
7550 g_return_if_fail (GTK_IS_WINDOW (window));
7552 priv = window->priv;
7553 widget = GTK_WIDGET (window);
7555 if (priv->frame_left == left &&
7556 priv->frame_top == top &&
7557 priv->frame_right == right &&
7558 priv->frame_bottom == bottom)
7561 priv->frame_left = left;
7562 priv->frame_top = top;
7563 priv->frame_right = right;
7564 priv->frame_bottom = bottom;
7566 if (gtk_widget_get_realized (widget) && priv->frame)
7569 gtk_widget_get_allocation (widget, &allocation);
7571 width = allocation.width + left + right;
7572 height = allocation.height + top + bottom;
7573 gdk_window_resize (priv->frame, width, height);
7574 gtk_decorated_window_move_resize_window (window,
7582 * gtk_window_present:
7583 * @window: a #GtkWindow
7585 * Presents a window to the user. This may mean raising the window
7586 * in the stacking order, deiconifying it, moving it to the current
7587 * desktop, and/or giving it the keyboard focus, possibly dependent
7588 * on the user's platform, window manager, and preferences.
7590 * If @window is hidden, this function calls gtk_widget_show()
7593 * This function should be used when the user tries to open a window
7594 * that's already open. Say for example the preferences dialog is
7595 * currently open, and the user chooses Preferences from the menu
7596 * a second time; use gtk_window_present() to move the already-open dialog
7597 * where the user can see it.
7599 * If you are calling this function in response to a user interaction,
7600 * it is preferable to use gtk_window_present_with_time().
7604 gtk_window_present (GtkWindow *window)
7606 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7610 * gtk_window_present_with_time:
7611 * @window: a #GtkWindow
7612 * @timestamp: the timestamp of the user interaction (typically a
7613 * button or key press event) which triggered this call
7615 * Presents a window to the user in response to a user interaction.
7616 * If you need to present a window without a timestamp, use
7617 * gtk_window_present(). See gtk_window_present() for details.
7622 gtk_window_present_with_time (GtkWindow *window,
7626 GdkWindow *gdk_window;
7628 g_return_if_fail (GTK_IS_WINDOW (window));
7630 widget = GTK_WIDGET (window);
7632 if (gtk_widget_get_visible (widget))
7634 gdk_window = gtk_widget_get_window (widget);
7636 g_assert (gdk_window != NULL);
7638 gdk_window_show (gdk_window);
7640 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7641 if (timestamp == GDK_CURRENT_TIME)
7643 #ifdef GDK_WINDOWING_X11
7644 GdkDisplay *display;
7646 display = gtk_widget_get_display (GTK_WIDGET (window));
7647 timestamp = gdk_x11_display_get_user_time (display);
7649 timestamp = gtk_get_current_event_time ();
7653 gdk_window_focus (gdk_window, timestamp);
7657 gtk_widget_show (widget);
7662 * gtk_window_iconify:
7663 * @window: a #GtkWindow
7665 * Asks to iconify (i.e. minimize) the specified @window. Note that
7666 * you shouldn't assume the window is definitely iconified afterward,
7667 * because other entities (e.g. the user or <link
7668 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7669 * again, or there may not be a window manager in which case
7670 * iconification isn't possible, etc. But normally the window will end
7671 * up iconified. Just don't write code that crashes if not.
7673 * It's permitted to call this function before showing a window,
7674 * in which case the window will be iconified before it ever appears
7677 * You can track iconification via the "window-state-event" signal
7682 gtk_window_iconify (GtkWindow *window)
7684 GtkWindowPrivate *priv;
7686 GdkWindow *toplevel;
7688 g_return_if_fail (GTK_IS_WINDOW (window));
7690 priv = window->priv;
7691 widget = GTK_WIDGET (window);
7693 priv->iconify_initially = TRUE;
7696 toplevel = priv->frame;
7698 toplevel = gtk_widget_get_window (widget);
7700 if (toplevel != NULL)
7701 gdk_window_iconify (toplevel);
7705 * gtk_window_deiconify:
7706 * @window: a #GtkWindow
7708 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7709 * that you shouldn't assume the window is definitely deiconified
7710 * afterward, because other entities (e.g. the user or <link
7711 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7712 * again before your code which assumes deiconification gets to run.
7714 * You can track iconification via the "window-state-event" signal
7718 gtk_window_deiconify (GtkWindow *window)
7720 GtkWindowPrivate *priv;
7722 GdkWindow *toplevel;
7724 g_return_if_fail (GTK_IS_WINDOW (window));
7726 priv = window->priv;
7727 widget = GTK_WIDGET (window);
7729 priv->iconify_initially = FALSE;
7732 toplevel = priv->frame;
7734 toplevel = gtk_widget_get_window (widget);
7736 if (toplevel != NULL)
7737 gdk_window_deiconify (toplevel);
7742 * @window: a #GtkWindow
7744 * Asks to stick @window, which means that it will appear on all user
7745 * desktops. Note that you shouldn't assume the window is definitely
7746 * stuck afterward, because other entities (e.g. the user or <link
7747 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7748 * again, and some window managers do not support sticking
7749 * windows. But normally the window will end up stuck. Just don't
7750 * write code that crashes if not.
7752 * It's permitted to call this function before showing a window.
7754 * You can track stickiness via the "window-state-event" signal
7759 gtk_window_stick (GtkWindow *window)
7761 GtkWindowPrivate *priv;
7763 GdkWindow *toplevel;
7765 g_return_if_fail (GTK_IS_WINDOW (window));
7767 priv = window->priv;
7768 widget = GTK_WIDGET (window);
7770 priv->stick_initially = TRUE;
7773 toplevel = priv->frame;
7775 toplevel = gtk_widget_get_window (widget);
7777 if (toplevel != NULL)
7778 gdk_window_stick (toplevel);
7782 * gtk_window_unstick:
7783 * @window: a #GtkWindow
7785 * Asks to unstick @window, which means that it will appear on only
7786 * one of the user's desktops. Note that you shouldn't assume the
7787 * window is definitely unstuck afterward, because other entities
7788 * (e.g. the user or <link linkend="gtk-X11-arch">window
7789 * manager</link>) could stick it again. But normally the window will
7790 * end up stuck. Just don't write code that crashes if not.
7792 * You can track stickiness via the "window-state-event" signal
7797 gtk_window_unstick (GtkWindow *window)
7799 GtkWindowPrivate *priv;
7801 GdkWindow *toplevel;
7803 g_return_if_fail (GTK_IS_WINDOW (window));
7805 priv = window->priv;
7806 widget = GTK_WIDGET (window);
7808 priv->stick_initially = FALSE;
7811 toplevel = priv->frame;
7813 toplevel = gtk_widget_get_window (widget);
7815 if (toplevel != NULL)
7816 gdk_window_unstick (toplevel);
7820 * gtk_window_maximize:
7821 * @window: a #GtkWindow
7823 * Asks to maximize @window, so that it becomes full-screen. Note that
7824 * you shouldn't assume the window is definitely maximized afterward,
7825 * because other entities (e.g. the user or <link
7826 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7827 * again, and not all window managers support maximization. But
7828 * normally the window will end up maximized. Just don't write code
7829 * that crashes if not.
7831 * It's permitted to call this function before showing a window,
7832 * in which case the window will be maximized when it appears onscreen
7835 * You can track maximization via the "window-state-event" signal
7840 gtk_window_maximize (GtkWindow *window)
7842 GtkWindowPrivate *priv;
7844 GdkWindow *toplevel;
7846 g_return_if_fail (GTK_IS_WINDOW (window));
7848 priv = window->priv;
7849 widget = GTK_WIDGET (window);
7851 priv->maximize_initially = TRUE;
7854 toplevel = priv->frame;
7856 toplevel = gtk_widget_get_window (widget);
7858 if (toplevel != NULL)
7859 gdk_window_maximize (toplevel);
7863 * gtk_window_unmaximize:
7864 * @window: a #GtkWindow
7866 * Asks to unmaximize @window. Note that you shouldn't assume the
7867 * window is definitely unmaximized afterward, because other entities
7868 * (e.g. the user or <link linkend="gtk-X11-arch">window
7869 * manager</link>) could maximize it again, and not all window
7870 * managers honor requests to unmaximize. But normally the window will
7871 * end up unmaximized. Just don't write code that crashes if not.
7873 * You can track maximization via the "window-state-event" signal
7878 gtk_window_unmaximize (GtkWindow *window)
7880 GtkWindowPrivate *priv;
7882 GdkWindow *toplevel;
7884 g_return_if_fail (GTK_IS_WINDOW (window));
7886 priv = window->priv;
7887 widget = GTK_WIDGET (window);
7889 priv->maximize_initially = FALSE;
7892 toplevel = priv->frame;
7894 toplevel = gtk_widget_get_window (widget);
7896 if (toplevel != NULL)
7897 gdk_window_unmaximize (toplevel);
7901 * gtk_window_fullscreen:
7902 * @window: a #GtkWindow
7904 * Asks to place @window in the fullscreen state. Note that you
7905 * shouldn't assume the window is definitely full screen afterward,
7906 * because other entities (e.g. the user or <link
7907 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7908 * again, and not all window managers honor requests to fullscreen
7909 * windows. But normally the window will end up fullscreen. Just
7910 * don't write code that crashes if not.
7912 * You can track the fullscreen state via the "window-state-event" signal
7918 gtk_window_fullscreen (GtkWindow *window)
7920 GtkWindowPrivate *priv;
7922 GdkWindow *toplevel;
7924 g_return_if_fail (GTK_IS_WINDOW (window));
7926 priv = window->priv;
7927 widget = GTK_WIDGET (window);
7929 priv->fullscreen_initially = TRUE;
7932 toplevel = priv->frame;
7934 toplevel = gtk_widget_get_window (widget);
7936 if (toplevel != NULL)
7937 gdk_window_fullscreen (toplevel);
7941 * gtk_window_unfullscreen:
7942 * @window: a #GtkWindow
7944 * Asks to toggle off the fullscreen state for @window. Note that you
7945 * shouldn't assume the window is definitely not full screen
7946 * afterward, because other entities (e.g. the user or <link
7947 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7948 * again, and not all window managers honor requests to unfullscreen
7949 * windows. But normally the window will end up restored to its normal
7950 * state. Just don't write code that crashes if not.
7952 * You can track the fullscreen state via the "window-state-event" signal
7958 gtk_window_unfullscreen (GtkWindow *window)
7961 GdkWindow *toplevel;
7962 GtkWindowPrivate *priv;
7964 g_return_if_fail (GTK_IS_WINDOW (window));
7966 priv = window->priv;
7967 widget = GTK_WIDGET (window);
7969 priv->fullscreen_initially = FALSE;
7972 toplevel = priv->frame;
7974 toplevel = gtk_widget_get_window (widget);
7976 if (toplevel != NULL)
7977 gdk_window_unfullscreen (toplevel);
7981 * gtk_window_set_keep_above:
7982 * @window: a #GtkWindow
7983 * @setting: whether to keep @window above other windows
7985 * Asks to keep @window above, so that it stays on top. Note that
7986 * you shouldn't assume the window is definitely above afterward,
7987 * because other entities (e.g. the user or <link
7988 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7989 * and not all window managers support keeping windows above. But
7990 * normally the window will end kept above. Just don't write code
7991 * that crashes if not.
7993 * It's permitted to call this function before showing a window,
7994 * in which case the window will be kept above when it appears onscreen
7997 * You can track the above state via the "window-state-event" signal
8000 * Note that, according to the <ulink
8001 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8002 * Manager Hints</ulink> specification, the above state is mainly meant
8003 * for user preferences and should not be used by applications e.g. for
8004 * drawing attention to their dialogs.
8009 gtk_window_set_keep_above (GtkWindow *window,
8013 GtkWindowPrivate *priv;
8014 GdkWindow *toplevel;
8016 g_return_if_fail (GTK_IS_WINDOW (window));
8018 priv = window->priv;
8019 widget = GTK_WIDGET (window);
8021 priv->above_initially = setting != FALSE;
8023 priv->below_initially = FALSE;
8026 toplevel = priv->frame;
8028 toplevel = gtk_widget_get_window (widget);
8030 if (toplevel != NULL)
8031 gdk_window_set_keep_above (toplevel, setting);
8035 * gtk_window_set_keep_below:
8036 * @window: a #GtkWindow
8037 * @setting: whether to keep @window below other windows
8039 * Asks to keep @window below, so that it stays in bottom. Note that
8040 * you shouldn't assume the window is definitely below afterward,
8041 * because other entities (e.g. the user or <link
8042 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
8043 * and not all window managers support putting windows below. But
8044 * normally the window will be kept below. Just don't write code
8045 * that crashes if not.
8047 * It's permitted to call this function before showing a window,
8048 * in which case the window will be kept below when it appears onscreen
8051 * You can track the below state via the "window-state-event" signal
8054 * Note that, according to the <ulink
8055 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8056 * Manager Hints</ulink> specification, the above state is mainly meant
8057 * for user preferences and should not be used by applications e.g. for
8058 * drawing attention to their dialogs.
8063 gtk_window_set_keep_below (GtkWindow *window,
8067 GtkWindowPrivate *priv;
8068 GdkWindow *toplevel;
8070 g_return_if_fail (GTK_IS_WINDOW (window));
8072 priv = window->priv;
8073 widget = GTK_WIDGET (window);
8075 priv->below_initially = setting != FALSE;
8077 priv->above_initially = FALSE;
8080 toplevel = priv->frame;
8082 toplevel = gtk_widget_get_window (widget);
8084 if (toplevel != NULL)
8085 gdk_window_set_keep_below (toplevel, setting);
8089 * gtk_window_set_resizable:
8090 * @window: a #GtkWindow
8091 * @resizable: %TRUE if the user can resize this window
8093 * Sets whether the user can resize a window. Windows are user resizable
8097 gtk_window_set_resizable (GtkWindow *window,
8100 GtkWindowPrivate *priv;
8102 g_return_if_fail (GTK_IS_WINDOW (window));
8104 priv = window->priv;
8106 resizable = (resizable != FALSE);
8108 if (priv->resizable != resizable)
8110 priv->resizable = (resizable != FALSE);
8112 update_grip_visibility (window);
8114 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8116 g_object_notify (G_OBJECT (window), "resizable");
8121 * gtk_window_get_resizable:
8122 * @window: a #GtkWindow
8124 * Gets the value set by gtk_window_set_resizable().
8126 * Return value: %TRUE if the user can resize the window
8129 gtk_window_get_resizable (GtkWindow *window)
8131 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8133 return window->priv->resizable;
8137 * gtk_window_set_gravity:
8138 * @window: a #GtkWindow
8139 * @gravity: window gravity
8141 * Window gravity defines the meaning of coordinates passed to
8142 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
8145 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
8146 * typically "do what you mean."
8150 gtk_window_set_gravity (GtkWindow *window,
8153 GtkWindowPrivate *priv;
8155 g_return_if_fail (GTK_IS_WINDOW (window));
8157 priv = window->priv;
8159 if (gravity != priv->gravity)
8161 priv->gravity = gravity;
8163 /* gtk_window_move_resize() will adapt gravity
8165 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8167 g_object_notify (G_OBJECT (window), "gravity");
8172 * gtk_window_get_gravity:
8173 * @window: a #GtkWindow
8175 * Gets the value set by gtk_window_set_gravity().
8177 * Return value: (transfer none): window gravity
8180 gtk_window_get_gravity (GtkWindow *window)
8182 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
8184 return window->priv->gravity;
8188 * gtk_window_begin_resize_drag:
8189 * @window: a #GtkWindow
8190 * @button: mouse button that initiated the drag
8191 * @edge: position of the resize control
8192 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8193 * @root_y: Y position where the user clicked to initiate the drag
8194 * @timestamp: timestamp from the click event that initiated the drag
8196 * Starts resizing a window. This function is used if an application
8197 * has window resizing controls. When GDK can support it, the resize
8198 * will be done using the standard mechanism for the <link
8199 * linkend="gtk-X11-arch">window manager</link> or windowing
8200 * system. Otherwise, GDK will try to emulate window resizing,
8201 * potentially not all that well, depending on the windowing system.
8205 gtk_window_begin_resize_drag (GtkWindow *window,
8212 GtkWindowPrivate *priv;
8214 GdkWindow *toplevel;
8216 g_return_if_fail (GTK_IS_WINDOW (window));
8217 widget = GTK_WIDGET (window);
8218 g_return_if_fail (gtk_widget_get_visible (widget));
8220 priv = window->priv;
8223 toplevel = priv->frame;
8225 toplevel = gtk_widget_get_window (widget);
8227 gdk_window_begin_resize_drag (toplevel,
8234 * gtk_window_get_frame_dimensions:
8235 * @window: a #GtkWindow
8236 * @left: (out) (allow-none): location to store the width of the frame at the left, or %NULL
8237 * @top: (out) (allow-none): location to store the height of the frame at the top, or %NULL
8238 * @right: (out) (allow-none): location to store the width of the frame at the returns, or %NULL
8239 * @bottom: (out) (allow-none): location to store the height of the frame at the bottom, or %NULL
8241 * (Note: this is a special-purpose function intended for the
8242 * framebuffer port; see gtk_window_set_has_frame(). It will not
8243 * return the size of the window border drawn by the <link
8244 * linkend="gtk-X11-arch">window manager</link>, which is the normal
8245 * case when using a windowing system. See
8246 * gdk_window_get_frame_extents() to get the standard window border
8249 * Retrieves the dimensions of the frame window for this toplevel.
8250 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
8253 gtk_window_get_frame_dimensions (GtkWindow *window,
8259 GtkWindowPrivate *priv;
8261 g_return_if_fail (GTK_IS_WINDOW (window));
8263 priv = window->priv;
8266 *left = priv->frame_left;
8268 *top = priv->frame_top;
8270 *right = priv->frame_right;
8272 *bottom = priv->frame_bottom;
8276 * gtk_window_begin_move_drag:
8277 * @window: a #GtkWindow
8278 * @button: mouse button that initiated the drag
8279 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8280 * @root_y: Y position where the user clicked to initiate the drag
8281 * @timestamp: timestamp from the click event that initiated the drag
8283 * Starts moving a window. This function is used if an application has
8284 * window movement grips. When GDK can support it, the window movement
8285 * will be done using the standard mechanism for the <link
8286 * linkend="gtk-X11-arch">window manager</link> or windowing
8287 * system. Otherwise, GDK will try to emulate window movement,
8288 * potentially not all that well, depending on the windowing system.
8292 gtk_window_begin_move_drag (GtkWindow *window,
8298 GtkWindowPrivate *priv;
8300 GdkWindow *toplevel;
8302 g_return_if_fail (GTK_IS_WINDOW (window));
8303 widget = GTK_WIDGET (window);
8304 g_return_if_fail (gtk_widget_get_visible (widget));
8306 priv = window->priv;
8309 toplevel = priv->frame;
8311 toplevel = gtk_widget_get_window (widget);
8313 gdk_window_begin_move_drag (toplevel,
8320 * gtk_window_set_screen:
8321 * @window: a #GtkWindow.
8322 * @screen: a #GdkScreen.
8324 * Sets the #GdkScreen where the @window is displayed; if
8325 * the window is already mapped, it will be unmapped, and
8326 * then remapped on the new screen.
8331 gtk_window_set_screen (GtkWindow *window,
8334 GtkWindowPrivate *priv;
8336 GdkScreen *previous_screen;
8337 gboolean was_mapped;
8339 g_return_if_fail (GTK_IS_WINDOW (window));
8340 g_return_if_fail (GDK_IS_SCREEN (screen));
8342 priv = window->priv;
8344 if (screen == priv->screen)
8347 widget = GTK_WIDGET (window);
8349 previous_screen = priv->screen;
8350 was_mapped = gtk_widget_get_mapped (widget);
8353 gtk_widget_unmap (widget);
8354 if (gtk_widget_get_realized (widget))
8355 gtk_widget_unrealize (widget);
8357 gtk_window_free_key_hash (window);
8358 priv->screen = screen;
8359 gtk_widget_reset_rc_styles (widget);
8360 if (screen != previous_screen)
8362 g_signal_handlers_disconnect_by_func (previous_screen,
8363 gtk_window_on_composited_changed, window);
8364 g_signal_connect (screen, "composited-changed",
8365 G_CALLBACK (gtk_window_on_composited_changed), window);
8367 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8368 _gtk_widget_propagate_composited_changed (widget);
8370 g_object_notify (G_OBJECT (window), "screen");
8373 gtk_widget_map (widget);
8377 gtk_window_on_composited_changed (GdkScreen *screen,
8380 gtk_widget_queue_draw (GTK_WIDGET (window));
8382 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8386 gtk_window_check_screen (GtkWindow *window)
8388 GtkWindowPrivate *priv = window->priv;
8391 return priv->screen;
8394 g_warning ("Screen for GtkWindow not set; you must always set\n"
8395 "a screen for a GtkWindow before using the window");
8401 * gtk_window_get_screen:
8402 * @window: a #GtkWindow.
8404 * Returns the #GdkScreen associated with @window.
8406 * Return value: (transfer none): a #GdkScreen.
8411 gtk_window_get_screen (GtkWindow *window)
8413 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8415 return window->priv->screen;
8419 * gtk_window_is_active:
8420 * @window: a #GtkWindow
8422 * Returns whether the window is part of the current active toplevel.
8423 * (That is, the toplevel window receiving keystrokes.)
8424 * The return value is %TRUE if the window is active toplevel
8425 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8426 * You might use this function if you wanted to draw a widget
8427 * differently in an active window from a widget in an inactive window.
8428 * See gtk_window_has_toplevel_focus()
8430 * Return value: %TRUE if the window part of the current active window.
8435 gtk_window_is_active (GtkWindow *window)
8437 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8439 return window->priv->is_active;
8443 * gtk_window_has_toplevel_focus:
8444 * @window: a #GtkWindow
8446 * Returns whether the input focus is within this GtkWindow.
8447 * For real toplevel windows, this is identical to gtk_window_is_active(),
8448 * but for embedded windows, like #GtkPlug, the results will differ.
8450 * Return value: %TRUE if the input focus is within this GtkWindow
8455 gtk_window_has_toplevel_focus (GtkWindow *window)
8457 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8459 return window->priv->has_toplevel_focus;
8463 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8465 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8469 gtk_window_group_get_type (void)
8471 static GType window_group_type = 0;
8473 if (!window_group_type)
8475 const GTypeInfo window_group_info =
8477 sizeof (GtkWindowGroupClass),
8478 NULL, /* base_init */
8479 NULL, /* base_finalize */
8480 (GClassInitFunc) gtk_window_group_class_init,
8481 NULL, /* class_finalize */
8482 NULL, /* class_data */
8483 sizeof (GtkWindowGroup),
8484 0, /* n_preallocs */
8485 (GInstanceInitFunc) NULL,
8488 window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"),
8489 &window_group_info, 0);
8492 return window_group_type;
8496 * gtk_window_group_new:
8498 * Creates a new #GtkWindowGroup object. Grabs added with
8499 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8501 * Return value: a new #GtkWindowGroup.
8504 gtk_window_group_new (void)
8506 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8510 window_group_cleanup_grabs (GtkWindowGroup *group,
8513 GtkWindowGroupPrivate *priv;
8514 GtkDeviceGrabInfo *info;
8516 GSList *to_remove = NULL;
8518 tmp_list = group->grabs;
8521 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8522 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8523 tmp_list = tmp_list->next;
8528 gtk_grab_remove (to_remove->data);
8529 g_object_unref (to_remove->data);
8530 to_remove = g_slist_delete_link (to_remove, to_remove);
8533 priv = GTK_WINDOW_GROUP_GET_PRIVATE (group);
8534 tmp_list = priv->device_grabs;
8538 info = tmp_list->data;
8540 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8541 to_remove = g_slist_prepend (to_remove, info);
8543 tmp_list = tmp_list->next;
8548 info = to_remove->data;
8550 gtk_device_grab_remove (info->widget, info->device);
8551 to_remove = g_slist_delete_link (to_remove, to_remove);
8556 * gtk_window_group_add_window:
8557 * @window_group: a #GtkWindowGroup
8558 * @window: the #GtkWindow to add
8560 * Adds a window to a #GtkWindowGroup.
8563 gtk_window_group_add_window (GtkWindowGroup *window_group,
8566 GtkWindowPrivate *priv;
8568 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8569 g_return_if_fail (GTK_IS_WINDOW (window));
8571 priv = window->priv;
8573 if (priv->group != window_group)
8575 g_object_ref (window);
8576 g_object_ref (window_group);
8579 gtk_window_group_remove_window (priv->group, window);
8581 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8583 priv->group = window_group;
8585 g_object_unref (window);
8590 * gtk_window_group_remove_window:
8591 * @window_group: a #GtkWindowGroup
8592 * @window: the #GtkWindow to remove
8594 * Removes a window from a #GtkWindowGroup.
8597 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8600 GtkWindowPrivate *priv;
8602 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8603 g_return_if_fail (GTK_IS_WINDOW (window));
8604 priv = window->priv;
8605 g_return_if_fail (priv->group == window_group);
8607 g_object_ref (window);
8609 window_group_cleanup_grabs (window_group, window);
8612 g_object_unref (window_group);
8613 g_object_unref (window);
8617 * gtk_window_group_list_windows:
8618 * @window_group: a #GtkWindowGroup
8620 * Returns a list of the #GtkWindows that belong to @window_group.
8622 * Returns: (element-type GtkWidget) (transfer container): A newly-allocated list of
8623 * windows inside the group.
8628 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8630 GList *toplevels, *toplevel, *group_windows;
8632 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8634 group_windows = NULL;
8635 toplevels = gtk_window_list_toplevels ();
8637 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8639 GtkWindow *window = toplevel->data;
8641 if (window_group == window->priv->group)
8642 group_windows = g_list_prepend (group_windows, window);
8645 return g_list_reverse (group_windows);
8649 * gtk_window_get_group:
8650 * @window: (allow-none): a #GtkWindow, or %NULL
8652 * Returns the group for @window or the default group, if
8653 * @window is %NULL or if @window does not have an explicit
8656 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8661 gtk_window_get_group (GtkWindow *window)
8663 if (window && window->priv->group)
8664 return window->priv->group;
8667 static GtkWindowGroup *default_group = NULL;
8670 default_group = gtk_window_group_new ();
8672 return default_group;
8677 * gtk_window_has_group:
8678 * @window: a #GtkWindow
8680 * Returns whether @window has an explicit window group.
8682 * Return value: %TRUE if @window has an explicit window group.
8687 gtk_window_has_group (GtkWindow *window)
8689 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8691 return window->priv->group != NULL;
8695 * gtk_window_group_get_current_grab:
8696 * @window_group: a #GtkWindowGroup
8698 * Gets the current grab widget of the given group,
8699 * see gtk_grab_add().
8701 * Returns: the current grab widget of the group
8706 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8708 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8710 if (window_group->grabs)
8711 return GTK_WIDGET (window_group->grabs->data);
8716 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8719 gboolean block_others)
8721 GtkWindowGroupPrivate *priv;
8722 GtkDeviceGrabInfo *info;
8724 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8726 info = g_slice_new0 (GtkDeviceGrabInfo);
8727 info->widget = widget;
8728 info->device = device;
8729 info->block_others = block_others;
8731 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8735 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8739 GtkWindowGroupPrivate *priv;
8740 GtkDeviceGrabInfo *info;
8741 GSList *list, *node = NULL;
8742 GdkDevice *other_device;
8744 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8745 other_device = gdk_device_get_associated_device (device);
8746 list = priv->device_grabs;
8752 if (info->widget == widget &&
8753 (info->device == device ||
8754 info->device == other_device))
8767 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8768 g_slice_free (GtkDeviceGrabInfo, info);
8773 * gtk_window_group_get_current_device_grab:
8774 * @window_group: a #GtkWindowGroup
8775 * @device: a #GdkDevice
8777 * Returns the current grab widget for @device, or %NULL if none.
8779 * Returns: The grab widget, or %NULL
8784 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8787 GtkWindowGroupPrivate *priv;
8788 GtkDeviceGrabInfo *info;
8789 GdkDevice *other_device;
8792 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8793 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8795 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8796 list = priv->device_grabs;
8797 other_device = gdk_device_get_associated_device (device);
8804 if (info->device == device ||
8805 info->device == other_device)
8806 return info->widget;
8813 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8817 GtkWindowGroupPrivate *priv;
8818 GtkDeviceGrabInfo *info;
8819 GdkDevice *other_device;
8822 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8823 other_device = gdk_device_get_associated_device (device);
8824 list = priv->device_grabs;
8831 /* Look for blocking grabs on other device pairs
8832 * that have the passed widget within the GTK+ grab.
8834 if (info->block_others &&
8835 info->device != device &&
8836 info->device != other_device &&
8837 (info->widget == widget ||
8838 gtk_widget_is_ancestor (widget, info->widget)))
8846 Derived from XParseGeometry() in XFree86
8848 Copyright 1985, 1986, 1987,1998 The Open Group
8850 All Rights Reserved.
8852 The above copyright notice and this permission notice shall be included
8853 in all copies or substantial portions of the Software.
8855 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8856 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8857 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8858 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8859 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8860 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8861 OTHER DEALINGS IN THE SOFTWARE.
8863 Except as contained in this notice, the name of The Open Group shall
8864 not be used in advertising or otherwise to promote the sale, use or
8865 other dealings in this Software without prior written authorization
8866 from The Open Group.
8871 * XParseGeometry parses strings of the form
8872 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8873 * width, height, xoffset, and yoffset are unsigned integers.
8874 * Example: "=80x24+300-49"
8875 * The equal sign is optional.
8876 * It returns a bitmask that indicates which of the four values
8877 * were actually found in the string. For each value found,
8878 * the corresponding argument is updated; for each value
8879 * not found, the corresponding argument is left unchanged.
8882 /* The following code is from Xlib, and is minimally modified, so we
8883 * can track any upstream changes if required. Don't change this
8884 * code. Or if you do, put in a huge comment marking which thing
8889 read_int (gchar *string,
8897 else if (*string == '-')
8903 for (; (*string >= '0') && (*string <= '9'); string++)
8905 result = (result * 10) + (*string - '0');
8917 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8918 * value (x, y, width, height) was found in the parsed string.
8920 #define NoValue 0x0000
8921 #define XValue 0x0001
8922 #define YValue 0x0002
8923 #define WidthValue 0x0004
8924 #define HeightValue 0x0008
8925 #define AllValues 0x000F
8926 #define XNegative 0x0010
8927 #define YNegative 0x0020
8929 /* Try not to reformat/modify, so we can compare/sync with X sources */
8931 gtk_XParseGeometry (const char *string,
8934 unsigned int *width,
8935 unsigned int *height)
8939 unsigned int tempWidth, tempHeight;
8941 char *nextCharacter;
8943 /* These initializations are just to silence gcc */
8949 if ( (string == NULL) || (*string == '\0')) return(mask);
8951 string++; /* ignore possible '=' at beg of geometry spec */
8953 strind = (char *)string;
8954 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8955 tempWidth = read_int(strind, &nextCharacter);
8956 if (strind == nextCharacter)
8958 strind = nextCharacter;
8962 if (*strind == 'x' || *strind == 'X') {
8964 tempHeight = read_int(strind, &nextCharacter);
8965 if (strind == nextCharacter)
8967 strind = nextCharacter;
8968 mask |= HeightValue;
8971 if ((*strind == '+') || (*strind == '-')) {
8972 if (*strind == '-') {
8974 tempX = -read_int(strind, &nextCharacter);
8975 if (strind == nextCharacter)
8977 strind = nextCharacter;
8983 tempX = read_int(strind, &nextCharacter);
8984 if (strind == nextCharacter)
8986 strind = nextCharacter;
8989 if ((*strind == '+') || (*strind == '-')) {
8990 if (*strind == '-') {
8992 tempY = -read_int(strind, &nextCharacter);
8993 if (strind == nextCharacter)
8995 strind = nextCharacter;
9002 tempY = read_int(strind, &nextCharacter);
9003 if (strind == nextCharacter)
9005 strind = nextCharacter;
9011 /* If strind isn't at the end of the string the it's an invalid
9012 geometry specification. */
9014 if (*strind != '\0') return (0);
9020 if (mask & WidthValue)
9022 if (mask & HeightValue)
9023 *height = tempHeight;
9028 * gtk_window_parse_geometry:
9029 * @window: a #GtkWindow
9030 * @geometry: geometry string
9032 * Parses a standard X Window System geometry string - see the
9033 * manual page for X (type 'man X') for details on this.
9034 * gtk_window_parse_geometry() does work on all GTK+ ports
9035 * including Win32 but is primarily intended for an X environment.
9037 * If either a size or a position can be extracted from the
9038 * geometry string, gtk_window_parse_geometry() returns %TRUE
9039 * and calls gtk_window_set_default_size() and/or gtk_window_move()
9040 * to resize/move the window.
9042 * If gtk_window_parse_geometry() returns %TRUE, it will also
9043 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
9044 * indicating to the window manager that the size/position of
9045 * the window was user-specified. This causes most window
9046 * managers to honor the geometry.
9048 * Note that for gtk_window_parse_geometry() to work as expected, it has
9049 * to be called when the window has its "final" size, i.e. after calling
9050 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
9053 * #include <gtk/gtk.h>
9056 * fill_with_content (GtkWidget *vbox)
9058 * /* fill with content... */
9062 * main (int argc, char *argv[])
9064 * GtkWidget *window, *vbox;
9065 * GdkGeometry size_hints = {
9066 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
9069 * gtk_init (&argc, &argv);
9071 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9072 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
9074 * gtk_container_add (GTK_CONTAINER (window), vbox);
9075 * fill_with_content (vbox);
9076 * gtk_widget_show_all (vbox);
9078 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
9081 * GDK_HINT_MIN_SIZE |
9082 * GDK_HINT_BASE_SIZE |
9083 * GDK_HINT_RESIZE_INC);
9087 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
9088 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
9091 * gtk_widget_show_all (window);
9098 * Return value: %TRUE if string was parsed successfully
9101 gtk_window_parse_geometry (GtkWindow *window,
9102 const gchar *geometry)
9104 gint result, x = 0, y = 0;
9108 gboolean size_set, pos_set;
9111 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9112 g_return_val_if_fail (geometry != NULL, FALSE);
9114 child = gtk_bin_get_child (GTK_BIN (window));
9115 if (!child || !gtk_widget_get_visible (child))
9116 g_warning ("gtk_window_parse_geometry() called on a window with no "
9117 "visible children; the window should be set up before "
9118 "gtk_window_parse_geometry() is called.");
9120 screen = gtk_window_check_screen (window);
9122 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
9125 if ((result & WidthValue) || (result & HeightValue))
9127 gtk_window_set_default_size_internal (window,
9128 TRUE, result & WidthValue ? w : -1,
9129 TRUE, result & HeightValue ? h : -1,
9134 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
9136 grav = GDK_GRAVITY_NORTH_WEST;
9138 if ((result & XNegative) && (result & YNegative))
9139 grav = GDK_GRAVITY_SOUTH_EAST;
9140 else if (result & XNegative)
9141 grav = GDK_GRAVITY_NORTH_EAST;
9142 else if (result & YNegative)
9143 grav = GDK_GRAVITY_SOUTH_WEST;
9145 if ((result & XValue) == 0)
9148 if ((result & YValue) == 0)
9151 if (grav == GDK_GRAVITY_SOUTH_WEST ||
9152 grav == GDK_GRAVITY_SOUTH_EAST)
9153 y = gdk_screen_get_height (screen) - h + y;
9155 if (grav == GDK_GRAVITY_SOUTH_EAST ||
9156 grav == GDK_GRAVITY_NORTH_EAST)
9157 x = gdk_screen_get_width (screen) - w + x;
9159 /* we don't let you put a window offscreen; maybe some people would
9160 * prefer to be able to, but it's kind of a bogus thing to do.
9169 if ((result & XValue) || (result & YValue))
9171 gtk_window_set_gravity (window, grav);
9172 gtk_window_move (window, x, y);
9176 if (size_set || pos_set)
9178 /* Set USSize, USPosition hints */
9179 GtkWindowGeometryInfo *info;
9181 info = gtk_window_get_geometry_info (window, TRUE);
9184 info->mask |= GDK_HINT_USER_POS;
9186 info->mask |= GDK_HINT_USER_SIZE;
9193 gtk_window_mnemonic_hash_foreach (guint keyval,
9199 GtkWindowKeysForeachFunc func;
9203 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
9207 _gtk_window_keys_foreach (GtkWindow *window,
9208 GtkWindowKeysForeachFunc func,
9212 GtkMnemonicHash *mnemonic_hash;
9216 GtkWindowKeysForeachFunc func;
9220 info.window = window;
9222 info.func_data = func_data;
9224 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
9226 _gtk_mnemonic_hash_foreach (mnemonic_hash,
9227 gtk_window_mnemonic_hash_foreach, &info);
9229 groups = gtk_accel_groups_from_object (G_OBJECT (window));
9232 GtkAccelGroup *group = groups->data;
9235 for (i = 0; i < group->priv->n_accels; i++)
9237 GtkAccelKey *key = &group->priv->priv_accels[i].key;
9240 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
9243 groups = groups->next;
9248 gtk_window_keys_changed (GtkWindow *window)
9250 gtk_window_free_key_hash (window);
9251 gtk_window_get_key_hash (window);
9254 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
9256 struct _GtkWindowKeyEntry
9260 guint is_mnemonic : 1;
9264 window_key_entry_destroy (gpointer data)
9266 g_slice_free (GtkWindowKeyEntry, data);
9270 add_to_key_hash (GtkWindow *window,
9272 GdkModifierType modifiers,
9273 gboolean is_mnemonic,
9276 GtkKeyHash *key_hash = data;
9278 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9280 entry->keyval = keyval;
9281 entry->modifiers = modifiers;
9282 entry->is_mnemonic = is_mnemonic;
9284 /* GtkAccelGroup stores lowercased accelerators. To deal
9285 * with this, if <Shift> was specified, uppercase.
9287 if (modifiers & GDK_SHIFT_MASK)
9289 if (keyval == GDK_KEY_Tab)
9290 keyval = GDK_KEY_ISO_Left_Tab;
9292 keyval = gdk_keyval_to_upper (keyval);
9295 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9299 gtk_window_get_key_hash (GtkWindow *window)
9301 GdkScreen *screen = gtk_window_check_screen (window);
9302 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9307 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9308 (GDestroyNotify)window_key_entry_destroy);
9309 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9310 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9316 gtk_window_free_key_hash (GtkWindow *window)
9318 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9321 _gtk_key_hash_free (key_hash);
9322 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9327 * gtk_window_activate_key:
9328 * @window: a #GtkWindow
9329 * @event: a #GdkEventKey
9331 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9332 * called by the default ::key_press_event handler for toplevel windows,
9333 * however in some cases it may be useful to call this directly when
9334 * overriding the standard key handling for a toplevel window.
9336 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9341 gtk_window_activate_key (GtkWindow *window,
9344 GtkKeyHash *key_hash;
9345 GtkWindowKeyEntry *found_entry = NULL;
9346 gboolean enable_mnemonics;
9347 gboolean enable_accels;
9349 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9350 g_return_val_if_fail (event != NULL, FALSE);
9352 key_hash = gtk_window_get_key_hash (window);
9357 GSList *entries = _gtk_key_hash_lookup (key_hash,
9358 event->hardware_keycode,
9360 gtk_accelerator_get_default_mod_mask (),
9363 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9364 "gtk-enable-mnemonics", &enable_mnemonics,
9365 "gtk-enable-accels", &enable_accels,
9368 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9370 GtkWindowKeyEntry *entry = tmp_list->data;
9371 if (entry->is_mnemonic)
9373 if (enable_mnemonics)
9375 found_entry = entry;
9381 if (enable_accels && !found_entry)
9383 found_entry = entry;
9388 g_slist_free (entries);
9393 if (found_entry->is_mnemonic)
9395 if (enable_mnemonics)
9396 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9397 found_entry->modifiers);
9402 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9403 found_entry->modifiers);
9411 window_update_has_focus (GtkWindow *window)
9413 GtkWindowPrivate *priv = window->priv;
9414 GtkWidget *widget = GTK_WIDGET (window);
9415 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9417 if (has_focus != priv->has_focus)
9419 priv->has_focus = has_focus;
9423 if (priv->focus_widget &&
9424 priv->focus_widget != widget &&
9425 !gtk_widget_has_focus (priv->focus_widget))
9426 do_focus_change (priv->focus_widget, TRUE);
9430 if (priv->focus_widget &&
9431 priv->focus_widget != widget &&
9432 gtk_widget_has_focus (priv->focus_widget))
9433 do_focus_change (priv->focus_widget, FALSE);
9439 * _gtk_window_set_is_active:
9440 * @window: a #GtkWindow
9441 * @is_active: %TRUE if the window is in the currently active toplevel
9443 * Internal function that sets whether the #GtkWindow is part
9444 * of the currently active toplevel window (taking into account inter-process
9448 _gtk_window_set_is_active (GtkWindow *window,
9451 GtkWindowPrivate *priv;
9453 g_return_if_fail (GTK_IS_WINDOW (window));
9455 priv = window->priv;
9457 is_active = is_active != FALSE;
9459 if (is_active != priv->is_active)
9461 priv->is_active = is_active;
9462 window_update_has_focus (window);
9464 g_object_notify (G_OBJECT (window), "is-active");
9469 * _gtk_window_set_is_toplevel:
9470 * @window: a #GtkWindow
9471 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9472 * parent of the root window); %FALSE if it is not (for example, for an
9473 * in-process, parented GtkPlug)
9475 * Internal function used by #GtkPlug when it gets parented/unparented by a
9476 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9477 * global list of toplevel windows.
9480 _gtk_window_set_is_toplevel (GtkWindow *window,
9481 gboolean is_toplevel)
9485 widget = GTK_WIDGET (window);
9487 if (gtk_widget_is_toplevel (widget))
9488 g_assert (g_slist_find (toplevel_list, window) != NULL);
9490 g_assert (g_slist_find (toplevel_list, window) == NULL);
9492 if (is_toplevel == gtk_widget_is_toplevel (widget))
9497 _gtk_widget_set_is_toplevel (widget, TRUE);
9498 toplevel_list = g_slist_prepend (toplevel_list, window);
9502 _gtk_widget_set_is_toplevel (widget, FALSE);
9503 toplevel_list = g_slist_remove (toplevel_list, window);
9508 * _gtk_window_set_has_toplevel_focus:
9509 * @window: a #GtkWindow
9510 * @has_toplevel_focus: %TRUE if the in
9512 * Internal function that sets whether the keyboard focus for the
9513 * toplevel window (taking into account inter-process embedding.)
9516 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9517 gboolean has_toplevel_focus)
9519 GtkWindowPrivate *priv;
9521 g_return_if_fail (GTK_IS_WINDOW (window));
9523 priv = window->priv;
9525 has_toplevel_focus = has_toplevel_focus != FALSE;
9527 if (has_toplevel_focus != priv->has_toplevel_focus)
9529 priv->has_toplevel_focus = has_toplevel_focus;
9530 window_update_has_focus (window);
9532 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9537 * gtk_window_set_auto_startup_notification:
9538 * @setting: %TRUE to automatically do startup notification
9540 * By default, after showing the first #GtkWindow, GTK+ calls
9541 * gdk_notify_startup_complete(). Call this function to disable
9542 * the automatic startup notification. You might do this if your
9543 * first window is a splash screen, and you want to delay notification
9544 * until after your real main window has been shown, for example.
9546 * In that example, you would disable startup notification
9547 * temporarily, show your splash screen, then re-enable it so that
9548 * showing the main window would automatically result in notification.
9553 gtk_window_set_auto_startup_notification (gboolean setting)
9555 disable_startup_notification = !setting;
9559 * gtk_window_get_window_type:
9560 * @window: a #GtkWindow
9562 * Gets the type of the window. See #GtkWindowType.
9564 * Return value: the type of the window
9569 gtk_window_get_window_type (GtkWindow *window)
9571 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9573 return window->priv->type;
9577 * gtk_window_get_mnemonics_visible:
9578 * @window: a #GtkWindow
9580 * Gets the value of the #GtkWindow:mnemonics-visible property.
9582 * Returns: %TRUE if mnemonics are supposed to be visible
9588 gtk_window_get_mnemonics_visible (GtkWindow *window)
9590 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9592 return window->priv->mnemonics_visible;
9596 * gtk_window_set_mnemonics_visible:
9597 * @window: a #GtkWindow
9598 * @setting: the new value
9600 * Sets the #GtkWindow:mnemonics-visible property.
9605 gtk_window_set_mnemonics_visible (GtkWindow *window,
9608 GtkWindowPrivate *priv;
9610 g_return_if_fail (GTK_IS_WINDOW (window));
9612 priv = window->priv;
9614 setting = setting != FALSE;
9616 if (priv->mnemonics_visible != setting)
9618 priv->mnemonics_visible = setting;
9619 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9622 priv->mnemonics_visible_set = TRUE;
9626 _gtk_window_get_wmclass (GtkWindow *window,
9627 gchar **wmclass_name,
9628 gchar **wmclass_class)
9630 GtkWindowPrivate *priv = window->priv;
9632 *wmclass_name = priv->wmclass_name;
9633 *wmclass_class = priv->wmclass_class;