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/.
30 #include "gdk/gdkkeysyms.h"
32 #if defined (GDK_WINDOWING_X11)
34 #elif defined (GDK_WINDOWING_WIN32)
35 #include "win32/gdkwin32.h"
36 #elif defined (GDK_WINDOWING_NANOX)
37 #include "nanox/gdkprivate-nanox.h"
38 #elif defined (GDK_WINDOWING_FB)
39 #include "linux-fb/gdkfb.h"
42 #include "gtkprivate.h"
44 #include "gtksignal.h"
45 #include "gtkwindow.h"
46 #include "gtkwindow-decorate.h"
47 #include "gtkbindings.h"
49 #include "gtkiconfactory.h"
76 PROP_DESTROY_WITH_PARENT,
85 GdkPixmap *icon_pixmap;
88 guint using_default_icon : 1;
89 guint using_parent_icon : 1;
93 GdkGeometry geometry; /* Last set of geometry hints we set */
95 GdkRectangle configure_request;
96 } GtkWindowLastGeometryInfo;
98 struct _GtkWindowGeometryInfo
100 /* Properties that the app has set on the window
102 GdkGeometry geometry; /* Geometry hints */
104 GtkWidget *widget; /* subwidget to which hints apply */
105 /* from last gtk_window_resize () - if > 0, indicates that
106 * we should resize to this size.
111 /* From last gtk_window_move () prior to mapping -
112 * only used if initial_pos_set
117 /* Default size - used only the FIRST time we map a window,
122 /* whether to use initial_x, initial_y */
123 guint initial_pos_set : 1;
124 /* CENTER_ALWAYS or other position constraint changed since
125 * we sent the last configure request.
127 guint position_constraints_changed : 1;
129 GtkWindowLastGeometryInfo last;
140 static void gtk_window_class_init (GtkWindowClass *klass);
141 static void gtk_window_init (GtkWindow *window);
142 static void gtk_window_dispose (GObject *object);
143 static void gtk_window_destroy (GtkObject *object);
144 static void gtk_window_finalize (GObject *object);
145 static void gtk_window_show (GtkWidget *widget);
146 static void gtk_window_hide (GtkWidget *widget);
147 static void gtk_window_map (GtkWidget *widget);
148 static void gtk_window_unmap (GtkWidget *widget);
149 static void gtk_window_realize (GtkWidget *widget);
150 static void gtk_window_unrealize (GtkWidget *widget);
151 static void gtk_window_size_request (GtkWidget *widget,
152 GtkRequisition *requisition);
153 static void gtk_window_size_allocate (GtkWidget *widget,
154 GtkAllocation *allocation);
155 static gint gtk_window_event (GtkWidget *widget,
157 static gboolean gtk_window_frame_event (GtkWidget *widget,
159 static gint gtk_window_configure_event (GtkWidget *widget,
160 GdkEventConfigure *event);
161 static gint gtk_window_key_press_event (GtkWidget *widget,
163 static gint gtk_window_key_release_event (GtkWidget *widget,
165 static gint gtk_window_enter_notify_event (GtkWidget *widget,
166 GdkEventCrossing *event);
167 static gint gtk_window_leave_notify_event (GtkWidget *widget,
168 GdkEventCrossing *event);
169 static gint gtk_window_focus_in_event (GtkWidget *widget,
170 GdkEventFocus *event);
171 static gint gtk_window_focus_out_event (GtkWidget *widget,
172 GdkEventFocus *event);
173 static gint gtk_window_client_event (GtkWidget *widget,
174 GdkEventClient *event);
175 static void gtk_window_check_resize (GtkContainer *container);
176 static gint gtk_window_focus (GtkWidget *widget,
177 GtkDirectionType direction);
178 static void gtk_window_real_set_focus (GtkWindow *window,
181 static void gtk_window_real_activate_default (GtkWindow *window);
182 static void gtk_window_real_activate_focus (GtkWindow *window);
183 static void gtk_window_move_focus (GtkWindow *window,
184 GtkDirectionType dir);
185 static void gtk_window_read_rcfiles (GtkWidget *widget,
186 GdkEventClient *event);
187 static void gtk_window_paint (GtkWidget *widget,
189 static gint gtk_window_expose (GtkWidget *widget,
190 GdkEventExpose *event);
191 static void gtk_window_unset_transient_for (GtkWindow *window);
192 static void gtk_window_transient_parent_realized (GtkWidget *parent,
194 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
197 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
200 static void gtk_window_move_resize (GtkWindow *window);
201 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
203 GdkGeometry *geometry_b,
205 static void gtk_window_constrain_size (GtkWindow *window,
206 GdkGeometry *geometry,
212 static void gtk_window_constrain_position (GtkWindow *window,
217 static void gtk_window_compute_hints (GtkWindow *window,
218 GdkGeometry *new_geometry,
220 static void gtk_window_compute_configure_request (GtkWindow *window,
221 GdkRectangle *request,
222 GdkGeometry *geometry,
225 static void gtk_window_set_default_size_internal (GtkWindow *window,
226 gboolean change_width,
228 gboolean change_height,
231 static void gtk_window_realize_icon (GtkWindow *window);
232 static void gtk_window_unrealize_icon (GtkWindow *window);
234 static GSList *toplevel_list = NULL;
235 static GHashTable *mnemonic_hash_table = NULL;
236 static GtkBinClass *parent_class = NULL;
237 static guint window_signals[LAST_SIGNAL] = { 0 };
238 static GList *default_icon_list = NULL;
239 /* FIXME need to be per-screen */
240 static GdkPixmap *default_icon_pixmap = NULL;
241 static GdkPixmap *default_icon_mask = NULL;
243 static void gtk_window_set_property (GObject *object,
247 static void gtk_window_get_property (GObject *object,
254 mnemonic_hash (gconstpointer key)
256 const GtkWindowMnemonic *k;
259 k = (GtkWindowMnemonic *)key;
261 h = (gulong) k->window;
262 h ^= k->keyval << 16;
263 h ^= k->keyval >> 16;
269 mnemonic_equal (gconstpointer a, gconstpointer b)
271 const GtkWindowMnemonic *ka;
272 const GtkWindowMnemonic *kb;
274 ka = (GtkWindowMnemonic *)a;
275 kb = (GtkWindowMnemonic *)b;
278 (ka->window == kb->window) &&
279 (ka->keyval == kb->keyval);
283 gtk_window_get_type (void)
285 static GtkType window_type = 0;
289 static const GtkTypeInfo window_info =
293 sizeof (GtkWindowClass),
294 (GtkClassInitFunc) gtk_window_class_init,
295 (GtkObjectInitFunc) gtk_window_init,
296 /* reserved_1 */ NULL,
297 /* reserved_2 */ NULL,
298 (GtkClassInitFunc) NULL,
301 window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
308 gtk_window_class_init (GtkWindowClass *klass)
310 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
311 GtkObjectClass *object_class;
312 GtkWidgetClass *widget_class;
313 GtkContainerClass *container_class;
314 GtkBindingSet *binding_set;
316 object_class = (GtkObjectClass*) klass;
317 widget_class = (GtkWidgetClass*) klass;
318 container_class = (GtkContainerClass*) klass;
320 parent_class = gtk_type_class (gtk_bin_get_type ());
322 gobject_class->dispose = gtk_window_dispose;
323 gobject_class->finalize = gtk_window_finalize;
325 gobject_class->set_property = gtk_window_set_property;
326 gobject_class->get_property = gtk_window_get_property;
328 object_class->destroy = gtk_window_destroy;
330 widget_class->show = gtk_window_show;
331 widget_class->hide = gtk_window_hide;
332 widget_class->map = gtk_window_map;
333 widget_class->unmap = gtk_window_unmap;
334 widget_class->realize = gtk_window_realize;
335 widget_class->unrealize = gtk_window_unrealize;
336 widget_class->size_request = gtk_window_size_request;
337 widget_class->size_allocate = gtk_window_size_allocate;
338 widget_class->configure_event = gtk_window_configure_event;
339 widget_class->key_press_event = gtk_window_key_press_event;
340 widget_class->key_release_event = gtk_window_key_release_event;
341 widget_class->enter_notify_event = gtk_window_enter_notify_event;
342 widget_class->leave_notify_event = gtk_window_leave_notify_event;
343 widget_class->focus_in_event = gtk_window_focus_in_event;
344 widget_class->focus_out_event = gtk_window_focus_out_event;
345 widget_class->client_event = gtk_window_client_event;
346 widget_class->focus = gtk_window_focus;
348 widget_class->expose_event = gtk_window_expose;
350 container_class->check_resize = gtk_window_check_resize;
352 klass->set_focus = gtk_window_real_set_focus;
353 klass->frame_event = gtk_window_frame_event;
355 klass->activate_default = gtk_window_real_activate_default;
356 klass->activate_focus = gtk_window_real_activate_focus;
357 klass->move_focus = gtk_window_move_focus;
360 g_object_class_install_property (gobject_class,
362 g_param_spec_enum ("type",
364 _("The type of the window"),
365 GTK_TYPE_WINDOW_TYPE,
367 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
370 g_object_class_install_property (gobject_class,
372 g_param_spec_string ("title",
374 _("The title of the window"),
378 g_object_class_install_property (gobject_class,
380 g_param_spec_boolean ("allow_shrink",
382 _("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea."),
386 g_object_class_install_property (gobject_class,
388 g_param_spec_boolean ("allow_grow",
390 _("If TRUE, users can expand the window beyond its minimum size."),
394 g_object_class_install_property (gobject_class,
396 g_param_spec_boolean ("resizable",
398 _("If TRUE, users can resize the window."),
402 g_object_class_install_property (gobject_class,
404 g_param_spec_boolean ("modal",
406 _("If TRUE, the window is modal (other windows are not usable while this one is up)."),
410 g_object_class_install_property (gobject_class,
412 g_param_spec_enum ("window_position",
413 _("Window Position"),
414 _("The initial position of the window."),
415 GTK_TYPE_WINDOW_POSITION,
419 g_object_class_install_property (gobject_class,
421 g_param_spec_int ("default_width",
423 _("The default width of the window, used when initially showing the window."),
429 g_object_class_install_property (gobject_class,
431 g_param_spec_int ("default_height",
433 _("The default height of the window, used when initially showing the window."),
439 g_object_class_install_property (gobject_class,
440 PROP_DESTROY_WITH_PARENT,
441 g_param_spec_boolean ("destroy_with_parent",
442 _("Destroy with Parent"),
443 _("If this window should be destroyed when the parent is destroyed"),
447 g_object_class_install_property (gobject_class,
449 g_param_spec_object ("icon",
451 _("Icon for this window"),
455 window_signals[SET_FOCUS] =
456 g_signal_new ("set_focus",
457 G_TYPE_FROM_CLASS (object_class),
459 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
461 gtk_marshal_VOID__OBJECT,
465 window_signals[FRAME_EVENT] =
466 g_signal_new ("frame_event",
467 G_TYPE_FROM_CLASS(object_class),
469 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
470 _gtk_boolean_handled_accumulator, NULL,
471 gtk_marshal_BOOLEAN__BOXED,
475 window_signals[ACTIVATE_FOCUS] =
476 g_signal_new ("activate_focus",
477 G_OBJECT_CLASS_TYPE (object_class),
478 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
479 GTK_SIGNAL_OFFSET (GtkWindowClass, activate_focus),
481 gtk_marshal_VOID__VOID,
485 window_signals[ACTIVATE_DEFAULT] =
486 g_signal_new ("activate_default",
487 G_OBJECT_CLASS_TYPE (object_class),
488 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
489 GTK_SIGNAL_OFFSET (GtkWindowClass, activate_default),
491 gtk_marshal_VOID__VOID,
495 window_signals[MOVE_FOCUS] =
496 g_signal_new ("move_focus",
497 G_OBJECT_CLASS_TYPE (object_class),
498 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
499 GTK_SIGNAL_OFFSET (GtkWindowClass, move_focus),
501 gtk_marshal_VOID__ENUM,
504 GTK_TYPE_DIRECTION_TYPE);
506 if (!mnemonic_hash_table)
507 mnemonic_hash_table = g_hash_table_new (mnemonic_hash,
514 binding_set = gtk_binding_set_by_class (klass);
516 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
517 "activate_focus", 0);
518 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
519 "activate_focus", 0);
521 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
522 "activate_default", 0);
524 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
525 "activate_default", 0);
527 gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
529 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_UP);
530 gtk_binding_entry_add_signal (binding_set, GDK_KP_Up, 0,
532 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_UP);
534 gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
536 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_DOWN);
537 gtk_binding_entry_add_signal (binding_set, GDK_KP_Down, 0,
539 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_DOWN);
541 gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
543 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_LEFT);
544 gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, 0,
546 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_LEFT);
548 gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
550 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_RIGHT);
551 gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, 0,
553 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_RIGHT);
555 gtk_binding_entry_add_signal (binding_set, GDK_Tab, 0,
557 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
558 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, 0,
560 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
561 gtk_binding_entry_add_signal (binding_set, GDK_ISO_Left_Tab, 0,
563 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
565 gtk_binding_entry_add_signal (binding_set, GDK_Tab, GDK_SHIFT_MASK,
567 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
568 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, GDK_SHIFT_MASK,
570 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
571 gtk_binding_entry_add_signal (binding_set, GDK_ISO_Left_Tab, GDK_SHIFT_MASK,
573 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
577 gtk_window_init (GtkWindow *window)
579 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
580 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
582 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
584 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
586 window->title = NULL;
587 window->wmclass_name = g_strdup (g_get_prgname ());
588 window->wmclass_class = g_strdup (gdk_progclass);
589 window->wm_role = NULL;
590 window->geometry_info = NULL;
591 window->type = GTK_WINDOW_TOPLEVEL;
592 window->focus_widget = NULL;
593 window->default_widget = NULL;
594 window->configure_request_count = 0;
595 window->allow_shrink = FALSE;
596 window->allow_grow = TRUE;
597 window->configure_notify_received = FALSE;
598 window->position = GTK_WIN_POS_NONE;
599 window->need_default_size = TRUE;
600 window->need_default_position = TRUE;
601 window->modal = FALSE;
602 window->frame = NULL;
603 window->has_frame = FALSE;
604 window->frame_left = 0;
605 window->frame_right = 0;
606 window->frame_top = 0;
607 window->frame_bottom = 0;
608 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
609 window->gravity = GDK_GRAVITY_NORTH_WEST;
610 window->decorated = TRUE;
611 window->mnemonic_modifier = GDK_MOD1_MASK;
613 gtk_widget_ref (GTK_WIDGET (window));
614 gtk_object_sink (GTK_OBJECT (window));
615 window->has_user_ref_count = TRUE;
616 toplevel_list = g_slist_prepend (toplevel_list, window);
618 gtk_decorated_window_init (window);
620 gtk_signal_connect (GTK_OBJECT (window),
622 GTK_SIGNAL_FUNC (gtk_window_event),
627 gtk_window_set_property (GObject *object,
634 window = GTK_WINDOW (object);
639 window->type = g_value_get_enum (value);
642 gtk_window_set_title (window, g_value_get_string (value));
644 case PROP_ALLOW_SHRINK:
645 window->allow_shrink = g_value_get_boolean (value);
646 gtk_widget_queue_resize (GTK_WIDGET (window));
648 case PROP_ALLOW_GROW:
649 window->allow_grow = g_value_get_boolean (value);
650 gtk_widget_queue_resize (GTK_WIDGET (window));
651 g_object_notify (G_OBJECT (window), "resizable");
654 window->allow_grow = g_value_get_boolean (value);
655 gtk_widget_queue_resize (GTK_WIDGET (window));
656 g_object_notify (G_OBJECT (window), "allow_grow");
659 gtk_window_set_modal (window, g_value_get_boolean (value));
662 gtk_window_set_position (window, g_value_get_enum (value));
664 case PROP_DEFAULT_WIDTH:
665 gtk_window_set_default_size_internal (window,
666 TRUE, g_value_get_int (value),
669 case PROP_DEFAULT_HEIGHT:
670 gtk_window_set_default_size_internal (window,
672 TRUE, g_value_get_int (value));
674 case PROP_DESTROY_WITH_PARENT:
675 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
678 gtk_window_set_icon (window,
679 g_value_get_object (value));
688 gtk_window_get_property (GObject *object,
695 window = GTK_WINDOW (object);
699 GtkWindowGeometryInfo *info;
701 g_value_set_enum (value, window->type);
704 g_value_set_string (value, window->title);
706 case PROP_ALLOW_SHRINK:
707 g_value_set_boolean (value, window->allow_shrink);
709 case PROP_ALLOW_GROW:
710 g_value_set_boolean (value, window->allow_grow);
713 g_value_set_boolean (value, window->allow_grow);
716 g_value_set_boolean (value, window->modal);
719 g_value_set_enum (value, window->position);
721 case PROP_DEFAULT_WIDTH:
722 info = gtk_window_get_geometry_info (window, FALSE);
724 g_value_set_int (value, -1);
726 g_value_set_int (value, info->default_width);
728 case PROP_DEFAULT_HEIGHT:
729 info = gtk_window_get_geometry_info (window, FALSE);
731 g_value_set_int (value, -1);
733 g_value_set_int (value, info->default_height);
735 case PROP_DESTROY_WITH_PARENT:
736 g_value_set_boolean (value, window->destroy_with_parent);
739 g_value_set_object (value,
740 G_OBJECT (gtk_window_get_icon (window)));
743 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
750 * @type: type of window
752 * Creates a new #GtkWindow, which is a toplevel window that can
753 * contain other widgets. Nearly always, the type of the window should
754 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
755 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
756 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
757 * dialogs, though in some other toolkits dialogs are called "popups."
758 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
759 * Popup windows are not controlled by the window manager.
761 * If you simply want an undecorated window (no window borders), use
762 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
764 * Return value: a new #GtkWindow.
767 gtk_window_new (GtkWindowType type)
771 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
773 window = gtk_type_new (GTK_TYPE_WINDOW);
777 return GTK_WIDGET (window);
781 * gtk_window_set_title:
782 * @window: a #GtkWindow
783 * @title: title of the window
785 * Sets the title of the #GtkWindow. The title of a window will be displayed in
786 * its title bar; on the X Window System, the title bar is rendered by the
787 * window manager, so exactly how the title appears to users may vary according
788 * to a user's exact configuration. The title should help a user distinguish
789 * this window from other windows they may have open. A good title might
790 * include the application name and current document filename, for example.
794 gtk_window_set_title (GtkWindow *window,
797 g_return_if_fail (GTK_IS_WINDOW (window));
800 g_free (window->title);
801 window->title = g_strdup (title);
803 if (GTK_WIDGET_REALIZED (window))
805 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
807 gtk_decorated_window_set_title (window, title);
810 g_object_notify (G_OBJECT (window), "title");
814 * gtk_window_get_title:
815 * @window: a #GtkWindow
817 * Retrieves the title of the window. See gtk_window_set_title().
819 * Return value: the title of the window, or %NULL if none has
820 * been set explicitely. The returned string is owned by the widget
821 * and must not be modified or freed.
823 G_CONST_RETURN gchar *
824 gtk_window_get_title (GtkWindow *window)
826 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
828 return window->title;
832 * gtk_window_set_wmclass:
833 * @window: a #GtkWindow
834 * @wmclass_name: window name hint
835 * @wmclass_class: window class hint
837 * Don't use this function. It sets the X Window System "class" and
838 * "name" hints for a window. According to the ICCCM, you should
839 * always set these to the same value for all windows in an
840 * application, and GTK sets them to that value by default, so calling
841 * this function is sort of pointless. However, you may want to call
842 * gtk_window_set_role() on each window in your application, for the
843 * benefit of the session manager. Setting the role allows the window
844 * manager to restore window positions when loading a saved session.
848 gtk_window_set_wmclass (GtkWindow *window,
849 const gchar *wmclass_name,
850 const gchar *wmclass_class)
852 g_return_if_fail (GTK_IS_WINDOW (window));
854 g_free (window->wmclass_name);
855 window->wmclass_name = g_strdup (wmclass_name);
857 g_free (window->wmclass_class);
858 window->wmclass_class = g_strdup (wmclass_class);
860 if (GTK_WIDGET_REALIZED (window))
861 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
865 * gtk_window_set_role:
866 * @window: a #GtkWindow
867 * @role: unique identifier for the window to be used when restoring a session
869 * In combination with the window title, the window role allows a
870 * window manager to identify "the same" window when an application is
871 * restarted. So for example you might set the "toolbox" role on your
872 * app's toolbox window, so that when the user restarts their session,
873 * the window manager can put the toolbox back in the same place.
875 * If a window already has a unique title, you don't need to set the
876 * role, since the WM can use the title to identify the window when
877 * restoring the session.
881 gtk_window_set_role (GtkWindow *window,
884 g_return_if_fail (GTK_IS_WINDOW (window));
886 if (role == window->wm_role)
889 g_free (window->wm_role);
890 window->wm_role = g_strdup (role);
892 if (GTK_WIDGET_REALIZED (window))
893 g_warning ("gtk_window_set_role(): shouldn't set role after window is realized!\n");
897 * gtk_window_get_role:
898 * @window: a #GtkWindow
900 * Returns the role of the window. See gtk_window_set_role() for
901 * further explanation.
903 * Return value: the role of the window if set, or %NULL. The
904 * returned is owned by the widget and must not be modified
907 G_CONST_RETURN gchar *
908 gtk_window_get_role (GtkWindow *window)
910 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
912 return window->wm_role;
916 * gtk_window_set_focus:
917 * @window: a #GtkWindow
918 * @focus: widget to be the new focus widget
920 * If @focus is not the current focus widget, and is focusable, emits
921 * the "set_focus" signal to set @focus as the focus widget for the
922 * window. This function is more or less GTK-internal; to focus an
923 * entry widget or the like, you should use gtk_widget_grab_focus()
924 * instead of this function.
928 gtk_window_set_focus (GtkWindow *window,
931 g_return_if_fail (GTK_IS_WINDOW (window));
934 g_return_if_fail (GTK_IS_WIDGET (focus));
935 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
938 if ((window->focus_widget != focus) ||
939 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
940 gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
944 * gtk_window_set_default:
945 * @window: a #GtkWindow
946 * @default_widget: widget to be the default
948 * The default widget is the widget that's activated when the user
949 * presses Enter in a dialog (for example). This function tells a
950 * #GtkWindow about the current default widget; it's really a GTK
951 * internal function and you shouldn't need it. Instead, to change the
952 * default widget, first set the #GTK_CAN_DEFAULT flag on the widget
953 * you'd like to make the default using GTK_WIDGET_SET_FLAGS(), then
954 * call gtk_widget_grab_default() to move the default.
958 gtk_window_set_default (GtkWindow *window,
959 GtkWidget *default_widget)
961 g_return_if_fail (GTK_IS_WINDOW (window));
964 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
966 if (window->default_widget != default_widget)
968 if (window->default_widget)
970 if (window->focus_widget != window->default_widget ||
971 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
972 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
973 gtk_widget_queue_draw (window->default_widget);
976 window->default_widget = default_widget;
978 if (window->default_widget)
980 if (window->focus_widget == NULL ||
981 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
982 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
983 gtk_widget_queue_draw (window->default_widget);
989 gtk_window_set_policy (GtkWindow *window,
990 gboolean allow_shrink,
992 gboolean auto_shrink)
994 g_return_if_fail (GTK_IS_WINDOW (window));
996 window->allow_shrink = (allow_shrink != FALSE);
997 window->allow_grow = (allow_grow != FALSE);
999 g_object_freeze_notify (G_OBJECT (window));
1000 g_object_notify (G_OBJECT (window), "allow_shrink");
1001 g_object_notify (G_OBJECT (window), "allow_grow");
1002 g_object_notify (G_OBJECT (window), "resizable");
1003 g_object_thaw_notify (G_OBJECT (window));
1005 gtk_widget_queue_resize (GTK_WIDGET (window));
1009 gtk_window_add_accel_group (GtkWindow *window,
1010 GtkAccelGroup *accel_group)
1012 g_return_if_fail (GTK_IS_WINDOW (window));
1013 g_return_if_fail (accel_group != NULL);
1015 gtk_accel_group_attach (accel_group, G_OBJECT (window));
1019 gtk_window_remove_accel_group (GtkWindow *window,
1020 GtkAccelGroup *accel_group)
1022 g_return_if_fail (GTK_IS_WINDOW (window));
1023 g_return_if_fail (accel_group != NULL);
1025 gtk_accel_group_detach (accel_group, G_OBJECT (window));
1029 gtk_window_add_mnemonic (GtkWindow *window,
1033 GtkWindowMnemonic key;
1034 GtkWindowMnemonic *mnemonic;
1036 g_return_if_fail (GTK_IS_WINDOW (window));
1037 g_return_if_fail (GTK_IS_WIDGET (target));
1039 key.window = window;
1040 key.keyval = keyval;
1041 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1045 g_return_if_fail (g_slist_find (mnemonic->targets, target) == NULL);
1046 mnemonic->targets = g_slist_prepend (mnemonic->targets, target);
1050 mnemonic = g_new (GtkWindowMnemonic, 1);
1052 mnemonic->targets = g_slist_prepend (NULL, target);
1053 g_hash_table_insert (mnemonic_hash_table, mnemonic, mnemonic);
1058 gtk_window_remove_mnemonic (GtkWindow *window,
1062 GtkWindowMnemonic key;
1063 GtkWindowMnemonic *mnemonic;
1065 g_return_if_fail (GTK_IS_WINDOW (window));
1066 g_return_if_fail (GTK_IS_WIDGET (target));
1068 key.window = window;
1069 key.keyval = keyval;
1070 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1072 g_return_if_fail (mnemonic && g_slist_find (mnemonic->targets, target) != NULL);
1074 mnemonic->targets = g_slist_remove (mnemonic->targets, target);
1075 if (mnemonic->targets == NULL)
1077 g_hash_table_remove (mnemonic_hash_table, mnemonic);
1083 gtk_window_mnemonic_activate (GtkWindow *window,
1085 GdkModifierType modifier)
1087 GtkWindowMnemonic key;
1088 GtkWindowMnemonic *mnemonic;
1090 GtkWidget *widget, *chosen_widget;
1091 gboolean overloaded;
1093 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1095 if (window->mnemonic_modifier != (modifier & gtk_accelerator_get_default_mod_mask ()))
1098 key.window = window;
1099 key.keyval = keyval;
1100 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1106 chosen_widget = NULL;
1107 list = mnemonic->targets;
1110 widget = GTK_WIDGET (list->data);
1112 if (GTK_WIDGET_IS_SENSITIVE (widget) &&
1113 GTK_WIDGET_MAPPED (widget))
1121 chosen_widget = widget;
1123 list = g_slist_next (list);
1128 /* For round robin we put the activated entry on
1129 * the end of the list after activation
1131 mnemonic->targets = g_slist_remove (mnemonic->targets, chosen_widget);
1132 mnemonic->targets = g_slist_append (mnemonic->targets, chosen_widget);
1134 return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
1140 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1141 GdkModifierType modifier)
1143 g_return_if_fail (GTK_IS_WINDOW (window));
1144 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1146 window->mnemonic_modifier = modifier;
1150 * gtk_window_get_mnemonic_modifier:
1151 * @window: a #GtkWindow
1153 * Returns the mnemonic modifier for this window. See
1154 * gtk_window_set_mnemonic_modifier().
1156 * Return value: the modifier mask used to activate
1157 * mnemonics on this window.
1160 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1162 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1164 return window->mnemonic_modifier;
1168 gtk_window_set_position (GtkWindow *window,
1169 GtkWindowPosition position)
1171 g_return_if_fail (GTK_IS_WINDOW (window));
1173 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1174 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1176 GtkWindowGeometryInfo *info;
1178 info = gtk_window_get_geometry_info (window, TRUE);
1180 /* this flag causes us to re-request the CENTER_ALWAYS
1181 * constraint in gtk_window_move_resize(), see
1182 * comment in that function.
1184 info->position_constraints_changed = TRUE;
1186 gtk_widget_queue_resize (GTK_WIDGET (window));
1189 window->position = position;
1191 g_object_notify (G_OBJECT (window), "window_position");
1195 gtk_window_activate_focus (GtkWindow *window)
1197 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1199 if (window->focus_widget)
1201 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1202 gtk_widget_activate (window->focus_widget);
1210 gtk_window_activate_default (GtkWindow *window)
1212 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1214 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1215 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1217 gtk_widget_activate (window->default_widget);
1220 else if (window->focus_widget)
1222 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1223 gtk_widget_activate (window->focus_widget);
1231 * gtk_window_set_modal:
1232 * @window: a #GtkWindow
1233 * @modal: whether the window is modal
1235 * Sets a window modal or non-modal. Modal windows prevent interaction
1236 * with other windows in the same application. To keep modal dialogs
1237 * on top of main application windows, use
1238 * gtk_window_set_transient_for() to make the dialog transient for the
1239 * parent; most window managers will then disallow lowering the dialog
1245 gtk_window_set_modal (GtkWindow *window,
1248 g_return_if_fail (GTK_IS_WINDOW (window));
1250 window->modal = modal != FALSE;
1252 /* adjust desired modality state */
1253 if (GTK_WIDGET_VISIBLE (window) && window->modal)
1254 gtk_grab_add (GTK_WIDGET (window));
1256 gtk_grab_remove (GTK_WIDGET (window));
1258 g_object_notify (G_OBJECT (window), "modal");
1262 * gtk_window_get_modal:
1263 * @window: a #GtkWindow
1265 * Returns whether the window is modal. See gtk_window_set_modal().
1267 * Return value: %TRUE if the window is set to be modal and
1268 * establishes a grab when shown
1271 gtk_window_get_modal (GtkWindow *window)
1273 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1275 return window->modal;
1279 * gtk_window_list_toplevels:
1281 * Returns a list of all existing toplevel windows. The widgets
1282 * in the list are not individually referenced. If you want
1283 * to iterate through the list and perform actions involving
1284 * callbacks that might destroy the widgets, you MUST call
1285 * g_list_foreach (result, (GFunc)g_object_ref, NULL) first, and
1286 * then unref all the widgets afterwards.
1288 * Return value: list of toplevel widgets
1291 gtk_window_list_toplevels (void)
1296 for (slist = toplevel_list; slist; slist = slist->next)
1297 list = g_list_prepend (list, slist->data);
1303 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1305 GList *embedded_windows;
1307 g_return_if_fail (GTK_IS_WINDOW (window));
1309 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1310 if (embedded_windows)
1311 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
1312 g_quark_from_static_string ("gtk-embedded"));
1313 embedded_windows = g_list_prepend (embedded_windows,
1314 GUINT_TO_POINTER (xid));
1316 gtk_object_set_data_full (GTK_OBJECT (window), "gtk-embedded",
1319 (GtkDestroyNotify) g_list_free : NULL);
1323 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1325 GList *embedded_windows;
1328 g_return_if_fail (GTK_IS_WINDOW (window));
1330 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1331 if (embedded_windows)
1332 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
1333 g_quark_from_static_string ("gtk-embedded"));
1335 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1338 embedded_windows = g_list_remove_link (embedded_windows, node);
1339 g_list_free_1 (node);
1342 gtk_object_set_data_full (GTK_OBJECT (window),
1343 "gtk-embedded", embedded_windows,
1345 (GtkDestroyNotify) g_list_free : NULL);
1349 _gtk_window_reposition (GtkWindow *window,
1353 g_return_if_fail (GTK_IS_WINDOW (window));
1355 gtk_window_move (window, x, y);
1359 gtk_window_dispose (GObject *object)
1363 g_return_if_fail (GTK_IS_WINDOW (object));
1365 window = GTK_WINDOW (object);
1367 gtk_window_set_focus (window, NULL);
1368 gtk_window_set_default (window, NULL);
1370 G_OBJECT_CLASS (parent_class)->dispose (object);
1374 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1376 gtk_widget_destroy (GTK_WIDGET (child));
1380 connect_parent_destroyed (GtkWindow *window)
1382 if (window->transient_parent)
1384 gtk_signal_connect (GTK_OBJECT (window->transient_parent),
1386 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1392 disconnect_parent_destroyed (GtkWindow *window)
1394 if (window->transient_parent)
1396 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1397 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1403 gtk_window_transient_parent_realized (GtkWidget *parent,
1406 if (GTK_WIDGET_REALIZED (window))
1407 gdk_window_set_transient_for (window->window, parent->window);
1411 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1414 if (GTK_WIDGET_REALIZED (window))
1415 gdk_property_delete (window->window,
1416 gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
1420 gtk_window_unset_transient_for (GtkWindow *window)
1422 if (window->transient_parent)
1424 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1425 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1427 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1428 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1430 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1431 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1432 &window->transient_parent);
1434 if (window->destroy_with_parent)
1435 disconnect_parent_destroyed (window);
1437 window->transient_parent = NULL;
1442 * gtk_window_set_transient_for:
1443 * @window: a #GtkWindow
1444 * @parent: parent window
1446 * Dialog windows should be set transient for the main application
1447 * window they were spawned from. This allows window managers to
1448 * e.g. keep the dialog on top of the main window, or center the
1449 * dialog over the main window. gtk_dialog_new_with_buttons() and
1450 * other convenience functions in GTK+ will sometimes call
1451 * gtk_window_set_transient_for() on your behalf.
1455 gtk_window_set_transient_for (GtkWindow *window,
1458 g_return_if_fail (GTK_IS_WINDOW (window));
1459 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1460 g_return_if_fail (window != parent);
1463 if (window->transient_parent)
1465 if (GTK_WIDGET_REALIZED (window) &&
1466 GTK_WIDGET_REALIZED (window->transient_parent) &&
1467 (!parent || !GTK_WIDGET_REALIZED (parent)))
1468 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1469 GTK_WIDGET (window));
1471 gtk_window_unset_transient_for (window);
1474 window->transient_parent = parent;
1478 gtk_signal_connect (GTK_OBJECT (parent), "destroy",
1479 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1480 &window->transient_parent);
1481 gtk_signal_connect (GTK_OBJECT (parent), "realize",
1482 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1484 gtk_signal_connect (GTK_OBJECT (parent), "unrealize",
1485 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1488 if (window->destroy_with_parent)
1489 connect_parent_destroyed (window);
1491 if (GTK_WIDGET_REALIZED (window) &&
1492 GTK_WIDGET_REALIZED (parent))
1493 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1494 GTK_WIDGET (window));
1499 * gtk_window_get_transient_for:
1500 * @window: a #GtkWindow
1502 * Fetches the transient parent for this window. See
1503 * gtk_window_set_transient_for().
1505 * Return value: the transient parent for this window, or %NULL
1506 * if no transient parent has been set.
1509 gtk_window_get_transient_for (GtkWindow *window)
1511 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1513 return window->transient_parent;
1517 * gtk_window_set_type_hint:
1518 * @window: a #GtkWindow
1519 * @hint: the window type
1521 * By setting the type hint for the window, you allow the window
1522 * manager to decorate and handle the window in a way which is
1523 * suitable to the function of the window in your application.
1525 * This function should be called before the window becomes visible.
1527 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1528 * will sometimes call gtk_window_set_type_hint() on your behalf.
1532 gtk_window_set_type_hint (GtkWindow *window,
1533 GdkWindowTypeHint hint)
1535 g_return_if_fail (GTK_IS_WINDOW (window));
1536 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1537 window->type_hint = hint;
1541 * gtk_window_get_type_hint:
1542 * @window: a #GtkWindow
1544 * Gets the type hint for this window. See gtk_window_set_type_hint().
1546 * Return value: the type hint for @window.
1549 gtk_window_get_type_hint (GtkWindow *window)
1551 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
1553 return window->type_hint;
1557 * gtk_window_set_destroy_with_parent:
1558 * @window: a #GtkWindow
1559 * @setting: whether to destroy @window with its transient parent
1561 * If @setting is TRUE, then destroying the transient parent of @window
1562 * will also destroy @window itself. This is useful for dialogs that
1563 * shouldn't persist beyond the lifetime of the main window they're
1564 * associated with, for example.
1567 gtk_window_set_destroy_with_parent (GtkWindow *window,
1570 g_return_if_fail (GTK_IS_WINDOW (window));
1572 if (window->destroy_with_parent == (setting != FALSE))
1575 if (window->destroy_with_parent)
1577 disconnect_parent_destroyed (window);
1581 connect_parent_destroyed (window);
1584 window->destroy_with_parent = setting;
1586 g_object_notify (G_OBJECT (window), "destroy_with_parent");
1590 * gtk_window_get_destroy_with_parent:
1591 * @window: a #GtkWindow
1593 * Returns whether the window will be destroyed with its transient parent. See
1594 * gtk_window_set_destroy_with_parent ().
1596 * Return value: %TRUE if the window will be destroyed with its transient parent.
1599 gtk_window_get_destroy_with_parent (GtkWindow *window)
1601 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1603 return window->destroy_with_parent;
1606 static GtkWindowGeometryInfo*
1607 gtk_window_get_geometry_info (GtkWindow *window,
1610 GtkWindowGeometryInfo *info;
1612 info = window->geometry_info;
1613 if (!info && create)
1615 info = g_new0 (GtkWindowGeometryInfo, 1);
1617 info->default_width = -1;
1618 info->default_height = -1;
1619 info->resize_width = -1;
1620 info->resize_height = -1;
1621 info->initial_x = 0;
1622 info->initial_y = 0;
1623 info->initial_pos_set = FALSE;
1624 info->position_constraints_changed = FALSE;
1625 info->last.configure_request.x = 0;
1626 info->last.configure_request.y = 0;
1627 info->last.configure_request.width = -1;
1628 info->last.configure_request.height = -1;
1629 info->widget = NULL;
1631 window->geometry_info = info;
1638 * gtk_window_set_geometry_hints:
1639 * @window: a #GtkWindow
1640 * @geometry_widget: widget the geometry hints will be applied to
1641 * @geometry: struct containing geometry information
1642 * @geom_mask: mask indicating which struct fields should be paid attention to
1644 * This function sets up hints about how a window can be resized by
1645 * the user. You can set a minimum and maximum size; allowed resize
1646 * increments (e.g. for xterm, you can only resize by the size of a
1647 * character); aspect ratios; and more. See the #GdkGeometry struct.
1651 gtk_window_set_geometry_hints (GtkWindow *window,
1652 GtkWidget *geometry_widget,
1653 GdkGeometry *geometry,
1654 GdkWindowHints geom_mask)
1656 GtkWindowGeometryInfo *info;
1658 g_return_if_fail (window != NULL);
1660 info = gtk_window_get_geometry_info (window, TRUE);
1663 gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
1664 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1667 info->widget = geometry_widget;
1669 gtk_signal_connect (GTK_OBJECT (geometry_widget), "destroy",
1670 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1674 info->geometry = *geometry;
1676 /* We store gravity in window->gravity not in the hints. */
1677 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
1679 if (geom_mask & GDK_HINT_WIN_GRAVITY)
1681 gtk_window_set_gravity (window, geometry->win_gravity);
1684 gtk_widget_queue_resize (GTK_WIDGET (window));
1688 * gtk_window_set_decorated:
1689 * @window: a #GtkWindow
1690 * @setting: %TRUE to decorate the window
1692 * By default, windows are decorated with a title bar, resize
1693 * controls, etc. Some window managers allow GTK+ to disable these
1694 * decorations, creating a borderless window. If you set the decorated
1695 * property to %FALSE using this function, GTK+ will do its best to
1696 * convince the window manager not to decorate the window.
1700 gtk_window_set_decorated (GtkWindow *window,
1703 g_return_if_fail (GTK_IS_WINDOW (window));
1705 setting = setting != FALSE;
1707 if (setting == window->decorated)
1710 window->decorated = setting;
1712 if (GTK_WIDGET (window)->window)
1714 if (window->decorated)
1715 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1718 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1724 * gtk_window_get_decorated:
1725 * @window: a #GtkWindow
1727 * Returns whether the window has been set to have decorations
1728 * such as a title bar via gtk_window_set_decorated().
1730 * Return value: %TRUE if the window has been set to have decorations
1733 gtk_window_get_decorated (GtkWindow *window)
1735 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
1737 return window->decorated;
1741 gdk_pixbuf_render_pixmap_and_mask_with_colormap (GdkPixbuf *pixbuf,
1742 GdkPixmap **pixmap_return,
1743 GdkBitmap **mask_return,
1744 int alpha_threshold,
1747 g_return_if_fail (pixbuf != NULL);
1753 *pixmap_return = gdk_pixmap_new (NULL, gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf),
1754 gdk_colormap_get_visual (cmap)->depth);
1755 gdk_drawable_set_colormap (GDK_DRAWABLE (*pixmap_return),
1757 gc = gdk_gc_new (*pixmap_return);
1758 gdk_pixbuf_render_to_drawable (pixbuf, *pixmap_return, gc,
1760 gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf),
1761 GDK_RGB_DITHER_NORMAL,
1768 if (gdk_pixbuf_get_has_alpha (pixbuf))
1770 *mask_return = gdk_pixmap_new (NULL, gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf), 1);
1772 gdk_pixbuf_render_threshold_alpha (pixbuf, *mask_return,
1774 gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf),
1778 *mask_return = NULL;
1782 static GtkWindowIconInfo*
1783 get_icon_info (GtkWindow *window)
1785 return g_object_get_data (G_OBJECT (window),
1786 "gtk-window-icon-info");
1789 static GtkWindowIconInfo*
1790 ensure_icon_info (GtkWindow *window)
1792 GtkWindowIconInfo *info;
1794 info = get_icon_info (window);
1798 info = g_new0 (GtkWindowIconInfo, 1);
1799 g_object_set_data_full (G_OBJECT (window),
1800 "gtk-window-icon-info",
1809 get_pixmap_and_mask (GtkWindowIconInfo *parent_info,
1810 gboolean is_default_list,
1812 GdkPixmap **pmap_return,
1813 GdkBitmap **mask_return)
1815 GdkPixbuf *best_icon;
1819 *pmap_return = NULL;
1820 *mask_return = NULL;
1822 if (is_default_list &&
1823 default_icon_pixmap != NULL)
1825 /* Use shared icon pixmap (eventually will be stored on the
1828 if (default_icon_pixmap)
1829 g_object_ref (G_OBJECT (default_icon_pixmap));
1830 if (default_icon_mask)
1831 g_object_ref (G_OBJECT (default_icon_mask));
1833 *pmap_return = default_icon_pixmap;
1834 *mask_return = default_icon_mask;
1836 else if (parent_info && parent_info->icon_pixmap)
1838 if (parent_info->icon_pixmap)
1839 g_object_ref (G_OBJECT (parent_info->icon_pixmap));
1840 if (parent_info->icon_mask)
1841 g_object_ref (G_OBJECT (parent_info->icon_mask));
1843 *pmap_return = parent_info->icon_pixmap;
1844 *mask_return = parent_info->icon_mask;
1848 #define IDEAL_SIZE 48
1850 best_size = G_MAXINT;
1852 tmp_list = icon_list;
1853 while (tmp_list != NULL)
1855 GdkPixbuf *pixbuf = tmp_list->data;
1858 /* average width and height - if someone passes in a rectangular
1859 * icon they deserve what they get.
1861 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
1864 if (best_icon == NULL)
1871 /* icon is better if it's 32 pixels or larger, and closer to
1872 * the ideal size than the current best.
1875 (ABS (best_size - IDEAL_SIZE) <
1876 ABS (this - IDEAL_SIZE)))
1883 tmp_list = tmp_list->next;
1887 gdk_pixbuf_render_pixmap_and_mask_with_colormap (best_icon,
1891 gdk_colormap_get_system ());
1893 /* Save pmap/mask for others to use if appropriate */
1896 parent_info->icon_pixmap = *pmap_return;
1897 parent_info->icon_mask = *mask_return;
1899 if (parent_info->icon_pixmap)
1900 g_object_ref (G_OBJECT (parent_info->icon_pixmap));
1901 if (parent_info->icon_mask)
1902 g_object_ref (G_OBJECT (parent_info->icon_mask));
1904 else if (is_default_list)
1906 default_icon_pixmap = *pmap_return;
1907 default_icon_mask = *mask_return;
1909 if (default_icon_pixmap)
1910 g_object_add_weak_pointer (G_OBJECT (default_icon_pixmap),
1911 (gpointer*)&default_icon_pixmap);
1912 if (default_icon_mask)
1913 g_object_add_weak_pointer (G_OBJECT (default_icon_mask),
1914 (gpointer*)&default_icon_mask);
1920 gtk_window_realize_icon (GtkWindow *window)
1923 GtkWindowIconInfo *info;
1926 widget = GTK_WIDGET (window);
1928 g_return_if_fail (widget->window != NULL);
1930 /* no point setting an icon on override-redirect */
1931 if (window->type == GTK_WINDOW_POPUP)
1936 info = ensure_icon_info (window);
1941 g_return_if_fail (info->icon_pixmap == NULL);
1942 g_return_if_fail (info->icon_mask == NULL);
1944 info->using_default_icon = FALSE;
1945 info->using_parent_icon = FALSE;
1947 icon_list = info->icon_list;
1949 /* Inherit from transient parent */
1950 if (icon_list == NULL && window->transient_parent)
1952 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
1954 info->using_parent_icon = TRUE;
1957 /* Inherit from default */
1958 if (icon_list == NULL)
1960 icon_list = default_icon_list;
1962 info->using_default_icon = TRUE;
1965 gdk_window_set_icon_list (widget->window, icon_list);
1967 get_pixmap_and_mask (info->using_parent_icon ?
1968 ensure_icon_info (window->transient_parent) : NULL,
1969 info->using_default_icon,
1974 /* This is a slight ICCCM violation since it's a color pixmap not
1975 * a bitmap, but everyone does it.
1977 gdk_window_set_icon (widget->window,
1982 info->realized = TRUE;
1986 gtk_window_unrealize_icon (GtkWindow *window)
1988 GtkWindowIconInfo *info;
1991 widget = GTK_WIDGET (window);
1993 info = get_icon_info (window);
1998 if (info->icon_pixmap)
1999 g_object_unref (G_OBJECT (info->icon_pixmap));
2001 if (info->icon_mask)
2002 g_object_unref (G_OBJECT (info->icon_mask));
2004 info->icon_pixmap = NULL;
2005 info->icon_mask = NULL;
2007 /* We don't clear the properties on the window, just figure the
2008 * window is going away.
2011 info->realized = FALSE;
2015 * gtk_window_set_icon_list:
2016 * @window: a #GtkWindow
2017 * @list: list of #GdkPixbuf
2019 * Sets up the icon representing a #GtkWindow. The icon is used when
2020 * the window is minimized (also known as iconified). Some window
2021 * managers or desktop environments may also place it in the window
2022 * frame, or display it in other contexts.
2024 * gtk_window_set_icon_list() allows you to pass in the same icon in
2025 * several hand-drawn sizes. The list should contain the natural sizes
2026 * your icon is available in; that is, don't scale the image before
2027 * passing it to GTK+. Scaling is postponed until the last minute,
2028 * when the desired final size is known, to allow best quality.
2030 * By passing several sizes, you may improve the final image quality
2031 * of the icon, by reducing or eliminating automatic image scaling.
2033 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2034 * larger images (64x64, 128x128) if you have them.
2036 * See also gtk_window_set_default_icon_list() to set the icon
2037 * for all windows in your application in one go.
2039 * Note that transient windows (those who have been set transient for another
2040 * window using gtk_window_set_transient_for()) will inherit their
2041 * icon from their transient parent. So there's no need to explicitly
2042 * set the icon on transient windows.
2045 gtk_window_set_icon_list (GtkWindow *window,
2048 GtkWindowIconInfo *info;
2050 g_return_if_fail (GTK_IS_WINDOW (window));
2052 info = ensure_icon_info (window);
2054 if (info->icon_list == list) /* check for NULL mostly */
2057 g_list_foreach (info->icon_list,
2058 (GFunc) g_object_unref, NULL);
2060 g_list_free (info->icon_list);
2062 info->icon_list = g_list_copy (list);
2063 g_list_foreach (info->icon_list,
2064 (GFunc) g_object_ref, NULL);
2066 g_object_notify (G_OBJECT (window), "icon");
2068 gtk_window_unrealize_icon (window);
2070 if (GTK_WIDGET_REALIZED (window))
2071 gtk_window_realize_icon (window);
2073 /* We could try to update our transient children, but I don't think
2074 * it's really worth it. If we did it, the best way would probably
2075 * be to have children connect to notify::icon_list
2080 * gtk_window_get_icon_list:
2081 * @window: a #GtkWindow
2083 * Retrieves the list of icons set by gtk_window_set_icon_list().
2084 * The list is copied, but the reference count on each
2085 * member won't be incremented.
2087 * Return value: copy of window's icon list
2090 gtk_window_get_icon_list (GtkWindow *window)
2092 GtkWindowIconInfo *info;
2094 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2096 info = get_icon_info (window);
2099 return g_list_copy (info->icon_list);
2105 * gtk_window_set_icon:
2106 * @window: a #GtkWindow
2107 * @icon: icon image, or %NULL
2109 * Sets up the icon representing a #GtkWindow. This icon is used when
2110 * the window is minimized (also known as iconified). Some window
2111 * managers or desktop environments may also place it in the window
2112 * frame, or display it in other contexts.
2114 * The icon should be provided in whatever size it was naturally
2115 * drawn; that is, don't scale the image before passing it to
2116 * GTK+. Scaling is postponed until the last minute, when the desired
2117 * final size is known, to allow best quality.
2119 * If you have your icon hand-drawn in multiple sizes, use
2120 * gtk_window_set_icon_list(). Then the best size will be used.
2122 * This function is equivalent to calling gtk_window_set_icon_list()
2123 * with a 1-element list.
2125 * See also gtk_window_set_default_icon_list() to set the icon
2126 * for all windows in your application in one go.
2129 gtk_window_set_icon (GtkWindow *window,
2134 g_return_if_fail (GTK_IS_WINDOW (window));
2135 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
2138 list = g_list_append (list, icon);
2139 gtk_window_set_icon_list (window, list);
2144 * gtk_window_get_icon:
2145 * @window: a #GtkWindow
2147 * Gets the value set by gtk_window_set_icon() (or if you've
2148 * called gtk_window_set_icon_list(), gets the first icon in
2151 * Return value: icon for window
2154 gtk_window_get_icon (GtkWindow *window)
2156 GtkWindowIconInfo *info;
2158 info = get_icon_info (window);
2159 if (info && info->icon_list)
2160 return GDK_PIXBUF (info->icon_list->data);
2166 * gtk_window_set_default_icon_list:
2167 * @list: a list of #GdkPixbuf
2169 * Sets an icon list to be used as fallback for windows that haven't
2170 * had gtk_window_set_icon_list() called on them to set up a
2171 * window-specific icon list. This function allows you to set up the
2172 * icon for all windows in your app at once.
2174 * See gtk_window_set_icon_list() for more details.
2178 gtk_window_set_default_icon_list (GList *list)
2182 if (list == default_icon_list)
2185 if (default_icon_pixmap)
2186 g_object_unref (G_OBJECT (default_icon_pixmap));
2187 if (default_icon_mask)
2188 g_object_unref (G_OBJECT (default_icon_mask));
2190 default_icon_pixmap = NULL;
2191 default_icon_mask = NULL;
2193 g_list_foreach (default_icon_list,
2194 (GFunc) g_object_unref, NULL);
2196 g_list_free (default_icon_list);
2198 default_icon_list = g_list_copy (list);
2199 g_list_foreach (default_icon_list,
2200 (GFunc) g_object_ref, NULL);
2202 /* Update all toplevels */
2203 toplevels = gtk_window_list_toplevels ();
2204 tmp_list = toplevels;
2205 while (tmp_list != NULL)
2207 GtkWindowIconInfo *info;
2208 GtkWindow *w = tmp_list->data;
2210 info = get_icon_info (w);
2211 if (info && info->using_default_icon)
2213 gtk_window_unrealize_icon (w);
2214 if (GTK_WIDGET_REALIZED (w))
2215 gtk_window_realize_icon (w);
2218 tmp_list = tmp_list->next;
2220 g_list_free (toplevels);
2224 * gtk_window_get_default_icon_list:
2226 * Gets the value set by gtk_window_set_default_icon_list().
2227 * The list is a copy and should be freed with g_list_free(),
2228 * but the pixbufs in the list have not had their reference count
2231 * Return value: copy of default icon list
2234 gtk_window_get_default_icon_list (void)
2236 return g_list_copy (default_icon_list);
2240 gtk_window_set_default_size_internal (GtkWindow *window,
2241 gboolean change_width,
2243 gboolean change_height,
2246 GtkWindowGeometryInfo *info;
2248 g_return_if_fail (GTK_IS_WINDOW (window));
2249 g_return_if_fail (change_width == FALSE || width >= -1);
2250 g_return_if_fail (change_height == FALSE || height >= -1);
2252 info = gtk_window_get_geometry_info (window, TRUE);
2254 g_object_freeze_notify (G_OBJECT (window));
2264 info->default_width = width;
2266 g_object_notify (G_OBJECT (window), "default_width");
2277 info->default_height = height;
2279 g_object_notify (G_OBJECT (window), "default_height");
2282 g_object_thaw_notify (G_OBJECT (window));
2284 gtk_widget_queue_resize (GTK_WIDGET (window));
2288 * gtk_window_set_default_size:
2289 * @window: a #GtkWindow
2290 * @width: width in pixels, or -1 to unset the default width
2291 * @height: height in pixels, or -1 to unset the default height
2293 * Sets the default size of a window. If the window's "natural" size
2294 * (its size request) is larger than the default, the default will be
2295 * ignored. More generally, if the default size does not obey the
2296 * geometry hints for the window (gtk_window_set_geometry_hints() can
2297 * be used to set these explicitly), the default size will be clamped
2298 * to the nearest permitted size.
2300 * Unlike gtk_widget_set_size_request(), which sets a size request for
2301 * a widget and thus would keep users from shrinking the window, this
2302 * function only sets the initial size, just as if the user had
2303 * resized the window themselves. Users can still shrink the window
2304 * again as they normally would. Setting a default size of -1 means to
2305 * use the "natural" default size (the size request of the window).
2307 * For more control over a window's initial size and how resizing works,
2308 * investigate gtk_window_set_geometry_hints().
2310 * A useful feature: if you set the "geometry widget" via
2311 * gtk_window_set_geometry_hints(), the default size specified by
2312 * gtk_window_set_default_size() will be the default size of that
2313 * widget, not of the entire window.
2315 * For some uses, gtk_window_resize() is a more appropriate function.
2316 * gtk_window_resize() changes the current size of the window, rather
2317 * than the size to be used on initial display. gtk_window_resize() always
2318 * affects the window itself, not the geometry widget.
2320 * The default size of a window only affects the first time a window is
2321 * shown; if a window is hidden and re-shown, it will remember the size
2322 * it had prior to hiding, rather than using the default size.
2324 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
2325 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
2328 gtk_window_set_default_size (GtkWindow *window,
2332 g_return_if_fail (GTK_IS_WINDOW (window));
2333 g_return_if_fail (width >= -1);
2334 g_return_if_fail (height >= -1);
2336 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height);
2340 * gtk_window_get_default_size:
2341 * @window: a #GtkWindow
2342 * @width: location to store the default width, or %NULL
2343 * @height: location to store the default height, or %NULL
2345 * Gets the default size of the window. A value of -1 for the width or
2346 * height indicates that a default size has not been explicitly set
2347 * for that dimension, so the "natural" size of the window will be
2352 gtk_window_get_default_size (GtkWindow *window,
2356 GtkWindowGeometryInfo *info;
2358 g_return_if_fail (GTK_IS_WINDOW (window));
2360 info = gtk_window_get_geometry_info (window, FALSE);
2363 *width = info->default_width;
2366 *height = info->default_height;
2370 * gtk_window_resize:
2371 * @window: a #GtkWindow
2372 * @width: width to resize the window to
2373 * @height: height to resize the window to
2375 * Resizes the window as if the user had done so, obeying geometry
2376 * constraints. The default geometry constraint is that windows may
2377 * not be smaller than their size request; to override this
2378 * constraint, call gtk_widget_set_size_request() to set the window's
2379 * request to a smaller value.
2381 * If gtk_window_resize() is called before showing a window for the
2382 * first time, it overrides any default size set with
2383 * gtk_window_set_default_size().
2385 * Windows may not be resized smaller than 1 by 1 pixels.
2389 gtk_window_resize (GtkWindow *window,
2393 GtkWindowGeometryInfo *info;
2395 g_return_if_fail (GTK_IS_WINDOW (window));
2396 g_return_if_fail (width > 0);
2397 g_return_if_fail (height > 0);
2399 info = gtk_window_get_geometry_info (window, TRUE);
2401 info->resize_width = width;
2402 info->resize_height = height;
2404 gtk_widget_queue_resize (GTK_WIDGET (window));
2408 * gtk_window_get_size:
2409 * @window: a #GtkWindow
2410 * @width: return location for width, or %NULL
2411 * @height: return location for height, or %NULL
2413 * Obtains the current size of @window. If @window is not onscreen,
2414 * returns the size GTK+ will suggest to the window manager for the
2415 * initial window size (but this is not reliably the same as the size
2416 * the window manager will actually select). The size obtained by
2417 * gtk_window_get_size() is the last size received in a
2418 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
2419 * rather than querying the X server for the size. As a result, if you
2420 * call gtk_window_resize() then immediately call
2421 * gtk_window_get_size(), the size won't have taken effect yet. After
2422 * the window manager processes the resize request, GTK+ receives
2423 * notification that the size has changed via a configure event, and
2424 * the size of the window gets updated.
2426 * Note #1: Nearly any use of this function creates a race condition,
2427 * because the size of the window may change between the time that you
2428 * get the size and the time that you perform some action assuming
2429 * that size is the current size. To avoid race conditions, connect to
2430 * "configure_event" on the window and adjust your size-dependent
2431 * state to match the size delivered in the #GdkEventConfigure.
2433 * Note #2: The returned size does NOT include the size of the window
2434 * manager decorations (aka the window frame or border). Those
2435 * are not drawn by GTK+ and GTK+ has no reliable method of
2436 * determining their size.
2438 * Note #3: If you are getting a window size in order to position
2439 * the window onscreen, there may be a better way. The preferred
2440 * way is to simply set the window's semantic type with
2441 * gtk_window_set_type_hint(), which allows the window manager to
2442 * e.g. center dialogs. Also, if you set the transient parent of
2443 * dialogs with gtk_widget_set_transient_for() window managers
2444 * will often center the dialog over its parent window. It's
2445 * much preferred to let the window manager handle these
2446 * things rather than doing it yourself, because all apps will
2447 * behave consistently and according to user prefs if the window
2448 * manager handles it. Also, the window manager can take the size
2449 * of the window decorations/border into account, while your
2450 * application cannot.
2452 * In any case, if you insist on application-specified window
2453 * positioning, there's STILL a better way than doing it yourself -
2454 * gtk_window_set_position() will frequently handle the details
2459 gtk_window_get_size (GtkWindow *window,
2466 g_return_if_fail (GTK_IS_WINDOW (window));
2468 widget = GTK_WIDGET (window);
2470 if (width == NULL && height == NULL)
2473 if (GTK_WIDGET_MAPPED (window))
2475 gdk_drawable_get_size (GTK_WIDGET (window)->window,
2480 GdkRectangle configure_request;
2482 gtk_window_compute_configure_request (window,
2486 w = configure_request.width;
2487 h = configure_request.height;
2498 * @window: a #GtkWindow
2499 * @x: X coordinate to move window to
2500 * @y: Y coordinate to move window to
2502 * Asks the window manager to move @window to the given position.
2503 * Window managers are free to ignore this; most window managers
2504 * ignore requests for initial window positions (instead using a
2505 * user-defined placement algorithm) and honor requests after the
2506 * window has already been shown.
2508 * Note: the position is the position of the gravity-determined
2509 * reference point for the window. The gravity determines two things:
2510 * first, the location of the reference point in root window
2511 * coordinates; and second, which point on the window is positioned at
2512 * the reference point.
2514 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
2515 * point is simply the @x, @y supplied to gtk_window_move(). The
2516 * top-left corner of the window decorations (aka window frame or
2517 * border) will be placed at @x, @y. Therefore, to position a window
2518 * at the top left of the screen, you want to use the default gravity
2519 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
2521 * To position a window at the bottom right corner of the screen, you
2522 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
2523 * point is at @x + the window width and @y + the window height, and
2524 * the bottom-right corner of the window border will be placed at that
2525 * reference point. So, to place a window in the bottom right corner
2526 * you would first set gravity to south east, then write:
2527 * gtk_window_move (window, gdk_screen_width () - window_width,
2528 * gdk_screen_height () - window_height).
2530 * The extended window manager hints specification at
2531 * http://www.freedesktop.org/standards/wm-spec.html has a nice table
2532 * of gravities in the "implementation notes" section.
2534 * The gtk_window_get_position() documentation may also be relevant.
2538 gtk_window_move (GtkWindow *window,
2542 GtkWindowGeometryInfo *info;
2545 g_return_if_fail (GTK_IS_WINDOW (window));
2547 widget = GTK_WIDGET (window);
2549 info = gtk_window_get_geometry_info (window, TRUE);
2551 if (GTK_WIDGET_MAPPED (window))
2553 /* we have now sent a request with this position
2554 * with currently-active constraints, so toggle flag.
2556 info->position_constraints_changed = FALSE;
2558 /* we only constrain if mapped - if not mapped,
2559 * then gtk_window_compute_configure_request()
2560 * will apply the constraints later, and we
2561 * don't want to lose information about
2562 * what position the user set before then.
2563 * i.e. if you do a move() then turn off POS_CENTER
2564 * then show the window, your move() will work.
2566 gtk_window_constrain_position (window,
2567 widget->allocation.width,
2568 widget->allocation.height,
2571 /* Note that this request doesn't go through our standard request
2572 * framework, e.g. doesn't increment configure_request_count,
2573 * doesn't set info->last, etc.; that's because
2574 * we don't save the info needed to arrive at this same request
2577 * To gtk_window_move_resize(), this will end up looking exactly
2578 * the same as the position being changed by the window
2582 /* FIXME are we handling gravity properly for framed windows? */
2584 gdk_window_move (window->frame,
2585 x - window->frame_left,
2586 y - window->frame_top);
2588 gdk_window_move (GTK_WIDGET (window)->window,
2593 /* Save this position to apply on mapping */
2594 info->initial_x = x;
2595 info->initial_y = y;
2596 info->initial_pos_set = TRUE;
2601 * gtk_window_get_position:
2602 * @window: a #GtkWindow
2603 * @root_x: return location for X coordinate of gravity-determined reference p\oint
2604 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
2606 * This function returns the position you need to pass to
2607 * gtk_window_move() to keep @window in its current position. This
2608 * means that the meaning of the returned value varies with window
2609 * gravity. See gtk_window_move() for more details.
2611 * If you haven't changed the window gravity, its gravity will be
2612 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
2613 * returns the position of the top-left corner of the window
2614 * manager frame for the window. gtk_window_move() sets the
2615 * position of this same top-left corner.
2617 * gtk_window_get_position() is not 100% reliable because the X Window System
2618 * does not specify a way to obtain the geometry of the
2619 * decorations placed on a window by the window manager.
2620 * Thus GTK+ is using a "best guess" that works with most
2623 * Moreover, nearly all window managers are broken with respect to
2624 * their handling of window gravity. So moving a window to its current
2625 * position as returned by gtk_window_get_position() tends to
2626 * result in moving the window slightly.
2628 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
2629 * frame is not relevant, and thus gtk_window_get_position() will
2630 * always produce accurate results. However you can't use static
2631 * gravity to do things like place a window in a corner of the screen,
2632 * because static gravity ignores the window manager decorations.
2634 * If you are saving and restoring your application's window
2635 * positions, you should know that it's impossible for applications to
2636 * do this without getting it somewhat wrong because applications do
2637 * not have sufficient knowledge of window manager state. The Correct
2638 * Mechanism is to support the session management protocol (see the
2639 * "GnomeClient" object in the GNOME libraries for example) and allow
2640 * the window manager to save your window sizes and positions.
2645 gtk_window_get_position (GtkWindow *window,
2651 g_return_if_fail (GTK_IS_WINDOW (window));
2653 widget = GTK_WIDGET (window);
2655 if (window->gravity == GDK_GRAVITY_STATIC)
2657 if (GTK_WIDGET_MAPPED (widget))
2659 /* This does a server round-trip, which is sort of wrong;
2660 * but a server round-trip is inevitable for
2661 * gdk_window_get_frame_extents() in the usual
2662 * NorthWestGravity case below, so not sure what else to
2663 * do. We should likely be consistent about whether we get
2664 * the client-side info or the server-side info.
2666 gdk_window_get_origin (widget->window, root_x, root_y);
2670 GdkRectangle configure_request;
2672 gtk_window_compute_configure_request (window,
2676 *root_x = configure_request.x;
2677 *root_y = configure_request.y;
2682 GdkRectangle frame_extents;
2687 if (GTK_WIDGET_MAPPED (widget))
2689 gdk_window_get_frame_extents (widget->window, &frame_extents);
2690 x = frame_extents.x;
2691 y = frame_extents.y;
2692 gtk_window_get_size (window, &w, &h);
2696 /* We just say the frame has 0 size on all sides.
2697 * Not sure what else to do.
2699 gtk_window_compute_configure_request (window,
2702 x = frame_extents.x;
2703 y = frame_extents.y;
2704 w = frame_extents.width;
2705 h = frame_extents.height;
2708 switch (window->gravity)
2710 case GDK_GRAVITY_NORTH:
2711 case GDK_GRAVITY_CENTER:
2712 case GDK_GRAVITY_SOUTH:
2713 /* Find center of frame. */
2714 x += frame_extents.width / 2;
2715 /* Center client window on that point. */
2719 case GDK_GRAVITY_SOUTH_EAST:
2720 case GDK_GRAVITY_EAST:
2721 case GDK_GRAVITY_NORTH_EAST:
2722 /* Find right edge of frame */
2723 x += frame_extents.width;
2724 /* Align left edge of client at that point. */
2731 switch (window->gravity)
2733 case GDK_GRAVITY_WEST:
2734 case GDK_GRAVITY_CENTER:
2735 case GDK_GRAVITY_EAST:
2736 /* Find center of frame. */
2737 y += frame_extents.height / 2;
2738 /* Center client window there. */
2741 case GDK_GRAVITY_SOUTH_WEST:
2742 case GDK_GRAVITY_SOUTH:
2743 case GDK_GRAVITY_SOUTH_EAST:
2744 /* Find south edge of frame */
2745 y += frame_extents.height;
2746 /* Place bottom edge of client there */
2761 * gtk_window_reshow_with_initial_size:
2762 * @window: a #GtkWindow
2764 * Hides @window, then reshows it, resetting the
2765 * default size and position of the window. Used
2766 * by GUI builders only.
2769 gtk_window_reshow_with_initial_size (GtkWindow *window)
2773 g_return_if_fail (GTK_IS_WINDOW (window));
2775 widget = GTK_WIDGET (window);
2777 gtk_widget_hide (widget);
2778 gtk_widget_unrealize (widget);
2779 gtk_widget_show (widget);
2783 gtk_window_destroy (GtkObject *object)
2787 g_return_if_fail (GTK_IS_WINDOW (object));
2789 window = GTK_WINDOW (object);
2791 if (window->transient_parent)
2792 gtk_window_set_transient_for (window, NULL);
2794 /* frees the icons */
2795 gtk_window_set_icon_list (window, NULL);
2797 if (window->has_user_ref_count)
2799 window->has_user_ref_count = FALSE;
2800 gtk_widget_unref (GTK_WIDGET (window));
2804 gtk_window_group_remove_window (window->group, window);
2806 GTK_OBJECT_CLASS (parent_class)->destroy (object);
2810 gtk_window_mnemonic_hash_remove (gpointer key,
2814 GtkWindowMnemonic *mnemonic = key;
2815 GtkWindow *window = user;
2817 if (mnemonic->window == window)
2819 if (mnemonic->targets)
2821 gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
2823 g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
2824 name, mnemonic->targets->data);
2827 g_slist_free (mnemonic->targets);
2836 gtk_window_finalize (GObject *object)
2840 g_return_if_fail (GTK_IS_WINDOW (object));
2842 window = GTK_WINDOW (object);
2844 toplevel_list = g_slist_remove (toplevel_list, window);
2846 g_free (window->title);
2847 g_free (window->wmclass_name);
2848 g_free (window->wmclass_class);
2849 g_free (window->wm_role);
2851 g_hash_table_foreach_remove (mnemonic_hash_table,
2852 gtk_window_mnemonic_hash_remove,
2854 if (window->geometry_info)
2856 if (window->geometry_info->widget)
2857 gtk_signal_disconnect_by_func (GTK_OBJECT (window->geometry_info->widget),
2858 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
2859 &window->geometry_info->widget);
2860 g_free (window->geometry_info);
2863 G_OBJECT_CLASS (parent_class)->finalize (object);
2867 gtk_window_show (GtkWidget *widget)
2869 GtkWindow *window = GTK_WINDOW (widget);
2870 GtkContainer *container = GTK_CONTAINER (window);
2871 gboolean need_resize;
2873 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
2875 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
2876 container->need_resize = FALSE;
2880 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
2881 GtkAllocation allocation = { 0, 0 };
2882 GdkRectangle configure_request;
2883 GdkGeometry new_geometry;
2885 gboolean was_realized;
2887 /* We are going to go ahead and perform this configure request
2888 * and then emulate a configure notify by going ahead and
2889 * doing a size allocate. Sort of a synchronous
2890 * mini-copy of gtk_window_move_resize() here.
2892 gtk_window_compute_configure_request (window,
2897 /* We update this because we are going to go ahead
2898 * and gdk_window_resize() below, rather than
2901 info->last.configure_request.width = configure_request.width;
2902 info->last.configure_request.height = configure_request.height;
2904 /* and allocate the window - this is normally done
2905 * in move_resize in response to configure notify
2907 allocation.width = configure_request.width;
2908 allocation.height = configure_request.height;
2909 gtk_widget_size_allocate (widget, &allocation);
2911 /* Then we guarantee we have a realize */
2912 was_realized = FALSE;
2913 if (!GTK_WIDGET_REALIZED (widget))
2915 gtk_widget_realize (widget);
2916 was_realized = TRUE;
2919 /* Must be done after the windows are realized,
2920 * so that the decorations can be read
2922 gtk_decorated_window_calculate_frame_size (window);
2924 /* We only send configure request if we didn't just finish
2925 * creating the window; if we just created the window
2926 * then we created it with widget->allocation anyhow.
2929 gdk_window_resize (widget->window,
2930 configure_request.width,
2931 configure_request.height);
2934 gtk_container_check_resize (container);
2936 gtk_widget_map (widget);
2939 gtk_grab_add (widget);
2943 gtk_window_hide (GtkWidget *widget)
2947 g_return_if_fail (GTK_IS_WINDOW (widget));
2949 window = GTK_WINDOW (widget);
2951 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
2952 gtk_widget_unmap (widget);
2955 gtk_grab_remove (widget);
2959 gtk_window_map (GtkWidget *widget)
2962 GdkWindow *toplevel;
2964 g_return_if_fail (GTK_IS_WINDOW (widget));
2966 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
2968 window = GTK_WINDOW (widget);
2970 if (window->bin.child &&
2971 GTK_WIDGET_VISIBLE (window->bin.child) &&
2972 !GTK_WIDGET_MAPPED (window->bin.child))
2973 gtk_widget_map (window->bin.child);
2976 toplevel = window->frame;
2978 toplevel = widget->window;
2980 if (window->maximize_initially)
2981 gdk_window_maximize (toplevel);
2983 gdk_window_unmaximize (toplevel);
2985 if (window->stick_initially)
2986 gdk_window_stick (toplevel);
2988 gdk_window_unstick (toplevel);
2990 if (window->iconify_initially)
2991 gdk_window_iconify (toplevel);
2993 gdk_window_deiconify (toplevel);
2995 /* No longer use the default settings */
2996 window->need_default_size = FALSE;
2997 window->need_default_position = FALSE;
2999 gdk_window_show (widget->window);
3002 gdk_window_show (window->frame);
3006 gtk_window_unmap (GtkWidget *widget)
3009 GtkWindowGeometryInfo *info;
3011 window = GTK_WINDOW (widget);
3013 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
3015 gdk_window_withdraw (window->frame);
3017 gdk_window_withdraw (widget->window);
3019 window->configure_request_count = 0;
3020 window->configure_notify_received = FALSE;
3022 /* on unmap, we reset the default positioning of the window,
3023 * so it's placed again, but we don't reset the default
3024 * size of the window, so it's remembered.
3026 window->need_default_position = TRUE;
3028 info = gtk_window_get_geometry_info (window, FALSE);
3031 info->initial_pos_set = FALSE;
3032 info->position_constraints_changed = FALSE;
3037 gtk_window_realize (GtkWidget *widget)
3040 GdkWindow *parent_window;
3041 GdkWindowAttr attributes;
3042 gint attributes_mask;
3044 g_return_if_fail (GTK_IS_WINDOW (widget));
3046 window = GTK_WINDOW (widget);
3048 /* ensure widget tree is properly size allocated */
3049 if (widget->allocation.x == -1 &&
3050 widget->allocation.y == -1 &&
3051 widget->allocation.width == 1 &&
3052 widget->allocation.height == 1)
3054 GtkRequisition requisition;
3055 GtkAllocation allocation = { 0, 0, 200, 200 };
3057 gtk_widget_size_request (widget, &requisition);
3058 if (requisition.width || requisition.height)
3060 /* non-empty window */
3061 allocation.width = requisition.width;
3062 allocation.height = requisition.height;
3064 gtk_widget_size_allocate (widget, &allocation);
3066 gtk_container_queue_resize (GTK_CONTAINER (widget));
3068 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
3071 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
3073 switch (window->type)
3075 case GTK_WINDOW_TOPLEVEL:
3076 attributes.window_type = GDK_WINDOW_TOPLEVEL;
3078 case GTK_WINDOW_POPUP:
3079 attributes.window_type = GDK_WINDOW_TEMP;
3082 g_warning (G_STRLOC": Unknown window type %d!", window->type);
3086 attributes.title = window->title;
3087 attributes.wmclass_name = window->wmclass_name;
3088 attributes.wmclass_class = window->wmclass_class;
3089 attributes.wclass = GDK_INPUT_OUTPUT;
3090 attributes.visual = gtk_widget_get_visual (widget);
3091 attributes.colormap = gtk_widget_get_colormap (widget);
3093 if (window->has_frame)
3095 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
3096 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
3097 attributes.event_mask = (GDK_EXPOSURE_MASK |
3098 GDK_KEY_PRESS_MASK |
3099 GDK_ENTER_NOTIFY_MASK |
3100 GDK_LEAVE_NOTIFY_MASK |
3101 GDK_FOCUS_CHANGE_MASK |
3102 GDK_STRUCTURE_MASK |
3103 GDK_BUTTON_MOTION_MASK |
3104 GDK_POINTER_MOTION_HINT_MASK |
3105 GDK_BUTTON_PRESS_MASK |
3106 GDK_BUTTON_RELEASE_MASK);
3108 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
3110 window->frame = gdk_window_new (NULL, &attributes, attributes_mask);
3111 gdk_window_set_user_data (window->frame, widget);
3113 attributes.window_type = GDK_WINDOW_CHILD;
3114 attributes.x = window->frame_left;
3115 attributes.y = window->frame_right;
3117 attributes_mask = GDK_WA_X | GDK_WA_Y;
3119 parent_window = window->frame;
3123 attributes_mask = 0;
3124 parent_window = NULL;
3127 attributes.width = widget->allocation.width;
3128 attributes.height = widget->allocation.height;
3129 attributes.event_mask = gtk_widget_get_events (widget);
3130 attributes.event_mask |= (GDK_EXPOSURE_MASK |
3131 GDK_KEY_PRESS_MASK |
3132 GDK_ENTER_NOTIFY_MASK |
3133 GDK_LEAVE_NOTIFY_MASK |
3134 GDK_FOCUS_CHANGE_MASK |
3135 GDK_STRUCTURE_MASK);
3137 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
3138 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
3139 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
3140 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
3141 gdk_window_set_user_data (widget->window, window);
3143 widget->style = gtk_style_attach (widget->style, widget->window);
3144 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
3146 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
3148 /* This is a bad hack to set the window background. */
3149 gtk_window_paint (widget, NULL);
3151 if (window->transient_parent &&
3152 GTK_WIDGET_REALIZED (window->transient_parent))
3153 gdk_window_set_transient_for (widget->window,
3154 GTK_WIDGET (window->transient_parent)->window);
3156 if (window->wm_role)
3157 gdk_window_set_role (widget->window, window->wm_role);
3159 if (!window->decorated)
3160 gdk_window_set_decorations (widget->window, 0);
3162 gdk_window_set_type_hint (widget->window, window->type_hint);
3164 /* transient_for must be set to allow the modal hint */
3165 if (window->transient_parent && window->modal)
3166 gdk_window_set_modal_hint (widget->window, TRUE);
3168 gdk_window_set_modal_hint (widget->window, FALSE);
3171 gtk_window_realize_icon (window);
3175 gtk_window_unrealize (GtkWidget *widget)
3178 GtkWindowGeometryInfo *info;
3180 window = GTK_WINDOW (widget);
3182 /* On unrealize, we reset the size of the window such
3183 * that we will re-apply the default sizing stuff
3184 * next time we show the window.
3186 * Default positioning is reset on unmap, instead of unrealize.
3188 window->need_default_size = TRUE;
3189 info = gtk_window_get_geometry_info (window, FALSE);
3192 info->resize_width = -1;
3193 info->resize_height = -1;
3194 info->last.configure_request.x = 0;
3195 info->last.configure_request.y = 0;
3196 info->last.configure_request.width = -1;
3197 info->last.configure_request.height = -1;
3198 /* be sure we reset geom hints on re-realize */
3199 info->last.flags = 0;
3204 gdk_window_set_user_data (window->frame, NULL);
3205 gdk_window_destroy (window->frame);
3206 window->frame = NULL;
3210 gtk_window_unrealize_icon (window);
3212 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
3216 gtk_window_size_request (GtkWidget *widget,
3217 GtkRequisition *requisition)
3222 g_return_if_fail (GTK_IS_WINDOW (widget));
3223 g_return_if_fail (requisition != NULL);
3225 window = GTK_WINDOW (widget);
3226 bin = GTK_BIN (window);
3228 requisition->width = GTK_CONTAINER (window)->border_width * 2;
3229 requisition->height = GTK_CONTAINER (window)->border_width * 2;
3231 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
3233 GtkRequisition child_requisition;
3235 gtk_widget_size_request (bin->child, &child_requisition);
3237 requisition->width += child_requisition.width;
3238 requisition->height += child_requisition.height;
3243 gtk_window_size_allocate (GtkWidget *widget,
3244 GtkAllocation *allocation)
3247 GtkAllocation child_allocation;
3249 g_return_if_fail (GTK_IS_WINDOW (widget));
3250 g_return_if_fail (allocation != NULL);
3252 window = GTK_WINDOW (widget);
3253 widget->allocation = *allocation;
3255 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
3257 child_allocation.x = GTK_CONTAINER (window)->border_width;
3258 child_allocation.y = GTK_CONTAINER (window)->border_width;
3259 child_allocation.width =
3260 MAX (1, (gint)allocation->width - child_allocation.x * 2);
3261 child_allocation.height =
3262 MAX (1, (gint)allocation->height - child_allocation.y * 2);
3264 gtk_widget_size_allocate (window->bin.child, &child_allocation);
3267 if (GTK_WIDGET_REALIZED (widget) && window->frame)
3269 gdk_window_resize (window->frame,
3270 allocation->width + window->frame_left + window->frame_right,
3271 allocation->height + window->frame_top + window->frame_bottom);
3276 gtk_window_event (GtkWidget *widget, GdkEvent *event)
3279 gboolean return_val;
3282 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3283 g_return_val_if_fail (event != NULL, FALSE);
3285 window = GTK_WINDOW (widget);
3287 if (window->frame && (event->any.window == window->frame))
3289 if ((event->type != GDK_KEY_PRESS) &&
3290 (event->type != GDK_KEY_RELEASE) &&
3291 (event->type != GDK_FOCUS_CHANGE))
3293 gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "event");
3295 gtk_signal_emit (GTK_OBJECT (widget), window_signals[FRAME_EVENT], event, &return_val);
3300 g_object_unref (event->any.window);
3301 event->any.window = g_object_ref (widget->window);
3309 gtk_window_frame_event (GtkWidget *widget, GdkEvent *event)
3311 GdkEventConfigure *configure_event;
3312 GtkWindow *window = GTK_WINDOW (widget);
3315 switch (event->type)
3318 configure_event = (GdkEventConfigure *)event;
3320 /* Invalidate the decorations */
3323 rect.width = configure_event->width;
3324 rect.height = configure_event->height;
3326 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
3328 /* Pass on the (modified) configure event */
3329 configure_event->width -= window->frame_left + window->frame_right;
3330 configure_event->height -= window->frame_top + window->frame_bottom;
3331 return gtk_window_configure_event (widget, configure_event);
3340 gtk_window_configure_event (GtkWidget *widget,
3341 GdkEventConfigure *event)
3345 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3346 g_return_val_if_fail (event != NULL, FALSE);
3348 window = GTK_WINDOW (widget);
3350 /* window->configure_request_count incremented for each
3351 * configure request, and decremented to a min of 0 for
3352 * each configure notify.
3354 * All it means is that we know we will get at least
3355 * window->configure_request_count more configure notifies.
3356 * We could get more configure notifies than that; some
3357 * of the configure notifies we get may be unrelated to
3358 * the configure requests. But we will get at least
3359 * window->configure_request_count notifies.
3362 if (window->configure_request_count > 0)
3363 window->configure_request_count -= 1;
3365 /* As an optimization, we avoid a resize when possible.
3367 * The only times we can avoid a resize are:
3368 * - we know only the position changed, not the size
3369 * - we know we have made more requests and so will get more
3370 * notifies and can wait to resize when we get them
3373 if (window->configure_request_count > 0 ||
3374 (widget->allocation.width == event->width &&
3375 widget->allocation.height == event->height))
3379 * If we do need to resize, we do that by:
3380 * - filling in widget->allocation with the new size
3381 * - setting configure_notify_received to TRUE
3382 * for use in gtk_window_move_resize()
3383 * - queueing a resize, leading to invocation of
3384 * gtk_window_move_resize() in an idle handler
3388 window->configure_notify_received = TRUE;
3390 widget->allocation.width = event->width;
3391 widget->allocation.height = event->height;
3393 gtk_widget_queue_resize (widget);
3399 gtk_window_key_press_event (GtkWidget *widget,
3405 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3406 g_return_val_if_fail (event != NULL, FALSE);
3408 window = GTK_WINDOW (widget);
3412 if (window->focus_widget && window->focus_widget != widget &&
3413 GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
3414 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
3417 handled = gtk_window_mnemonic_activate (window,
3422 handled = gtk_accel_groups_activate (G_OBJECT (window), event->keyval, event->state);
3424 /* Chain up, invokes binding set */
3425 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
3426 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
3433 gtk_window_real_activate_default (GtkWindow *window)
3435 gtk_window_activate_default (window);
3439 gtk_window_real_activate_focus (GtkWindow *window)
3441 gtk_window_activate_focus (window);
3445 gtk_window_move_focus (GtkWindow *window,
3446 GtkDirectionType dir)
3448 gtk_widget_child_focus (GTK_WIDGET (window), dir);
3450 if (!GTK_CONTAINER (window)->focus_child)
3451 gtk_window_set_focus (window, NULL);
3455 gtk_window_key_release_event (GtkWidget *widget,
3461 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3462 g_return_val_if_fail (event != NULL, FALSE);
3464 window = GTK_WINDOW (widget);
3466 if (window->focus_widget &&
3467 window->focus_widget != widget &&
3468 GTK_WIDGET_SENSITIVE (window->focus_widget))
3470 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
3473 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
3474 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
3480 gtk_window_enter_notify_event (GtkWidget *widget,
3481 GdkEventCrossing *event)
3483 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3484 g_return_val_if_fail (event != NULL, FALSE);
3490 gtk_window_leave_notify_event (GtkWidget *widget,
3491 GdkEventCrossing *event)
3493 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3494 g_return_val_if_fail (event != NULL, FALSE);
3500 gtk_window_focus_in_event (GtkWidget *widget,
3501 GdkEventFocus *event)
3503 GtkWindow *window = GTK_WINDOW (widget);
3504 GdkEventFocus fevent;
3506 /* It appears spurious focus in events can occur when
3507 * the window is hidden. So we'll just check to see if
3508 * the window is visible before actually handling the
3511 if (GTK_WIDGET_VISIBLE (widget))
3513 window->has_focus = TRUE;
3515 if (window->focus_widget &&
3516 window->focus_widget != widget &&
3517 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
3519 fevent.type = GDK_FOCUS_CHANGE;
3520 fevent.window = window->focus_widget->window;
3523 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
3531 gtk_window_focus_out_event (GtkWidget *widget,
3532 GdkEventFocus *event)
3534 GtkWindow *window = GTK_WINDOW (widget);
3535 GdkEventFocus fevent;
3537 window->has_focus = FALSE;
3539 if (window->focus_widget &&
3540 window->focus_widget != widget &&
3541 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
3543 fevent.type = GDK_FOCUS_CHANGE;
3544 fevent.window = window->focus_widget->window;
3547 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
3553 static GdkAtom atom_rcfiles = GDK_NONE;
3556 gtk_window_read_rcfiles (GtkWidget *widget,
3557 GdkEventClient *event)
3559 GList *embedded_windows;
3561 embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
3562 if (embedded_windows)
3567 for (i = 0; i < 5; i++)
3569 sev.data_format = 32;
3570 sev.message_type = atom_rcfiles;
3572 while (embedded_windows)
3574 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
3575 gdk_event_send_client_message ((GdkEvent *) &sev, xid);
3576 embedded_windows = embedded_windows->next;
3580 gtk_rc_reparse_all ();
3584 gtk_window_client_event (GtkWidget *widget,
3585 GdkEventClient *event)
3587 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3588 g_return_val_if_fail (event != NULL, FALSE);
3591 atom_rcfiles = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE);
3593 if (event->message_type == atom_rcfiles)
3594 gtk_window_read_rcfiles (widget, event);
3600 gtk_window_check_resize (GtkContainer *container)
3604 g_return_if_fail (GTK_IS_WINDOW (container));
3606 window = GTK_WINDOW (container);
3608 if (GTK_WIDGET_VISIBLE (container))
3609 gtk_window_move_resize (window);
3613 gtk_window_focus (GtkWidget *widget,
3614 GtkDirectionType direction)
3618 GtkContainer *container;
3619 GtkWidget *old_focus_child;
3622 container = GTK_CONTAINER (widget);
3623 window = GTK_WINDOW (widget);
3624 bin = GTK_BIN (widget);
3626 old_focus_child = container->focus_child;
3628 /* We need a special implementation here to deal properly with wrapping
3629 * around in the tab chain without the danger of going into an
3632 if (old_focus_child)
3634 if (gtk_widget_child_focus (old_focus_child, direction))
3638 if (window->focus_widget)
3640 /* Wrapped off the end, clear the focus setting for the toplpevel */
3641 parent = window->focus_widget->parent;
3644 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
3645 parent = GTK_WIDGET (parent)->parent;
3648 gtk_window_set_focus (GTK_WINDOW (container), NULL);
3651 /* Now try to focus the first widget in the window */
3654 if (gtk_widget_child_focus (bin->child, direction))
3662 gtk_window_real_set_focus (GtkWindow *window,
3665 GdkEventFocus event;
3666 gboolean def_flags = 0;
3668 g_return_if_fail (GTK_IS_WINDOW (window));
3670 if (window->default_widget)
3671 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
3673 if (window->focus_widget)
3675 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3676 (window->focus_widget != window->default_widget))
3678 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3680 if (window->default_widget)
3681 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3684 if (window->has_focus)
3686 event.type = GDK_FOCUS_CHANGE;
3687 event.window = window->focus_widget->window;
3690 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
3694 window->focus_widget = focus;
3696 if (window->focus_widget)
3698 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3699 (window->focus_widget != window->default_widget))
3701 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
3702 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3704 if (window->default_widget)
3705 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3708 if (window->has_focus)
3710 event.type = GDK_FOCUS_CHANGE;
3711 event.window = window->focus_widget->window;
3714 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
3718 if (window->default_widget &&
3719 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
3720 gtk_widget_queue_draw (window->default_widget);
3723 /*********************************
3724 * Functions related to resizing *
3725 *********************************/
3727 /* This function doesn't constrain to geometry hints */
3729 gtk_window_compute_configure_request_size (GtkWindow *window,
3733 GtkRequisition requisition;
3734 GtkWindowGeometryInfo *info;
3738 * - we've done a size request
3741 widget = GTK_WIDGET (window);
3743 info = gtk_window_get_geometry_info (window, FALSE);
3745 if (window->need_default_size)
3747 gtk_widget_get_child_requisition (widget, &requisition);
3749 /* Default to requisition */
3750 *width = requisition.width;
3751 *height = requisition.height;
3753 /* If window is empty so requests 0, default to random nonzero size */
3754 if (*width == 0 && *height == 0)
3760 /* Override requisition with default size */
3764 if (info->default_width > 0)
3765 *width = info->default_width;
3767 if (info->default_height > 0)
3768 *height = info->default_height;
3773 /* Default to keeping current size */
3774 *width = widget->allocation.width;
3775 *height = widget->allocation.height;
3778 /* Override any size with gtk_window_resize() values */
3781 if (info->resize_width > 0)
3782 *width = info->resize_width;
3784 if (info->resize_height > 0)
3785 *height = info->resize_height;
3790 gtk_window_compute_configure_request (GtkWindow *window,
3791 GdkRectangle *request,
3792 GdkGeometry *geometry,
3795 GdkGeometry new_geometry;
3799 GtkWindowPosition pos;
3800 GtkWidget *parent_widget;
3801 GtkWindowGeometryInfo *info;
3804 widget = GTK_WIDGET (window);
3806 gtk_widget_size_request (widget, NULL);
3807 gtk_window_compute_configure_request_size (window, &w, &h);
3809 gtk_window_compute_hints (window, &new_geometry, &new_flags);
3810 gtk_window_constrain_size (window,
3811 &new_geometry, new_flags,
3815 parent_widget = (GtkWidget*) window->transient_parent;
3817 pos = window->position;
3818 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
3819 (parent_widget == NULL ||
3820 !GTK_WIDGET_MAPPED (parent_widget)))
3821 pos = GTK_WIN_POS_NONE;
3823 info = gtk_window_get_geometry_info (window, TRUE);
3825 /* by default, don't change position requested */
3826 x = info->last.configure_request.x;
3827 y = info->last.configure_request.y;
3829 if (window->need_default_position)
3832 /* FIXME this all interrelates with window gravity.
3833 * For most of them I think we want to set GRAVITY_CENTER.
3835 * Not sure how to go about that.
3840 /* here we are only handling CENTER_ALWAYS
3841 * as it relates to default positioning,
3842 * where it's equivalent to simply CENTER
3844 case GTK_WIN_POS_CENTER_ALWAYS:
3845 case GTK_WIN_POS_CENTER:
3847 gint screen_width = gdk_screen_width ();
3848 gint screen_height = gdk_screen_height ();
3850 x = (screen_width - w) / 2;
3851 y = (screen_height - h) / 2;
3855 case GTK_WIN_POS_CENTER_ON_PARENT:
3859 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
3861 gdk_window_get_origin (parent_widget->window,
3864 x = ox + (parent_widget->allocation.width - w) / 2;
3865 y = oy + (parent_widget->allocation.height - h) / 2;
3869 case GTK_WIN_POS_MOUSE:
3871 gint screen_width = gdk_screen_width ();
3872 gint screen_height = gdk_screen_height ();
3875 gdk_window_get_pointer (NULL, &px, &py, NULL);
3878 x = CLAMP (x, 0, screen_width - w);
3879 y = CLAMP (y, 0, screen_height - h);
3886 } /* if (window->need_default_position) */
3888 if (window->need_default_position &&
3889 info->initial_pos_set)
3891 x = info->initial_x;
3892 y = info->initial_y;
3893 gtk_window_constrain_position (window, w, h, &x, &y);
3899 request->height = h;
3902 *geometry = new_geometry;
3908 gtk_window_constrain_position (GtkWindow *window,
3914 /* See long comments in gtk_window_move_resize()
3915 * on when it's safe to call this function.
3917 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
3919 gint center_x, center_y;
3920 gint screen_width = gdk_screen_width ();
3921 gint screen_height = gdk_screen_height ();
3923 center_x = (screen_width - new_width) / 2;
3924 center_y = (screen_height - new_height) / 2;
3932 gtk_window_move_resize (GtkWindow *window)
3936 * First we determine whether any information has changed that would
3937 * cause us to revise our last configure request. If we would send
3938 * a different configure request from last time, then
3939 * configure_request_size_changed = TRUE or
3940 * configure_request_pos_changed = TRUE. configure_request_size_changed
3941 * may be true due to new hints, a gtk_window_resize(), or whatever.
3942 * configure_request_pos_changed may be true due to gtk_window_set_position()
3943 * or gtk_window_move().
3945 * If the configure request has changed, we send off a new one. To
3946 * ensure GTK invariants are maintained (resize queue does what it
3947 * should), we go ahead and size_allocate the requested size in this
3950 * If the configure request has not changed, we don't ever resend
3951 * it, because it could mean fighting the user or window manager.
3954 * To prepare the configure request, we come up with a base size/pos:
3955 * - the one from gtk_window_move()/gtk_window_resize()
3956 * - else default_width, default_height if we haven't ever
3958 * - else the size request if we haven't ever been mapped,
3959 * as a substitute default size
3960 * - else the current size of the window, as received from
3961 * configure notifies (i.e. the current allocation)
3963 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
3964 * the position request to be centered.
3967 GtkContainer *container;
3968 GtkWindowGeometryInfo *info;
3969 GdkGeometry new_geometry;
3971 GdkRectangle new_request;
3972 gboolean configure_request_size_changed;
3973 gboolean configure_request_pos_changed;
3974 gboolean hints_changed; /* do we need to send these again */
3975 GtkWindowLastGeometryInfo saved_last_info;
3977 widget = GTK_WIDGET (window);
3978 container = GTK_CONTAINER (widget);
3979 info = gtk_window_get_geometry_info (window, TRUE);
3981 configure_request_size_changed = FALSE;
3982 configure_request_pos_changed = FALSE;
3984 gtk_window_compute_configure_request (window, &new_request,
3985 &new_geometry, &new_flags);
3987 /* This check implies the invariant that we never set info->last
3988 * without setting the hints and sending off a configure request.
3990 * If we change info->last without sending the request, we may
3993 if (info->last.configure_request.x != new_request.x ||
3994 info->last.configure_request.y != new_request.y)
3995 configure_request_pos_changed = TRUE;
3997 /* To change, we must be different from BOTH the last request, and
3998 * also our current size as received from the most recent configure
4001 * If different from last request, it means some sizing
4002 * parameters have changed; but one possible such sizing
4003 * parameter could be the current size.
4005 * We never want to re-request our current size, because that could
4006 * lead to some strange infinite loops if a window manager did
4007 * something insane but ICCCM-compliant such as add 2 to all
4008 * requested sizes. (i.e. if the WM always assigned a size that
4009 * was a function of the requested size, rather than a constraint
4010 * applied to requested size - so that requesting current size
4011 * did not result in getting that size back)
4013 * So here we detect and prevent any attempt to set size
4016 * (FIXME I think some race may be possible here, but
4017 * perhaps avoided by configure_request_count?)
4019 if ((info->last.configure_request.width != new_request.width ||
4020 info->last.configure_request.height != new_request.height) &&
4021 (widget->allocation.width != new_request.width ||
4022 widget->allocation.height != new_request.height))
4023 configure_request_size_changed = TRUE;
4026 hints_changed = FALSE;
4028 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
4029 &new_geometry, new_flags))
4031 hints_changed = TRUE;
4034 /* Position Constraints
4035 * ====================
4037 * POS_CENTER_ALWAYS is conceptually a constraint rather than
4038 * a default. The other POS_ values are used only when the
4039 * window is shown, not after that.
4041 * However, we can't implement a position constraint as
4042 * "anytime the window size changes, center the window"
4043 * because this may well end up fighting the WM or user. In
4044 * fact it gets in an infinite loop with at least one WM.
4046 * Basically, applications are in no way in a position to
4047 * constrain the position of a window, with one exception:
4048 * override redirect windows. (Really the intended purpose
4049 * of CENTER_ALWAYS anyhow, I would think.)
4051 * So the way we implement this "constraint" is to say that when WE
4052 * cause a move or resize, i.e. we make a configure request changing
4053 * window size, we recompute the CENTER_ALWAYS position to reflect
4054 * the new window size, and include it in our request. Also, if we
4055 * just turned on CENTER_ALWAYS we snap to center with a new
4056 * request. Otherwise, if we are just NOTIFIED of a move or resize
4057 * done by someone else e.g. the window manager, we do NOT send a
4058 * new configure request.
4060 * For override redirect windows, this works fine; all window
4061 * sizes are from our configure requests. For managed windows,
4062 * it is at least semi-sane, though who knows what the
4063 * app author is thinking.
4066 /* This condition should be kept in sync with the condition later on
4067 * that determines whether we send a configure request. i.e. we
4068 * should do this position constraining anytime we were going to
4069 * send a configure request anyhow, plus when constraints have
4072 if (configure_request_pos_changed ||
4073 configure_request_size_changed ||
4075 info->position_constraints_changed)
4077 /* We request the constrained position if:
4078 * - we were changing position, and need to clamp
4079 * the change to the constraint
4080 * - we're changing the size anyway
4081 * - set_position() was called to toggle CENTER_ALWAYS on
4084 gtk_window_constrain_position (window,
4090 /* Update whether we need to request a move */
4091 if (info->last.configure_request.x != new_request.x ||
4092 info->last.configure_request.y != new_request.y)
4093 configure_request_pos_changed = TRUE;
4095 configure_request_pos_changed = FALSE;
4100 int notify_x, notify_y;
4102 /* this is the position from the last configure notify */
4103 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
4105 g_print ("--- %s ---\n"
4106 "last : %d,%d\t%d x %d\n"
4107 "this : %d,%d\t%d x %d\n"
4108 "alloc: %d,%d\t%d x %d\n"
4110 "size_changed: %d pos_changed: %d hints_changed: %d\n"
4111 "configure_notify_received: %d\n"
4112 "configure_request_count: %d\n"
4113 "position_constraints_changed: %d\n",
4114 window->title ? window->title : "(no title)",
4115 info->last.configure_request.x,
4116 info->last.configure_request.y,
4117 info->last.configure_request.width,
4118 info->last.configure_request.height,
4124 widget->allocation.width,
4125 widget->allocation.height,
4126 widget->requisition.width,
4127 widget->requisition.height,
4128 configure_request_pos_changed,
4129 configure_request_size_changed,
4131 window->configure_notify_received,
4132 window->configure_request_count,
4133 info->position_constraints_changed);
4137 saved_last_info = info->last;
4138 info->last.geometry = new_geometry;
4139 info->last.flags = new_flags;
4140 info->last.configure_request = new_request;
4142 /* need to set PPosition so the WM will look at our position,
4143 * but we don't want to count PPosition coming and going as a hints
4144 * change for future iterations. So we saved info->last prior to
4148 /* Also, if the initial position was explicitly set, then we always
4149 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
4153 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
4154 * this is an initial map
4157 if ((configure_request_pos_changed ||
4158 info->initial_pos_set ||
4159 (window->need_default_position &&
4160 window->position != GTK_WIN_POS_NONE)) &&
4161 (new_flags & GDK_HINT_POS) == 0)
4163 new_flags |= GDK_HINT_POS;
4164 hints_changed = TRUE;
4167 /* Set hints if necessary
4170 gdk_window_set_geometry_hints (widget->window,
4174 /* handle resizing/moving and widget tree allocation
4176 if (window->configure_notify_received)
4178 GtkAllocation allocation;
4180 /* If we have received a configure event since
4181 * the last time in this function, we need to
4182 * accept our new size and size_allocate child widgets.
4183 * (see gtk_window_configure_event() for more details).
4185 * 1 or more configure notifies may have been received.
4186 * Also, configure_notify_received will only be TRUE
4187 * if all expected configure notifies have been received
4188 * (one per configure request), as an optimization.
4191 window->configure_notify_received = FALSE;
4193 /* gtk_window_configure_event() filled in widget->allocation */
4194 allocation = widget->allocation;
4195 gtk_widget_size_allocate (widget, &allocation);
4196 gtk_widget_queue_draw (widget);
4198 /* If the configure request changed, it means that
4200 * 1) coincidentally changed hints or widget properties
4201 * impacting the configure request before getting
4202 * a configure notify, or
4203 * 2) some broken widget is changing its size request
4204 * during size allocation, resulting in
4205 * a false appearance of changed configure request.
4207 * For 1), we could just go ahead and ask for the
4208 * new size right now, but doing that for 2)
4209 * might well be fighting the user (and can even
4210 * trigger a loop). Since we really don't want to
4211 * do that, we requeue a resize in hopes that
4212 * by the time it gets handled, the child has seen
4213 * the light and is willing to go along with the
4214 * new size. (this happens for the zvt widget, since
4215 * the size_allocate() above will have stored the
4216 * requisition corresponding to the new size in the
4219 * This doesn't buy us anything for 1), but it shouldn't
4220 * hurt us too badly, since it is what would have
4221 * happened if we had gotten the configure event before
4222 * the new size had been set.
4225 if (configure_request_size_changed ||
4226 configure_request_pos_changed)
4228 /* Don't change the recorded last info after all, because we
4229 * haven't actually updated to the new info yet - we decided
4230 * to postpone our configure request until later.
4232 info->last = saved_last_info;
4234 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
4237 else if (configure_request_pos_changed ||
4238 configure_request_size_changed ||
4241 /* We are in one of the following situations:
4242 * A. configure_request_size_changed
4243 * our requisition has changed and we need a different window size,
4244 * so we request it from the window manager.
4245 * B. !configure_request_size_changed
4246 * the window manager wouldn't assign us the size we requested, in this
4247 * case we don't try to request a new size with every resize.
4248 * C. !configure_request_size_changed && hints_changed
4249 * the window manager rejects our size, but we have just changed the
4250 * window manager hints, so there's a certain chance our request will
4251 * be honoured this time, so we try again.
4252 * D. configure_request_pos_changed
4253 * we need to move to a new position, in which case we can also request
4254 * a new size since any of A-C might also apply.
4257 /* Now send the configure request */
4258 if (configure_request_pos_changed)
4262 gdk_window_move_resize (window->frame,
4263 new_request.x - window->frame_left,
4264 new_request.y - window->frame_top,
4265 new_request.width + window->frame_left + window->frame_right,
4266 new_request.height + window->frame_top + window->frame_bottom);
4267 gdk_window_resize (GTK_WIDGET (window)->window,
4268 new_request.width, new_request.height);
4271 gdk_window_move_resize (widget->window,
4272 new_request.x, new_request.y,
4273 new_request.width, new_request.height);
4275 else /* only size changed */
4278 gdk_window_resize (window->frame,
4279 new_request.width + window->frame_left + window->frame_right,
4280 new_request.height + window->frame_top + window->frame_bottom);
4281 gdk_window_resize (widget->window,
4282 new_request.width, new_request.height);
4285 /* Increment the number of have-not-yet-received-notify requests */
4286 window->configure_request_count += 1;
4288 /* We have now sent a request since the last position constraint
4289 * change and definitely don't need a an initial size again (not
4290 * resetting this here can lead to infinite loops for
4291 * GTK_RESIZE_IMMEDIATE containers)
4293 info->position_constraints_changed = FALSE;
4294 window->need_default_position = FALSE;
4296 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
4297 * configure event in response to our resizing request.
4298 * the configure event will cause a new resize with
4299 * ->configure_notify_received=TRUE.
4300 * until then, we want to
4301 * - discard expose events
4302 * - coalesce resizes for our children
4303 * - defer any window resizes until the configure event arrived
4304 * to achieve this, we queue a resize for the window, but remove its
4305 * resizing handler, so resizing will not be handled from the next
4306 * idle handler but when the configure event arrives.
4308 * FIXME: we should also dequeue the pending redraws here, since
4309 * we handle those ourselves upon ->configure_notify_received==TRUE.
4311 if (container->resize_mode == GTK_RESIZE_QUEUE)
4313 gtk_widget_queue_resize (widget);
4314 _gtk_container_dequeue_resize_handler (container);
4319 /* Not requesting anything new from WM, just had a queue resize
4320 * for some reason, so handle the resize queue
4322 if (container->resize_widgets)
4323 gtk_container_resize_children (container);
4327 /* Compare two sets of Geometry hints for equality.
4330 gtk_window_compare_hints (GdkGeometry *geometry_a,
4332 GdkGeometry *geometry_b,
4335 if (flags_a != flags_b)
4338 if ((flags_a & GDK_HINT_MIN_SIZE) &&
4339 (geometry_a->min_width != geometry_b->min_width ||
4340 geometry_a->min_height != geometry_b->min_height))
4343 if ((flags_a & GDK_HINT_MAX_SIZE) &&
4344 (geometry_a->max_width != geometry_b->max_width ||
4345 geometry_a->max_height != geometry_b->max_height))
4348 if ((flags_a & GDK_HINT_BASE_SIZE) &&
4349 (geometry_a->base_width != geometry_b->base_width ||
4350 geometry_a->base_height != geometry_b->base_height))
4353 if ((flags_a & GDK_HINT_ASPECT) &&
4354 (geometry_a->min_aspect != geometry_b->min_aspect ||
4355 geometry_a->max_aspect != geometry_b->max_aspect))
4358 if ((flags_a & GDK_HINT_RESIZE_INC) &&
4359 (geometry_a->width_inc != geometry_b->width_inc ||
4360 geometry_a->height_inc != geometry_b->height_inc))
4363 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
4364 geometry_a->win_gravity != geometry_b->win_gravity)
4371 _gtk_window_constrain_size (GtkWindow *window,
4377 GtkWindowGeometryInfo *info;
4379 g_return_if_fail (GTK_IS_WINDOW (window));
4381 info = window->geometry_info;
4384 GdkWindowHints flags = info->last.flags;
4385 GdkGeometry *geometry = &info->last.geometry;
4387 gtk_window_constrain_size (window,
4398 gtk_window_constrain_size (GtkWindow *window,
4399 GdkGeometry *geometry,
4406 gdk_window_constrain_size (geometry, flags, width, height,
4407 new_width, new_height);
4410 /* Compute the set of geometry hints and flags for a window
4411 * based on the application set geometry, and requisiition
4412 * of the window. gtk_widget_size_request() must have been
4416 gtk_window_compute_hints (GtkWindow *window,
4417 GdkGeometry *new_geometry,
4421 gint extra_width = 0;
4422 gint extra_height = 0;
4423 GtkWindowGeometryInfo *geometry_info;
4424 GtkRequisition requisition;
4426 g_return_if_fail (GTK_IS_WINDOW (window));
4428 widget = GTK_WIDGET (window);
4430 gtk_widget_get_child_requisition (widget, &requisition);
4431 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
4435 *new_flags = geometry_info->mask;
4436 *new_geometry = geometry_info->geometry;
4443 if (geometry_info && geometry_info->widget)
4445 extra_width = widget->requisition.width - geometry_info->widget->requisition.width;
4446 extra_height = widget->requisition.height - geometry_info->widget->requisition.height;
4449 /* We don't want to set GDK_HINT_POS in here, we just set it
4450 * in gtk_window_move_resize() when we want the position
4454 if (*new_flags & GDK_HINT_BASE_SIZE)
4456 new_geometry->base_width += extra_width;
4457 new_geometry->base_height += extra_height;
4459 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
4460 (*new_flags & GDK_HINT_RESIZE_INC) &&
4461 ((extra_width != 0) || (extra_height != 0)))
4463 *new_flags |= GDK_HINT_BASE_SIZE;
4465 new_geometry->base_width = extra_width;
4466 new_geometry->base_height = extra_height;
4469 if (*new_flags & GDK_HINT_MIN_SIZE)
4471 if (new_geometry->min_width < 0)
4472 new_geometry->min_width = requisition.width;
4474 new_geometry->min_width += extra_width;
4476 if (new_geometry->min_height < 0)
4477 new_geometry->min_height = requisition.height;
4479 new_geometry->min_height += extra_height;
4481 else if (!window->allow_shrink)
4483 *new_flags |= GDK_HINT_MIN_SIZE;
4485 new_geometry->min_width = requisition.width;
4486 new_geometry->min_height = requisition.height;
4489 if (*new_flags & GDK_HINT_MAX_SIZE)
4491 if (new_geometry->max_width < 0)
4492 new_geometry->max_width = requisition.width;
4494 new_geometry->max_width += extra_width;
4496 if (new_geometry->max_height < 0)
4497 new_geometry->max_width = requisition.height;
4499 new_geometry->max_height += extra_height;
4501 else if (!window->allow_grow)
4503 *new_flags |= GDK_HINT_MAX_SIZE;
4505 new_geometry->max_width = requisition.width;
4506 new_geometry->max_height = requisition.height;
4509 *new_flags |= GDK_HINT_WIN_GRAVITY;
4510 new_geometry->win_gravity = window->gravity;
4513 /***********************
4514 * Redrawing functions *
4515 ***********************/
4518 gtk_window_paint (GtkWidget *widget,
4521 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
4522 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
4526 gtk_window_expose (GtkWidget *widget,
4527 GdkEventExpose *event)
4529 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
4530 g_return_val_if_fail (event != NULL, FALSE);
4532 if (!GTK_WIDGET_APP_PAINTABLE (widget))
4533 gtk_window_paint (widget, &event->area);
4535 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
4536 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
4542 * gtk_window_set_has_frame:
4543 * @window: a #GtkWindow
4544 * @setting: a boolean
4546 * If this function is called on a window with setting of TRUE, before
4547 * it is realized or showed, it will have a "frame" window around
4548 * widget->window, accessible in window->frame. Using the signal
4549 * frame_event you can recieve all events targeted at the frame.
4551 * This function is used by the linux-fb port to implement managed
4552 * windows, but it could concievably be used by X-programs that
4553 * want to do their own window decorations.
4556 gtk_window_set_has_frame (GtkWindow *window,
4559 g_return_if_fail (GTK_IS_WINDOW (window));
4560 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
4562 window->has_frame = setting != FALSE;
4566 * gtk_window_get_has_frame:
4567 * @window: a #GtkWindow
4569 * Returns whether the window has a frame window exterior to
4570 * widget->window. See gtk_window_set_has_frame ().
4572 * Return value: %TRUE if a frame has been added to the window
4573 * via gtk_widow_has_frame
4576 gtk_window_get_has_frame (GtkWindow *window)
4578 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4580 return window->has_frame;
4584 * gtk_window_set_frame_dimensions:
4585 * @window: a #GtkWindow that has a frame
4586 * @left: The width of the left border
4587 * @top: The height of the top border
4588 * @right: The width of the right border
4589 * @bottom: The height of the bottom border
4591 * For windows with frames (see #gtk_window_set_has_frame) this function
4592 * can be used to change the size of the frame border.
4595 gtk_window_set_frame_dimensions (GtkWindow *window,
4601 GtkWidget *widget = GTK_WIDGET (window);
4603 g_return_if_fail (GTK_IS_WINDOW (window));
4605 if (window->frame_left == left &&
4606 window->frame_top == top &&
4607 window->frame_right == right &&
4608 window->frame_bottom == bottom)
4611 window->frame_left = left;
4612 window->frame_top = top;
4613 window->frame_right = right;
4614 window->frame_bottom = bottom;
4616 if (GTK_WIDGET_REALIZED (widget) && window->frame)
4618 gint width = widget->allocation.width + left + right;
4619 gint height = widget->allocation.height + top + bottom;
4620 gdk_window_resize (window->frame, width, height);
4621 gtk_decorated_window_move_resize_window (window,
4623 widget->allocation.width,
4624 widget->allocation.height);
4629 * gtk_window_present:
4630 * @window: a #GtkWindow
4632 * Presents a window to the user. This may mean raising the window
4633 * in the stacking order, deiconifying it, moving it to the current
4634 * desktop, and/or giving it the keyboard focus, possibly dependent
4635 * on the user's platform, window manager, and preferences.
4637 * If @window is hidden, this function calls gtk_widget_show()
4640 * This function should be used when the user tries to open a window
4641 * that's already open. Say for example the preferences dialog is
4642 * currently open, and the user chooses Preferences from the menu
4643 * a second time; use gtk_window_present() to move the already-open dialog
4644 * where the user can see it.
4648 gtk_window_present (GtkWindow *window)
4652 g_return_if_fail (GTK_IS_WINDOW (window));
4654 widget = GTK_WIDGET (window);
4656 if (GTK_WIDGET_VISIBLE (window))
4658 g_assert (widget->window != NULL);
4660 gdk_window_show (widget->window);
4662 /* note that gdk_window_focus() will also move the window to
4663 * the current desktop, for WM spec compliant window managers.
4665 gdk_window_focus (widget->window,
4666 gtk_get_current_event_time ());
4670 gtk_widget_show (widget);
4675 * gtk_window_iconify:
4676 * @window: a #GtkWindow
4678 * Asks to iconify (i.e. minimize) the specified @window. Note that you
4679 * shouldn't assume the window is definitely iconified afterward,
4680 * because other entities (e.g. the user or window manager) could
4681 * deiconify it again, or there may not be a window manager in which
4682 * case iconification isn't possible, etc. But normally the window
4683 * will end up iconified. Just don't write code that crashes if not.
4685 * It's permitted to call this function before showing a window,
4686 * in which case the window will be iconified before it ever appears
4689 * You can track iconification via the "window_state_event" signal
4694 gtk_window_iconify (GtkWindow *window)
4697 GdkWindow *toplevel;
4699 g_return_if_fail (GTK_IS_WINDOW (window));
4701 widget = GTK_WIDGET (window);
4703 window->iconify_initially = TRUE;
4706 toplevel = window->frame;
4708 toplevel = widget->window;
4710 if (toplevel != NULL)
4711 gdk_window_iconify (toplevel);
4715 * gtk_window_deiconify:
4716 * @window: a #GtkWindow
4718 * Asks to deiconify (i.e. unminimize) the specified @window. Note
4719 * that you shouldn't assume the window is definitely deiconified
4720 * afterward, because other entities (e.g. the user or window manager)
4721 * could iconify it again before your code which assumes
4722 * deiconification gets to run.
4724 * You can track iconification via the "window_state_event" signal
4728 gtk_window_deiconify (GtkWindow *window)
4731 GdkWindow *toplevel;
4733 g_return_if_fail (GTK_IS_WINDOW (window));
4735 widget = GTK_WIDGET (window);
4737 window->iconify_initially = FALSE;
4740 toplevel = window->frame;
4742 toplevel = widget->window;
4744 if (toplevel != NULL)
4745 gdk_window_deiconify (toplevel);
4750 * @window: a #GtkWindow
4752 * Asks to stick @window, which means that it will appear on all user
4753 * desktops. Note that you shouldn't assume the window is definitely
4754 * stuck afterward, because other entities (e.g. the user or window
4755 * manager) could unstick it again, and some window managers do not
4756 * support sticking windows. But normally the window will end up
4757 * stuck. Just don't write code that crashes if not.
4759 * It's permitted to call this function before showing a window.
4761 * You can track stickiness via the "window_state_event" signal
4766 gtk_window_stick (GtkWindow *window)
4769 GdkWindow *toplevel;
4771 g_return_if_fail (GTK_IS_WINDOW (window));
4773 widget = GTK_WIDGET (window);
4775 window->stick_initially = TRUE;
4778 toplevel = window->frame;
4780 toplevel = widget->window;
4782 if (toplevel != NULL)
4783 gdk_window_stick (toplevel);
4787 * gtk_window_unstick:
4788 * @window: a #GtkWindow
4790 * Asks to unstick @window, which means that it will appear on only
4791 * one of the user's desktops. Note that you shouldn't assume the
4792 * window is definitely unstuck afterward, because other entities
4793 * (e.g. the user or window manager) could stick it again. But
4794 * normally the window will end up stuck. Just don't write code that
4797 * You can track stickiness via the "window_state_event" signal
4802 gtk_window_unstick (GtkWindow *window)
4805 GdkWindow *toplevel;
4807 g_return_if_fail (GTK_IS_WINDOW (window));
4809 widget = GTK_WIDGET (window);
4811 window->stick_initially = FALSE;
4814 toplevel = window->frame;
4816 toplevel = widget->window;
4818 if (toplevel != NULL)
4819 gdk_window_unstick (toplevel);
4823 * gtk_window_maximize:
4824 * @window: a #GtkWindow
4826 * Asks to maximize @window, so that it becomes full-screen. Note that
4827 * you shouldn't assume the window is definitely maximized afterward,
4828 * because other entities (e.g. the user or window manager) could
4829 * unmaximize it again, and not all window managers support
4830 * maximization. But normally the window will end up maximized. Just
4831 * don't write code that crashes if not.
4833 * It's permitted to call this function before showing a window,
4834 * in which case the window will be maximized when it appears onscreen
4837 * You can track maximization via the "window_state_event" signal
4842 gtk_window_maximize (GtkWindow *window)
4845 GdkWindow *toplevel;
4847 g_return_if_fail (GTK_IS_WINDOW (window));
4849 widget = GTK_WIDGET (window);
4851 window->maximize_initially = TRUE;
4854 toplevel = window->frame;
4856 toplevel = widget->window;
4858 if (toplevel != NULL)
4859 gdk_window_maximize (toplevel);
4863 * gtk_window_unmaximize:
4864 * @window: a #GtkWindow
4866 * Asks to unmaximize @window. Note that you shouldn't assume the
4867 * window is definitely unmaximized afterward, because other entities
4868 * (e.g. the user or window manager) could maximize it again, and not
4869 * all window managers honor requests to unmaximize. But normally the
4870 * window will end up unmaximized. Just don't write code that crashes
4873 * You can track maximization via the "window_state_event" signal
4878 gtk_window_unmaximize (GtkWindow *window)
4881 GdkWindow *toplevel;
4883 g_return_if_fail (GTK_IS_WINDOW (window));
4885 widget = GTK_WIDGET (window);
4887 window->maximize_initially = FALSE;
4890 toplevel = window->frame;
4892 toplevel = widget->window;
4894 if (toplevel != NULL)
4895 gdk_window_unmaximize (toplevel);
4899 * gtk_window_set_resizable:
4900 * @window: a #GtkWindow
4901 * @resizable: %TRUE if the user can resize this window
4903 * Sets whether the user can resize a window. Windows are user resizable
4907 gtk_window_set_resizable (GtkWindow *window,
4910 g_return_if_fail (GTK_IS_WINDOW (window));
4912 gtk_window_set_policy (window, FALSE, resizable, FALSE);
4916 * gtk_window_get_resizable:
4917 * @window: a #GtkWindow
4919 * Gets the value set by gtk_window_set_resizable().
4921 * Return value: %TRUE if the user can resize the window
4924 gtk_window_get_resizable (GtkWindow *window)
4926 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4928 /* allow_grow is most likely to indicate the semantic concept we
4929 * mean by "resizable" (and will be a reliable indicator if
4930 * set_policy() hasn't been called)
4932 return window->allow_grow;
4936 * gtk_window_set_gravity:
4937 * @window: a #GtkWindow
4938 * @gravity: window gravity
4940 * Window gravity defines the meaning of coordinates passed to
4941 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
4944 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
4945 * typically "do what you mean."
4949 gtk_window_set_gravity (GtkWindow *window,
4952 g_return_if_fail (GTK_IS_WINDOW (window));
4954 if (gravity != window->gravity)
4956 window->gravity = gravity;
4958 /* gtk_window_move_resize() will adapt gravity
4960 gtk_widget_queue_resize (GTK_WIDGET (window));
4965 * gtk_window_get_gravity:
4966 * @window: a #GtkWindow
4968 * Gets the value set by gtk_window_set_gravity().
4970 * Return value: window gravity
4973 gtk_window_get_gravity (GtkWindow *window)
4975 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
4977 return window->gravity;
4981 * gtk_window_begin_resize_drag:
4982 * @window: a #GtkWindow
4983 * @button: mouse button that initiated the drag
4984 * @edge: position of the resize control
4985 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
4986 * @root_y: Y position where the user clicked to initiate the drag
4987 * @timestamp: timestamp from the click event that initiated the drag
4989 * Starts resizing a window. This function is used if an application
4990 * has window resizing controls. When GDK can support it, the resize
4991 * will be done using the standard mechanism for the window manager or
4992 * windowing system. Otherwise, GDK will try to emulate window
4993 * resizing, potentially not all that well, depending on the windowing system.
4997 gtk_window_begin_resize_drag (GtkWindow *window,
5005 GdkWindow *toplevel;
5007 g_return_if_fail (GTK_IS_WINDOW (window));
5008 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5010 widget = GTK_WIDGET (window);
5013 toplevel = window->frame;
5015 toplevel = widget->window;
5017 gdk_window_begin_resize_drag (toplevel,
5024 * gtk_window_get_frame_dimensions:
5025 * @window: a #GtkWindow
5026 * @left: location to store the width of the frame at the left, or %NULL
5027 * @top: location to store the height of the frame at the top, or %NULL
5028 * @right: location to store the width of the frame at the returns, or %NULL
5029 * @bottom: location to store the height of the frame at the bottom, or %NULL
5031 * Retrieves the dimensions of the frame window for this toplevel.
5032 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
5035 gtk_window_get_frame_dimensions (GtkWindow *window,
5041 g_return_if_fail (GTK_IS_WINDOW (window));
5044 *left = window->frame_left;
5046 *top = window->frame_top;
5048 *top = window->frame_right;
5050 *top = window->frame_bottom;
5054 * gtk_window_begin_move_drag:
5055 * @window: a #GtkWindow
5056 * @button: mouse button that initiated the drag
5057 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5058 * @root_y: Y position where the user clicked to initiate the drag
5059 * @timestamp: timestamp from the click event that initiated the drag
5061 * Starts moving a window. This function is used if an application
5062 * has window movement grips. When GDK can support it, the window movement
5063 * will be done using the standard mechanism for the window manager or
5064 * windowing system. Otherwise, GDK will try to emulate window
5065 * movement, potentially not all that well, depending on the windowing system.
5069 gtk_window_begin_move_drag (GtkWindow *window,
5076 GdkWindow *toplevel;
5078 g_return_if_fail (GTK_IS_WINDOW (window));
5079 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5081 widget = GTK_WIDGET (window);
5084 toplevel = window->frame;
5086 toplevel = widget->window;
5088 gdk_window_begin_move_drag (toplevel,
5096 gtk_window_group_class_init (GtkWindowGroupClass *klass)
5101 gtk_window_group_get_type (void)
5103 static GtkType window_group_type = 0;
5105 if (!window_group_type)
5107 static const GTypeInfo window_group_info =
5109 sizeof (GtkWindowGroupClass),
5110 NULL, /* base_init */
5111 NULL, /* base_finalize */
5112 (GClassInitFunc) gtk_window_group_class_init,
5113 NULL, /* class_finalize */
5114 NULL, /* class_data */
5115 sizeof (GtkWindowGroup),
5116 16, /* n_preallocs */
5117 (GInstanceInitFunc) NULL,
5120 window_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkWindowGroup", &window_group_info, 0);
5123 return window_group_type;
5127 * gtk_window_group_new:
5129 * Create a new #GtkWindowGroup object. Grabs added with
5130 * gtk_window_grab_add() only affect windows within the
5131 * same #GtkWindowGroup
5136 gtk_window_group_new (void)
5138 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
5142 window_group_cleanup_grabs (GtkWindowGroup *group,
5146 GSList *to_remove = NULL;
5148 tmp_list = group->grabs;
5151 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
5152 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
5153 tmp_list = tmp_list->next;
5158 gtk_grab_remove (to_remove->data);
5159 g_object_unref (to_remove->data);
5160 to_remove = g_slist_delete_link (to_remove, to_remove);
5165 * gtk_window_group_add_widget:
5166 * @window_group: a #GtkWindowGroup
5167 * @window: the #GtkWindow to add
5169 * Add a window to a #GtkWindowGroup.
5172 gtk_window_group_add_window (GtkWindowGroup *window_group,
5175 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5176 g_return_if_fail (GTK_IS_WINDOW (window));
5178 if (window->group != window_group)
5180 g_object_ref (window);
5181 g_object_ref (window_group);
5184 gtk_window_group_remove_window (window->group, window);
5186 window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
5188 window->group = window_group;
5190 g_object_unref (window);
5195 * gtk_window_group_remove_window:
5196 * @window_group: a #GtkWindowGroup
5197 * @window: the #GtkWindow to remove
5199 * Removes a window from a #GtkWindowGroup.
5202 gtk_window_group_remove_window (GtkWindowGroup *window_group,
5205 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5206 g_return_if_fail (GTK_IS_WIDGET (window));
5207 g_return_if_fail (window->group == window_group);
5209 g_object_ref (window);
5211 window_group_cleanup_grabs (window_group, window);
5212 window->group = NULL;
5214 g_object_unref (G_OBJECT (window_group));
5215 g_object_unref (window);
5218 /* Return the group for the window or the default group
5221 _gtk_window_get_group (GtkWindow *window)
5223 if (window && window->group)
5224 return window->group;
5227 static GtkWindowGroup *default_group = NULL;
5230 default_group = gtk_window_group_new ();
5232 return default_group;
5238 Derived from XParseGeometry() in XFree86
5240 Copyright 1985, 1986, 1987,1998 The Open Group
5242 All Rights Reserved.
5244 The above copyright notice and this permission notice shall be included
5245 in all copies or substantial portions of the Software.
5247 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
5248 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
5249 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
5250 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
5251 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
5252 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
5253 OTHER DEALINGS IN THE SOFTWARE.
5255 Except as contained in this notice, the name of The Open Group shall
5256 not be used in advertising or otherwise to promote the sale, use or
5257 other dealings in this Software without prior written authorization
5258 from The Open Group.
5263 * XParseGeometry parses strings of the form
5264 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
5265 * width, height, xoffset, and yoffset are unsigned integers.
5266 * Example: "=80x24+300-49"
5267 * The equal sign is optional.
5268 * It returns a bitmask that indicates which of the four values
5269 * were actually found in the string. For each value found,
5270 * the corresponding argument is updated; for each value
5271 * not found, the corresponding argument is left unchanged.
5274 /* The following code is from Xlib, and is minimally modified, so we
5275 * can track any upstream changes if required. Don't change this
5276 * code. Or if you do, put in a huge comment marking which thing
5281 read_int (gchar *string,
5289 else if (*string == '-')
5295 for (; (*string >= '0') && (*string <= '9'); string++)
5297 result = (result * 10) + (*string - '0');
5309 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
5310 * value (x, y, width, height) was found in the parsed string.
5312 #define NoValue 0x0000
5313 #define XValue 0x0001
5314 #define YValue 0x0002
5315 #define WidthValue 0x0004
5316 #define HeightValue 0x0008
5317 #define AllValues 0x000F
5318 #define XNegative 0x0010
5319 #define YNegative 0x0020
5321 /* Try not to reformat/modify, so we can compare/sync with X sources */
5323 gtk_XParseGeometry (const char *string,
5326 unsigned int *width,
5327 unsigned int *height)
5331 unsigned int tempWidth, tempHeight;
5333 char *nextCharacter;
5335 /* These initializations are just to silence gcc */
5341 if ( (string == NULL) || (*string == '\0')) return(mask);
5343 string++; /* ignore possible '=' at beg of geometry spec */
5345 strind = (char *)string;
5346 if (*strind != '+' && *strind != '-' && *strind != 'x') {
5347 tempWidth = read_int(strind, &nextCharacter);
5348 if (strind == nextCharacter)
5350 strind = nextCharacter;
5354 if (*strind == 'x' || *strind == 'X') {
5356 tempHeight = read_int(strind, &nextCharacter);
5357 if (strind == nextCharacter)
5359 strind = nextCharacter;
5360 mask |= HeightValue;
5363 if ((*strind == '+') || (*strind == '-')) {
5364 if (*strind == '-') {
5366 tempX = -read_int(strind, &nextCharacter);
5367 if (strind == nextCharacter)
5369 strind = nextCharacter;
5375 tempX = read_int(strind, &nextCharacter);
5376 if (strind == nextCharacter)
5378 strind = nextCharacter;
5381 if ((*strind == '+') || (*strind == '-')) {
5382 if (*strind == '-') {
5384 tempY = -read_int(strind, &nextCharacter);
5385 if (strind == nextCharacter)
5387 strind = nextCharacter;
5394 tempY = read_int(strind, &nextCharacter);
5395 if (strind == nextCharacter)
5397 strind = nextCharacter;
5403 /* If strind isn't at the end of the string the it's an invalid
5404 geometry specification. */
5406 if (*strind != '\0') return (0);
5412 if (mask & WidthValue)
5414 if (mask & HeightValue)
5415 *height = tempHeight;
5420 * gtk_window_parse_geometry:
5421 * @window: a #GtkWindow
5422 * @geometry: geometry string
5424 * Parses a standard X Window System geometry string - see the
5425 * manual page for X (type 'man X') for details on this.
5426 * gtk_window_parse_geometry() does work on all GTK+ ports
5427 * including Win32 but is primarily intended for an X environment.
5429 * If either a size or a position can be extracted from the
5430 * geometry string, gtk_window_parse_geometry() returns %TRUE
5431 * and calls gtk_window_set_default_size() and/or gtk_window_move()
5432 * to resize/move the window.
5434 * If gtk_window_parse_geometry() returns %TRUE, it will also
5435 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
5436 * indicating to the window manager that the size/position of
5437 * the window was user-specified. This causes most window
5438 * managers to honor the geometry.
5440 * Return value: %TRUE if string was parsed successfully
5443 gtk_window_parse_geometry (GtkWindow *window,
5444 const gchar *geometry)
5449 gboolean size_set, pos_set;
5451 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5452 g_return_val_if_fail (geometry != NULL, FALSE);
5454 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
5456 if ((result & WidthValue) == 0 ||
5459 if ((result & HeightValue) == 0 ||
5464 if ((result & WidthValue) || (result & HeightValue))
5466 gtk_window_set_default_size (window, w, h);
5470 gtk_window_get_size (window, &w, &h);
5472 grav = GDK_GRAVITY_NORTH_WEST;
5474 if ((result & XNegative) && (result & YNegative))
5475 grav = GDK_GRAVITY_SOUTH_EAST;
5476 else if (result & XNegative)
5477 grav = GDK_GRAVITY_NORTH_EAST;
5478 else if (result & YNegative)
5479 grav = GDK_GRAVITY_SOUTH_WEST;
5481 if ((result & XValue) == 0)
5484 if ((result & YValue) == 0)
5487 if (grav == GDK_GRAVITY_SOUTH_WEST ||
5488 grav == GDK_GRAVITY_SOUTH_EAST)
5489 y = gdk_screen_height () - h;
5491 if (grav == GDK_GRAVITY_SOUTH_EAST ||
5492 grav == GDK_GRAVITY_NORTH_EAST)
5493 x = gdk_screen_width () - w;
5502 if ((result & XValue) || (result & YValue))
5504 gtk_window_set_gravity (window, grav);
5505 gtk_window_move (window, x, y);
5509 if (size_set || pos_set)
5511 /* Set USSize, USPosition hints */
5512 GtkWindowGeometryInfo *info;
5514 info = gtk_window_get_geometry_info (window, TRUE);
5517 info->mask |= GDK_HINT_USER_POS;
5519 info->mask |= GDK_HINT_USER_SIZE;