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 Library 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 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library 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-1999. 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 #include "gtkprivate.h"
34 #include "gtksignal.h"
35 #include "gtkwindow.h"
36 #include "gtkbindings.h"
62 } GtkWindowGeometryInfo;
64 static void gtk_window_class_init (GtkWindowClass *klass);
65 static void gtk_window_init (GtkWindow *window);
66 static void gtk_window_set_arg (GtkObject *object,
69 static void gtk_window_get_arg (GtkObject *object,
72 static void gtk_window_shutdown (GtkObject *object);
73 static void gtk_window_destroy (GtkObject *object);
74 static void gtk_window_finalize (GtkObject *object);
75 static void gtk_window_show (GtkWidget *widget);
76 static void gtk_window_hide (GtkWidget *widget);
77 static void gtk_window_map (GtkWidget *widget);
78 static void gtk_window_unmap (GtkWidget *widget);
79 static void gtk_window_realize (GtkWidget *widget);
80 static void gtk_window_size_request (GtkWidget *widget,
81 GtkRequisition *requisition);
82 static void gtk_window_size_allocate (GtkWidget *widget,
83 GtkAllocation *allocation);
84 static gint gtk_window_configure_event (GtkWidget *widget,
85 GdkEventConfigure *event);
86 static gint gtk_window_key_press_event (GtkWidget *widget,
88 static gint gtk_window_key_release_event (GtkWidget *widget,
90 static gint gtk_window_enter_notify_event (GtkWidget *widget,
91 GdkEventCrossing *event);
92 static gint gtk_window_leave_notify_event (GtkWidget *widget,
93 GdkEventCrossing *event);
94 static gint gtk_window_focus_in_event (GtkWidget *widget,
95 GdkEventFocus *event);
96 static gint gtk_window_focus_out_event (GtkWidget *widget,
97 GdkEventFocus *event);
98 static gint gtk_window_client_event (GtkWidget *widget,
99 GdkEventClient *event);
100 static void gtk_window_check_resize (GtkContainer *container);
101 static void gtk_window_real_set_focus (GtkWindow *window,
103 static void gtk_window_move_resize (GtkWindow *window);
104 static void gtk_window_set_hints (GtkWidget *widget,
105 GtkRequisition *requisition);
107 static void gtk_window_read_rcfiles (GtkWidget *widget,
108 GdkEventClient *event);
109 static void gtk_window_draw (GtkWidget *widget,
111 static void gtk_window_paint (GtkWidget *widget,
113 static gint gtk_window_expose (GtkWidget *widget,
114 GdkEventExpose *event);
115 static void gtk_window_unset_transient_for (GtkWindow *window);
116 static void gtk_window_transient_parent_realized (GtkWidget *parent,
118 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
121 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
123 static void gtk_window_geometry_destroy (GtkWindowGeometryInfo *info);
125 static GtkBinClass *parent_class = NULL;
126 static guint window_signals[LAST_SIGNAL] = { 0 };
130 gtk_window_get_type (void)
132 static GtkType window_type = 0;
136 static const GtkTypeInfo window_info =
140 sizeof (GtkWindowClass),
141 (GtkClassInitFunc) gtk_window_class_init,
142 (GtkObjectInitFunc) gtk_window_init,
143 /* reserved_1 */ NULL,
144 /* reserved_2 */ NULL,
145 (GtkClassInitFunc) NULL,
148 window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
155 gtk_window_class_init (GtkWindowClass *klass)
157 GtkObjectClass *object_class;
158 GtkWidgetClass *widget_class;
159 GtkContainerClass *container_class;
161 object_class = (GtkObjectClass*) klass;
162 widget_class = (GtkWidgetClass*) klass;
163 container_class = (GtkContainerClass*) klass;
165 parent_class = gtk_type_class (gtk_bin_get_type ());
167 gtk_object_add_arg_type ("GtkWindow::type", GTK_TYPE_WINDOW_TYPE, GTK_ARG_READWRITE, ARG_TYPE);
168 gtk_object_add_arg_type ("GtkWindow::title", GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_TITLE);
169 gtk_object_add_arg_type ("GtkWindow::auto_shrink", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_AUTO_SHRINK);
170 gtk_object_add_arg_type ("GtkWindow::allow_shrink", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ALLOW_SHRINK);
171 gtk_object_add_arg_type ("GtkWindow::allow_grow", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ALLOW_GROW);
172 gtk_object_add_arg_type ("GtkWindow::modal", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_MODAL);
173 gtk_object_add_arg_type ("GtkWindow::window_position", GTK_TYPE_WINDOW_POSITION, GTK_ARG_READWRITE, ARG_WIN_POS);
175 window_signals[SET_FOCUS] =
176 gtk_signal_new ("set_focus",
179 GTK_SIGNAL_OFFSET (GtkWindowClass, set_focus),
180 gtk_marshal_NONE__POINTER,
184 gtk_object_class_add_signals (object_class, window_signals, LAST_SIGNAL);
186 object_class->set_arg = gtk_window_set_arg;
187 object_class->get_arg = gtk_window_get_arg;
188 object_class->shutdown = gtk_window_shutdown;
189 object_class->destroy = gtk_window_destroy;
190 object_class->finalize = gtk_window_finalize;
192 widget_class->show = gtk_window_show;
193 widget_class->hide = gtk_window_hide;
194 widget_class->map = gtk_window_map;
195 widget_class->unmap = gtk_window_unmap;
196 widget_class->realize = gtk_window_realize;
197 widget_class->size_request = gtk_window_size_request;
198 widget_class->size_allocate = gtk_window_size_allocate;
199 widget_class->configure_event = gtk_window_configure_event;
200 widget_class->key_press_event = gtk_window_key_press_event;
201 widget_class->key_release_event = gtk_window_key_release_event;
202 widget_class->enter_notify_event = gtk_window_enter_notify_event;
203 widget_class->leave_notify_event = gtk_window_leave_notify_event;
204 widget_class->focus_in_event = gtk_window_focus_in_event;
205 widget_class->focus_out_event = gtk_window_focus_out_event;
206 widget_class->client_event = gtk_window_client_event;
208 widget_class->draw = gtk_window_draw;
209 widget_class->expose_event = gtk_window_expose;
211 container_class->check_resize = gtk_window_check_resize;
213 klass->set_focus = gtk_window_real_set_focus;
217 gtk_window_init (GtkWindow *window)
219 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
220 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
222 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
224 window->title = NULL;
225 window->wmclass_name = g_strdup (g_get_prgname ());
226 window->wmclass_class = g_strdup (gdk_progclass);
227 window->type = GTK_WINDOW_TOPLEVEL;
228 window->focus_widget = NULL;
229 window->default_widget = NULL;
230 window->resize_count = 0;
231 window->allow_shrink = FALSE;
232 window->allow_grow = TRUE;
233 window->auto_shrink = FALSE;
234 window->handling_resize = FALSE;
235 window->position = GTK_WIN_POS_NONE;
236 window->use_uposition = TRUE;
237 window->modal = FALSE;
239 gtk_container_register_toplevel (GTK_CONTAINER (window));
243 gtk_window_set_arg (GtkObject *object,
249 window = GTK_WINDOW (object);
254 window->type = GTK_VALUE_ENUM (*arg);
257 gtk_window_set_title (window, GTK_VALUE_STRING (*arg));
259 case ARG_AUTO_SHRINK:
260 window->auto_shrink = (GTK_VALUE_BOOL (*arg) != FALSE);
261 gtk_window_set_hints (GTK_WIDGET (window), >K_WIDGET (window)->requisition);
263 case ARG_ALLOW_SHRINK:
264 window->allow_shrink = (GTK_VALUE_BOOL (*arg) != FALSE);
265 gtk_window_set_hints (GTK_WIDGET (window), >K_WIDGET (window)->requisition);
268 window->allow_grow = (GTK_VALUE_BOOL (*arg) != FALSE);
269 gtk_window_set_hints (GTK_WIDGET (window), >K_WIDGET (window)->requisition);
272 gtk_window_set_modal (window, GTK_VALUE_BOOL (*arg));
275 gtk_window_set_position (window, GTK_VALUE_ENUM (*arg));
283 gtk_window_get_arg (GtkObject *object,
289 window = GTK_WINDOW (object);
294 GTK_VALUE_ENUM (*arg) = window->type;
297 GTK_VALUE_STRING (*arg) = g_strdup (window->title);
299 case ARG_AUTO_SHRINK:
300 GTK_VALUE_BOOL (*arg) = window->auto_shrink;
302 case ARG_ALLOW_SHRINK:
303 GTK_VALUE_BOOL (*arg) = window->allow_shrink;
306 GTK_VALUE_BOOL (*arg) = window->allow_grow;
309 GTK_VALUE_BOOL (*arg) = window->modal;
312 GTK_VALUE_ENUM (*arg) = window->position;
315 arg->type = GTK_TYPE_INVALID;
321 gtk_window_new (GtkWindowType type)
325 window = gtk_type_new (gtk_window_get_type ());
329 return GTK_WIDGET (window);
333 gtk_window_set_title (GtkWindow *window,
336 g_return_if_fail (window != NULL);
337 g_return_if_fail (GTK_IS_WINDOW (window));
340 g_free (window->title);
341 window->title = g_strdup (title);
343 if (GTK_WIDGET_REALIZED (window))
344 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
348 gtk_window_set_wmclass (GtkWindow *window,
349 const gchar *wmclass_name,
350 const gchar *wmclass_class)
352 g_return_if_fail (window != NULL);
353 g_return_if_fail (GTK_IS_WINDOW (window));
355 g_free (window->wmclass_name);
356 window->wmclass_name = g_strdup (wmclass_name);
358 g_free (window->wmclass_class);
359 window->wmclass_class = g_strdup (wmclass_class);
361 if (GTK_WIDGET_REALIZED (window))
362 g_warning ("shouldn't set wmclass after window is realized!\n");
366 gtk_window_set_focus (GtkWindow *window,
369 g_return_if_fail (window != NULL);
370 g_return_if_fail (GTK_IS_WINDOW (window));
373 g_return_if_fail (GTK_IS_WIDGET (focus));
374 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
377 if ((window->focus_widget != focus) ||
378 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
379 gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
383 gtk_window_set_default (GtkWindow *window,
384 GtkWidget *default_widget)
386 g_return_if_fail (window != NULL);
387 g_return_if_fail (GTK_IS_WINDOW (window));
390 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
392 if (window->default_widget != default_widget)
394 if (window->default_widget)
396 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
397 gtk_widget_draw_default (window->default_widget);
400 window->default_widget = default_widget;
402 if (window->default_widget)
404 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
405 gtk_widget_draw_default (window->default_widget);
411 gtk_window_set_policy (GtkWindow *window,
416 g_return_if_fail (window != NULL);
417 g_return_if_fail (GTK_IS_WINDOW (window));
419 window->allow_shrink = (allow_shrink != FALSE);
420 window->allow_grow = (allow_grow != FALSE);
421 window->auto_shrink = (auto_shrink != FALSE);
423 gtk_window_set_hints (GTK_WIDGET (window), >K_WIDGET (window)->requisition);
427 gtk_window_add_accel_group (GtkWindow *window,
428 GtkAccelGroup *accel_group)
430 g_return_if_fail (window != NULL);
431 g_return_if_fail (GTK_IS_WINDOW (window));
432 g_return_if_fail (accel_group != NULL);
434 gtk_accel_group_attach (accel_group, GTK_OBJECT (window));
438 gtk_window_remove_accel_group (GtkWindow *window,
439 GtkAccelGroup *accel_group)
441 g_return_if_fail (window != NULL);
442 g_return_if_fail (GTK_IS_WINDOW (window));
443 g_return_if_fail (accel_group != NULL);
445 gtk_accel_group_detach (accel_group, GTK_OBJECT (window));
449 gtk_window_set_position (GtkWindow *window,
450 GtkWindowPosition position)
452 g_return_if_fail (window != NULL);
453 g_return_if_fail (GTK_IS_WINDOW (window));
455 window->position = position;
459 gtk_window_activate_focus (GtkWindow *window)
461 g_return_val_if_fail (window != NULL, FALSE);
462 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
464 if (window->focus_widget)
466 gtk_widget_activate (window->focus_widget);
474 gtk_window_activate_default (GtkWindow *window)
476 g_return_val_if_fail (window != NULL, FALSE);
477 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
479 if (window->default_widget)
481 gtk_widget_activate (window->default_widget);
489 gtk_window_set_modal (GtkWindow *window,
492 g_return_if_fail (window != NULL);
493 g_return_if_fail (GTK_IS_WINDOW (window));
495 window->modal = modal != FALSE;
497 /* adjust desired modality state */
498 if (GTK_WIDGET_VISIBLE (window) && window->modal)
499 gtk_grab_add (GTK_WIDGET (window));
501 gtk_grab_remove (GTK_WIDGET (window));
505 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
507 GList *embedded_windows;
509 g_return_if_fail (window != NULL);
510 g_return_if_fail (GTK_IS_WINDOW (window));
512 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
513 if (embedded_windows)
514 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
515 g_quark_from_static_string ("gtk-embedded"));
516 embedded_windows = g_list_prepend (embedded_windows,
517 GUINT_TO_POINTER (xid));
519 gtk_object_set_data_full (GTK_OBJECT (window), "gtk-embedded",
522 (GtkDestroyNotify) g_list_free : NULL);
526 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
528 GList *embedded_windows;
531 g_return_if_fail (window != NULL);
532 g_return_if_fail (GTK_IS_WINDOW (window));
534 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
535 if (embedded_windows)
536 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
537 g_quark_from_static_string ("gtk-embedded"));
539 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
542 embedded_windows = g_list_remove_link (embedded_windows, node);
543 g_list_free_1 (node);
546 gtk_object_set_data_full (GTK_OBJECT (window),
547 "gtk-embedded", embedded_windows,
549 (GtkDestroyNotify) g_list_free : NULL);
553 gtk_window_shutdown (GtkObject *object)
557 g_return_if_fail (object != NULL);
558 g_return_if_fail (GTK_IS_WINDOW (object));
560 window = GTK_WINDOW (object);
562 gtk_window_set_focus (window, NULL);
563 gtk_window_set_default (window, NULL);
565 GTK_OBJECT_CLASS (parent_class)->shutdown (object);
569 gtk_window_transient_parent_realized (GtkWidget *parent,
572 if (GTK_WIDGET_REALIZED (window))
573 gdk_window_set_transient_for (window->window, parent->window);
577 gtk_window_transient_parent_unrealized (GtkWidget *parent,
580 if (GTK_WIDGET_REALIZED (window))
581 gdk_property_delete (window->window,
582 gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
586 gtk_window_unset_transient_for (GtkWindow *window)
588 if (window->transient_parent)
590 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
591 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
593 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
594 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
596 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
597 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
598 &window->transient_parent);
600 window->transient_parent = NULL;
605 gtk_window_set_transient_for (GtkWindow *window,
608 g_return_if_fail (window != 0);
610 if (window->transient_parent)
612 gtk_window_unset_transient_for (window);
614 if (GTK_WIDGET_REALIZED (window) &&
615 GTK_WIDGET_REALIZED (window->transient_parent) &&
616 (!parent || !GTK_WIDGET_REALIZED (parent)))
617 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
618 GTK_WIDGET (window));
621 window->transient_parent = parent;
625 gtk_signal_connect (GTK_OBJECT (parent), "destroy",
626 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
627 &window->transient_parent);
628 gtk_signal_connect (GTK_OBJECT (parent), "realize",
629 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
631 gtk_signal_connect (GTK_OBJECT (parent), "unrealize",
632 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
635 if (GTK_WIDGET_REALIZED (window) &&
636 GTK_WIDGET_REALIZED (parent))
637 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
638 GTK_WIDGET (window));
643 gtk_window_geometry_destroy (GtkWindowGeometryInfo *info)
646 gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
647 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
652 static GtkWindowGeometryInfo *
653 gtk_window_get_geometry_info (GtkWindow *window, gboolean create)
655 GtkWindowGeometryInfo *info;
657 info = gtk_object_get_data (GTK_OBJECT (window), "gtk-window-geometry");
661 info = g_new (GtkWindowGeometryInfo, 1);
665 info->last_width = -1;
666 info->last_height = -1;
670 gtk_object_set_data_full (GTK_OBJECT (window),
672 "gtk-window-geometry",
674 (GtkDestroyNotify) gtk_window_geometry_destroy);
681 gtk_window_set_geometry_hints (GtkWindow *window,
682 GtkWidget *geometry_widget,
683 GdkGeometry *geometry,
684 GdkWindowHints geom_mask)
686 GtkWindowGeometryInfo *info;
688 g_return_if_fail (window != NULL);
690 info = gtk_window_get_geometry_info (window, TRUE);
693 gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
694 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
697 info->widget = geometry_widget;
699 gtk_signal_connect (GTK_OBJECT (geometry_widget), "destroy",
700 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
704 info->geometry = *geometry;
706 info->mask = geom_mask;
710 gtk_window_set_default_size (GtkWindow *window,
714 GtkWindowGeometryInfo *info;
716 g_return_if_fail (window != NULL);
718 info = gtk_window_get_geometry_info (window, TRUE);
721 info->height = height;
725 gtk_window_destroy (GtkObject *object)
729 g_return_if_fail (object != NULL);
730 g_return_if_fail (GTK_IS_WINDOW (object));
732 window = GTK_WINDOW (object);
734 gtk_container_unregister_toplevel (GTK_CONTAINER (object));
736 if (window->transient_parent)
737 gtk_window_unset_transient_for (window);
739 GTK_OBJECT_CLASS (parent_class)->destroy (object);
743 gtk_window_finalize (GtkObject *object)
747 g_return_if_fail (object != NULL);
748 g_return_if_fail (GTK_IS_WINDOW (object));
750 window = GTK_WINDOW (object);
751 g_free (window->title);
752 g_free (window->wmclass_name);
753 g_free (window->wmclass_class);
755 GTK_OBJECT_CLASS(parent_class)->finalize (object);
759 gtk_window_show (GtkWidget *widget)
761 g_return_if_fail (widget != NULL);
762 g_return_if_fail (GTK_IS_WINDOW (widget));
764 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
765 gtk_container_check_resize (GTK_CONTAINER (widget));
766 gtk_widget_map (widget);
768 if (GTK_WINDOW (widget)->modal)
769 gtk_grab_add (widget);
773 gtk_window_hide (GtkWidget *widget)
777 g_return_if_fail (widget != NULL);
778 g_return_if_fail (GTK_IS_WINDOW (widget));
780 window = GTK_WINDOW (widget);
782 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
783 gtk_widget_unmap (widget);
786 gtk_grab_remove (widget);
790 gtk_window_map (GtkWidget *widget)
794 g_return_if_fail (widget != NULL);
795 g_return_if_fail (GTK_IS_WINDOW (widget));
797 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
799 window = GTK_WINDOW (widget);
801 if (window->bin.child &&
802 GTK_WIDGET_VISIBLE (window->bin.child) &&
803 !GTK_WIDGET_MAPPED (window->bin.child))
804 gtk_widget_map (window->bin.child);
806 gtk_window_set_hints (widget, &widget->requisition);
807 gdk_window_show (widget->window);
811 gtk_window_unmap (GtkWidget *widget)
815 g_return_if_fail (widget != NULL);
816 g_return_if_fail (GTK_IS_WINDOW (widget));
818 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
819 gdk_window_hide (widget->window);
821 window = GTK_WINDOW (widget);
822 window->use_uposition = TRUE;
826 gtk_window_realize (GtkWidget *widget)
829 GdkWindowAttr attributes;
830 gint attributes_mask;
832 g_return_if_fail (widget != NULL);
833 g_return_if_fail (GTK_IS_WINDOW (widget));
835 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
836 window = GTK_WINDOW (widget);
838 switch (window->type)
840 case GTK_WINDOW_TOPLEVEL:
841 attributes.window_type = GDK_WINDOW_TOPLEVEL;
843 case GTK_WINDOW_DIALOG:
844 attributes.window_type = GDK_WINDOW_DIALOG;
846 case GTK_WINDOW_POPUP:
847 attributes.window_type = GDK_WINDOW_TEMP;
851 attributes.title = window->title;
852 attributes.wmclass_name = window->wmclass_name;
853 attributes.wmclass_class = window->wmclass_class;
854 attributes.width = widget->allocation.width;
855 attributes.height = widget->allocation.height;
856 attributes.wclass = GDK_INPUT_OUTPUT;
857 attributes.visual = gtk_widget_get_visual (widget);
858 attributes.colormap = gtk_widget_get_colormap (widget);
859 attributes.event_mask = gtk_widget_get_events (widget);
860 attributes.event_mask |= (GDK_EXPOSURE_MASK |
862 GDK_ENTER_NOTIFY_MASK |
863 GDK_LEAVE_NOTIFY_MASK |
864 GDK_FOCUS_CHANGE_MASK |
867 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
868 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
869 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
871 widget->window = gdk_window_new (NULL, &attributes, attributes_mask);
872 gdk_window_set_user_data (widget->window, window);
874 widget->style = gtk_style_attach (widget->style, widget->window);
875 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
876 gtk_window_paint (widget, NULL);
878 if (window->transient_parent &&
879 GTK_WIDGET_REALIZED (window->transient_parent))
880 gdk_window_set_transient_for (widget->window,
881 GTK_WIDGET (window->transient_parent)->window);
885 gtk_window_size_request (GtkWidget *widget,
886 GtkRequisition *requisition)
891 g_return_if_fail (widget != NULL);
892 g_return_if_fail (GTK_IS_WINDOW (widget));
893 g_return_if_fail (requisition != NULL);
895 window = GTK_WINDOW (widget);
896 bin = GTK_BIN (window);
898 requisition->width = GTK_CONTAINER (window)->border_width * 2;
899 requisition->height = GTK_CONTAINER (window)->border_width * 2;
901 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
903 GtkRequisition child_requisition;
905 gtk_widget_size_request (bin->child, &child_requisition);
907 requisition->width += child_requisition.width;
908 requisition->height += child_requisition.height;
912 if (!GTK_WIDGET_VISIBLE (window))
913 GTK_CONTAINER (window)->need_resize = TRUE;
918 gtk_window_size_allocate (GtkWidget *widget,
919 GtkAllocation *allocation)
922 GtkAllocation child_allocation;
924 g_return_if_fail (widget != NULL);
925 g_return_if_fail (GTK_IS_WINDOW (widget));
926 g_return_if_fail (allocation != NULL);
928 window = GTK_WINDOW (widget);
929 widget->allocation = *allocation;
931 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
933 child_allocation.x = GTK_CONTAINER (window)->border_width;
934 child_allocation.y = GTK_CONTAINER (window)->border_width;
935 child_allocation.width = allocation->width - child_allocation.x * 2;
936 child_allocation.height = allocation->height - child_allocation.y * 2;
938 gtk_widget_size_allocate (window->bin.child, &child_allocation);
943 gtk_window_configure_event (GtkWidget *widget,
944 GdkEventConfigure *event)
947 GtkAllocation allocation;
948 gboolean need_expose = FALSE;
950 g_return_val_if_fail (widget != NULL, FALSE);
951 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
952 g_return_val_if_fail (event != NULL, FALSE);
954 window = GTK_WINDOW (widget);
956 /* If the window was merely moved, do nothing */
957 if ((widget->allocation.width == event->width) &&
958 (widget->allocation.height == event->height))
960 if (window->resize_count == 0) /* The window was merely moved */
964 /* We asked for a new size, which was rejected, so the
965 * WM sent us a synthetic configure event. We won't
966 * get the expose event we would normally get (since
967 * we have ForgetGravity), so we need to fake it.
974 window->handling_resize = TRUE;
978 allocation.width = event->width;
979 allocation.height = event->height;
981 gtk_widget_size_allocate (widget, &allocation);
983 if (window->bin.child &&
984 GTK_WIDGET_VISIBLE (window->bin.child) &&
985 !GTK_WIDGET_MAPPED (window->bin.child))
986 gtk_widget_map (window->bin.child);
988 if (window->resize_count > 0)
989 window->resize_count -= 1;
994 temp_event.type = GDK_EXPOSE;
995 temp_event.expose.window = widget->window;
996 temp_event.expose.send_event = TRUE;
997 temp_event.expose.area.x = 0;
998 temp_event.expose.area.y = 0;
999 temp_event.expose.area.width = event->width;
1000 temp_event.expose.area.height = event->height;
1001 temp_event.expose.count = 0;
1003 gtk_widget_event (widget, &temp_event);
1006 window->handling_resize = FALSE;
1012 gtk_window_key_press_event (GtkWidget *widget,
1016 GtkDirectionType direction = 0;
1019 g_return_val_if_fail (widget != NULL, FALSE);
1020 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1021 g_return_val_if_fail (event != NULL, FALSE);
1023 window = GTK_WINDOW (widget);
1027 if (window->focus_widget && GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1029 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
1033 handled = gtk_accel_groups_activate (GTK_OBJECT (window), event->keyval, event->state);
1037 switch (event->keyval)
1040 if (window->focus_widget)
1042 gtk_widget_activate (window->focus_widget);
1048 if (window->default_widget &&
1049 (!window->focus_widget ||
1050 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1052 gtk_widget_activate (window->default_widget);
1055 else if (window->focus_widget)
1057 gtk_widget_activate (window->focus_widget);
1066 case GDK_ISO_Left_Tab:
1067 switch (event->keyval)
1070 direction = GTK_DIR_UP;
1073 direction = GTK_DIR_DOWN;
1076 direction = GTK_DIR_LEFT;
1079 direction = GTK_DIR_RIGHT;
1082 case GDK_ISO_Left_Tab:
1083 if (event->state & GDK_SHIFT_MASK)
1084 direction = GTK_DIR_TAB_BACKWARD;
1086 direction = GTK_DIR_TAB_FORWARD;
1089 direction = GTK_DIR_UP; /* never reached, but makes compiler happy */
1092 gtk_container_focus (GTK_CONTAINER (widget), direction);
1094 if (!GTK_CONTAINER (window)->focus_child)
1095 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
1102 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
1103 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
1109 gtk_window_key_release_event (GtkWidget *widget,
1115 g_return_val_if_fail (widget != NULL, FALSE);
1116 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1117 g_return_val_if_fail (event != NULL, FALSE);
1119 window = GTK_WINDOW (widget);
1121 if (window->focus_widget && GTK_WIDGET_SENSITIVE (window->focus_widget))
1123 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
1126 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
1127 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
1133 gtk_window_enter_notify_event (GtkWidget *widget,
1134 GdkEventCrossing *event)
1136 g_return_val_if_fail (widget != NULL, FALSE);
1137 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1138 g_return_val_if_fail (event != NULL, FALSE);
1144 gtk_window_leave_notify_event (GtkWidget *widget,
1145 GdkEventCrossing *event)
1147 g_return_val_if_fail (widget != NULL, FALSE);
1148 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1149 g_return_val_if_fail (event != NULL, FALSE);
1155 gtk_window_focus_in_event (GtkWidget *widget,
1156 GdkEventFocus *event)
1159 GdkEventFocus fevent;
1161 g_return_val_if_fail (widget != NULL, FALSE);
1162 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1163 g_return_val_if_fail (event != NULL, FALSE);
1165 /* It appears spurious focus in events can occur when
1166 * the window is hidden. So we'll just check to see if
1167 * the window is visible before actually handling the
1170 if (GTK_WIDGET_VISIBLE (widget))
1172 window = GTK_WINDOW (widget);
1173 if (window->focus_widget && !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
1175 fevent.type = GDK_FOCUS_CHANGE;
1176 fevent.window = window->focus_widget->window;
1179 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
1187 gtk_window_focus_out_event (GtkWidget *widget,
1188 GdkEventFocus *event)
1191 GdkEventFocus fevent;
1193 g_return_val_if_fail (widget != NULL, FALSE);
1194 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1195 g_return_val_if_fail (event != NULL, FALSE);
1197 window = GTK_WINDOW (widget);
1198 if (window->focus_widget && GTK_WIDGET_HAS_FOCUS (window->focus_widget))
1200 fevent.type = GDK_FOCUS_CHANGE;
1201 fevent.window = window->focus_widget->window;
1204 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
1210 static GdkAtom atom_rcfiles = GDK_NONE;
1213 gtk_window_read_rcfiles (GtkWidget *widget,
1214 GdkEventClient *event)
1216 GList *embedded_windows;
1218 embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
1219 if (embedded_windows)
1224 for(i = 0; i < 5; i++)
1226 sev.data_format = 32;
1227 sev.message_type = atom_rcfiles;
1229 while (embedded_windows)
1231 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
1232 gdk_event_send_client_message ((GdkEvent *) &sev, xid);
1233 embedded_windows = embedded_windows->next;
1237 if (gtk_rc_reparse_all ())
1239 /* If the above returned true, some of our RC files are out
1240 * of date, so we need to reset all our widgets. Our other
1241 * toplevel windows will also get the message, but by
1242 * then, the RC file will up to date, so we have to tell
1247 toplevels = gtk_container_get_toplevels();
1250 gtk_widget_reset_rc_styles (toplevels->data);
1251 toplevels = toplevels->next;
1257 gtk_window_client_event (GtkWidget *widget,
1258 GdkEventClient *event)
1260 g_return_val_if_fail (widget != NULL, FALSE);
1261 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1262 g_return_val_if_fail (event != NULL, FALSE);
1265 atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
1267 if(event->message_type == atom_rcfiles)
1268 gtk_window_read_rcfiles (widget, event);
1274 gtk_window_check_resize (GtkContainer *container)
1278 g_return_if_fail (container != NULL);
1279 g_return_if_fail (GTK_IS_WINDOW (container));
1281 window = GTK_WINDOW (container);
1282 if (!window->handling_resize)
1284 if (GTK_WIDGET_VISIBLE (container))
1285 gtk_window_move_resize (window);
1287 GTK_CONTAINER (window)->need_resize = TRUE;
1291 /* FIXME: we leave container->resize_widgets set under some
1294 gtk_window_move_resize (GtkWindow *window)
1297 GtkWindowGeometryInfo *info;
1298 GtkRequisition requisition;
1299 GtkContainer *container;
1302 gint new_width, new_height;
1303 gint min_width, min_height;
1306 gboolean needed_resize;
1307 gboolean size_changed;
1309 g_return_if_fail (window != NULL);
1310 g_return_if_fail (GTK_IS_WINDOW (window));
1312 widget = GTK_WIDGET (window);
1313 container = GTK_CONTAINER (widget);
1315 info = gtk_window_get_geometry_info (window, FALSE);
1317 /* Remember old size, to know if we have to reset hints */
1318 if (info && (info->last_width > 0))
1319 width = info->last_width;
1321 width = widget->requisition.width;
1323 if (info && (info->last_height > 0))
1324 height = info->last_height;
1326 height = widget->requisition.height;
1328 size_changed = FALSE;
1330 gtk_widget_size_request (widget, &requisition);
1332 size_changed |= requisition.width != widget->requisition.width;
1333 size_changed |= requisition.height != widget->requisition.height;
1334 widget->requisition = requisition;
1336 /* Figure out the new desired size */
1338 if (info && info->width > 0)
1340 size_changed |= width != info->last_width;
1341 info->last_width = width;
1342 new_width = info->width;
1346 size_changed |= width != widget->requisition.width;
1347 new_width = widget->requisition.width;
1350 if (info && info->height > 0)
1352 size_changed |= height != info->last_height;
1353 info->last_height = height;
1354 new_height = info->height;
1358 size_changed |= height != widget->requisition.height;
1359 new_height = widget->requisition.height;
1362 /* Figure out the new minimum size */
1364 if (info && (info->mask & (GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE)))
1366 if (info->mask && GDK_HINT_MIN_SIZE)
1368 min_width = info->geometry.min_width;
1369 min_height = info->geometry.min_height;
1373 min_width = info->geometry.base_width;
1374 min_height = info->geometry.base_height;
1379 min_width += widget->requisition.width - info->widget->requisition.width;
1380 min_height += widget->requisition.height - info->widget->requisition.height;
1385 min_width = widget->requisition.width;
1386 min_height = widget->requisition.height;
1391 gboolean saved_use_upos;
1393 saved_use_upos = window->use_uposition;
1394 gtk_window_set_hints (widget, &widget->requisition);
1395 window->use_uposition = saved_use_upos;
1401 if (window->use_uposition)
1402 switch (window->position)
1404 case GTK_WIN_POS_CENTER:
1405 x = (gdk_screen_width () - new_width) / 2;
1406 y = (gdk_screen_height () - new_height) / 2;
1407 gtk_widget_set_uposition (widget, x, y);
1409 case GTK_WIN_POS_MOUSE:
1410 gdk_window_get_pointer (NULL, &x, &y, NULL);
1413 y -= new_height / 2;
1415 screen_width = gdk_screen_width ();
1416 screen_height = gdk_screen_height ();
1420 else if (x > (screen_width - new_width))
1421 x = screen_width - new_width;
1425 else if (y > (screen_height - new_height))
1426 y = screen_height - new_height;
1428 gtk_widget_set_uposition (widget, x, y);
1432 /* Now, do the resizing */
1434 needed_resize = container->need_resize;
1435 container->need_resize = FALSE;
1437 if ((new_width == 0) || (new_height == 0))
1443 if (!GTK_WIDGET_REALIZED (window))
1445 GtkAllocation allocation;
1449 allocation.width = new_width;
1450 allocation.height = new_height;
1452 gtk_widget_size_allocate (widget, &allocation);
1457 gdk_window_get_geometry (widget->window, NULL, NULL, &width, &height, NULL);
1459 /* As an optimization, we don't try to get a new size from the
1460 * window manager if we asked for the same size last time and
1464 (((window->auto_shrink &&
1465 ((width != new_width) ||
1466 (height != new_height)))) ||
1467 ((width < min_width) ||
1468 (height < min_height))))
1470 window->resize_count += 1;
1472 if (!window->auto_shrink)
1474 new_width = MAX(width, min_width);
1475 new_height = MAX(height, min_height);
1478 if ((x != -1) && (y != -1))
1479 gdk_window_move_resize (widget->window, x, y,
1483 gdk_window_resize (widget->window,
1487 else if (needed_resize)
1489 /* The windows contents changed size while it was not
1490 * visible, so reallocate everything, since we didn't
1491 * keep track of what changed
1493 GtkAllocation allocation;
1497 allocation.width = new_width;
1498 allocation.height = new_height;
1500 gtk_widget_size_allocate (widget, &allocation);
1501 gdk_window_resize (widget->window,
1507 if ((x != -1) && (y != -1))
1508 gdk_window_move (widget->window, x, y);
1510 gtk_container_resize_children (GTK_CONTAINER (window));
1515 gtk_window_real_set_focus (GtkWindow *window,
1518 GdkEventFocus event;
1519 gboolean def_flags = 0;
1521 g_return_if_fail (window != NULL);
1522 g_return_if_fail (GTK_IS_WINDOW (window));
1524 if (window->default_widget)
1525 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
1527 if (window->focus_widget)
1529 event.type = GDK_FOCUS_CHANGE;
1530 event.window = window->focus_widget->window;
1533 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
1534 (window->focus_widget != window->default_widget))
1536 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
1537 /* if any widget had the default set there should be
1538 a default_widget, but might not so this is a sanity
1540 if (window->default_widget)
1541 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1544 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
1547 window->focus_widget = focus;
1549 if (window->focus_widget)
1551 event.type = GDK_FOCUS_CHANGE;
1552 event.window = window->focus_widget->window;
1555 if (window->default_widget)
1557 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
1558 (window->focus_widget != window->default_widget))
1560 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
1561 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
1562 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1566 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1570 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
1572 else if (window->default_widget)
1574 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1577 if (window->default_widget &&
1578 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
1579 gtk_widget_queue_draw (window->default_widget);
1583 gtk_window_set_hints (GtkWidget *widget,
1584 GtkRequisition *requisition)
1587 GtkWidgetAuxInfo *aux_info;
1588 GtkWindowGeometryInfo *geometry_info;
1589 GdkGeometry new_geometry;
1592 gint extra_width = 0;
1593 gint extra_height = 0;
1595 g_return_if_fail (widget != NULL);
1596 g_return_if_fail (GTK_IS_WINDOW (widget));
1597 g_return_if_fail (requisition != NULL);
1599 if (GTK_WIDGET_REALIZED (widget))
1601 window = GTK_WINDOW (widget);
1603 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
1607 flags = geometry_info->mask;
1608 new_geometry = geometry_info->geometry;
1610 if (geometry_info->widget)
1612 extra_width = requisition->width - geometry_info->widget->requisition.width;
1613 extra_height = requisition->height - geometry_info->widget->requisition.height;
1622 aux_info = gtk_object_get_data (GTK_OBJECT (widget), "gtk-aux-info");
1623 if (aux_info && (aux_info->x != -1) && (aux_info->y != -1))
1627 flags |= GDK_HINT_POS;
1630 if (flags & GDK_HINT_BASE_SIZE)
1632 new_geometry.base_width += extra_width;
1633 new_geometry.base_height += extra_height;
1635 else if (!(flags & GDK_HINT_MIN_SIZE) &&
1636 (flags & GDK_HINT_RESIZE_INC) &&
1637 ((extra_width != 0) || (extra_height != 0)))
1639 flags |= GDK_HINT_BASE_SIZE;
1641 new_geometry.base_width = extra_width;
1642 new_geometry.base_height = extra_height;
1645 if (flags & GDK_HINT_MIN_SIZE)
1647 new_geometry.min_width += extra_width;
1648 new_geometry.min_height += extra_height;
1650 else if (!window->allow_shrink)
1652 flags |= GDK_HINT_MIN_SIZE;
1654 new_geometry.min_width = requisition->width;
1655 new_geometry.min_height = requisition->height;
1658 if (flags & GDK_HINT_MAX_SIZE)
1660 new_geometry.max_width += extra_width;
1661 new_geometry.max_height += extra_height;
1663 else if (!window->allow_grow)
1665 flags |= GDK_HINT_MAX_SIZE;
1667 new_geometry.max_width = requisition->width;
1668 new_geometry.max_height = requisition->height;
1671 gdk_window_set_geometry_hints (widget->window, &new_geometry, flags);
1673 if (window->use_uposition && (flags & GDK_HINT_POS))
1675 window->use_uposition = FALSE;
1676 gdk_window_move (widget->window, ux, uy);
1682 gtk_window_paint (GtkWidget *widget,
1685 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
1686 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
1690 gtk_window_expose (GtkWidget *widget,
1691 GdkEventExpose *event)
1693 g_return_val_if_fail (widget != NULL, FALSE);
1694 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1695 g_return_val_if_fail (event != NULL, FALSE);
1697 if (!GTK_WIDGET_APP_PAINTABLE (widget))
1698 gtk_window_paint (widget, &event->area);
1700 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
1701 return (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
1707 gtk_window_draw (GtkWidget *widget,
1710 if (!GTK_WIDGET_APP_PAINTABLE (widget))
1711 gtk_window_paint (widget, area);
1713 if (GTK_WIDGET_CLASS (parent_class)->draw)
1714 (* GTK_WIDGET_CLASS (parent_class)->draw) (widget, area);