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.
22 #include "gdk/gdkkeysyms.h"
24 #include "gtkprivate.h"
26 #include "gtksignal.h"
27 #include "gtkwindow.h"
28 #include "gtkbindings.h"
53 } GtkWindowGeometryInfo;
55 static void gtk_window_class_init (GtkWindowClass *klass);
56 static void gtk_window_init (GtkWindow *window);
57 static void gtk_window_set_arg (GtkObject *object,
60 static void gtk_window_get_arg (GtkObject *object,
63 static void gtk_window_shutdown (GtkObject *object);
64 static void gtk_window_destroy (GtkObject *object);
65 static void gtk_window_finalize (GtkObject *object);
66 static void gtk_window_show (GtkWidget *widget);
67 static void gtk_window_hide (GtkWidget *widget);
68 static void gtk_window_map (GtkWidget *widget);
69 static void gtk_window_unmap (GtkWidget *widget);
70 static void gtk_window_realize (GtkWidget *widget);
71 static void gtk_window_size_request (GtkWidget *widget,
72 GtkRequisition *requisition);
73 static void gtk_window_size_allocate (GtkWidget *widget,
74 GtkAllocation *allocation);
75 static gint gtk_window_configure_event (GtkWidget *widget,
76 GdkEventConfigure *event);
77 static gint gtk_window_key_press_event (GtkWidget *widget,
79 static gint gtk_window_key_release_event (GtkWidget *widget,
81 static gint gtk_window_enter_notify_event (GtkWidget *widget,
82 GdkEventCrossing *event);
83 static gint gtk_window_leave_notify_event (GtkWidget *widget,
84 GdkEventCrossing *event);
85 static gint gtk_window_focus_in_event (GtkWidget *widget,
86 GdkEventFocus *event);
87 static gint gtk_window_focus_out_event (GtkWidget *widget,
88 GdkEventFocus *event);
89 static gint gtk_window_client_event (GtkWidget *widget,
90 GdkEventClient *event);
91 static void gtk_window_check_resize (GtkContainer *container);
92 static void gtk_window_real_set_focus (GtkWindow *window,
94 static void gtk_window_move_resize (GtkWindow *window);
95 static void gtk_window_set_hints (GtkWidget *widget,
96 GtkRequisition *requisition);
98 static void gtk_window_read_rcfiles (GtkWidget *widget,
99 GdkEventClient *event);
100 static void gtk_window_draw (GtkWidget *widget,
102 static void gtk_window_paint (GtkWidget *widget,
104 static gint gtk_window_expose (GtkWidget *widget,
105 GdkEventExpose *event);
106 static void gtk_window_style_set (GtkWidget *widget,
107 GtkStyle *previous_style);
108 static void gtk_window_unset_transient_for (GtkWindow *window);
109 static void gtk_window_transient_parent_realized (GtkWidget *parent,
111 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
114 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
116 static void gtk_window_geometry_destroy (GtkWindowGeometryInfo *info);
118 static GtkBinClass *parent_class = NULL;
119 static guint window_signals[LAST_SIGNAL] = { 0 };
123 gtk_window_get_type (void)
125 static GtkType window_type = 0;
129 static const GtkTypeInfo window_info =
133 sizeof (GtkWindowClass),
134 (GtkClassInitFunc) gtk_window_class_init,
135 (GtkObjectInitFunc) gtk_window_init,
136 /* reserved_1 */ NULL,
137 /* reserved_2 */ NULL,
138 (GtkClassInitFunc) NULL,
141 window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
148 gtk_window_class_init (GtkWindowClass *klass)
150 GtkObjectClass *object_class;
151 GtkWidgetClass *widget_class;
152 GtkContainerClass *container_class;
154 object_class = (GtkObjectClass*) klass;
155 widget_class = (GtkWidgetClass*) klass;
156 container_class = (GtkContainerClass*) klass;
158 parent_class = gtk_type_class (gtk_bin_get_type ());
160 gtk_object_add_arg_type ("GtkWindow::type", GTK_TYPE_WINDOW_TYPE, GTK_ARG_READWRITE, ARG_TYPE);
161 gtk_object_add_arg_type ("GtkWindow::title", GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_TITLE);
162 gtk_object_add_arg_type ("GtkWindow::auto_shrink", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_AUTO_SHRINK);
163 gtk_object_add_arg_type ("GtkWindow::allow_shrink", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ALLOW_SHRINK);
164 gtk_object_add_arg_type ("GtkWindow::allow_grow", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ALLOW_GROW);
165 gtk_object_add_arg_type ("GtkWindow::window_position", GTK_TYPE_WINDOW_POSITION, GTK_ARG_READWRITE, ARG_WIN_POS);
167 window_signals[SET_FOCUS] =
168 gtk_signal_new ("set_focus",
171 GTK_SIGNAL_OFFSET (GtkWindowClass, set_focus),
172 gtk_marshal_NONE__POINTER,
176 gtk_object_class_add_signals (object_class, window_signals, LAST_SIGNAL);
178 object_class->set_arg = gtk_window_set_arg;
179 object_class->get_arg = gtk_window_get_arg;
180 object_class->shutdown = gtk_window_shutdown;
181 object_class->destroy = gtk_window_destroy;
182 object_class->finalize = gtk_window_finalize;
184 widget_class->show = gtk_window_show;
185 widget_class->hide = gtk_window_hide;
186 widget_class->map = gtk_window_map;
187 widget_class->unmap = gtk_window_unmap;
188 widget_class->realize = gtk_window_realize;
189 widget_class->size_request = gtk_window_size_request;
190 widget_class->size_allocate = gtk_window_size_allocate;
191 widget_class->configure_event = gtk_window_configure_event;
192 widget_class->key_press_event = gtk_window_key_press_event;
193 widget_class->key_release_event = gtk_window_key_release_event;
194 widget_class->enter_notify_event = gtk_window_enter_notify_event;
195 widget_class->leave_notify_event = gtk_window_leave_notify_event;
196 widget_class->focus_in_event = gtk_window_focus_in_event;
197 widget_class->focus_out_event = gtk_window_focus_out_event;
198 widget_class->client_event = gtk_window_client_event;
199 widget_class->style_set = gtk_window_style_set;
201 widget_class->draw = gtk_window_draw;
202 widget_class->expose_event = gtk_window_expose;
204 container_class->check_resize = gtk_window_check_resize;
206 klass->set_focus = gtk_window_real_set_focus;
210 gtk_window_init (GtkWindow *window)
212 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
213 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
215 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
217 window->title = NULL;
218 window->wmclass_name = g_strdup (g_get_prgname ());
219 window->wmclass_class = g_strdup (gdk_progclass);
220 window->type = GTK_WINDOW_TOPLEVEL;
221 window->focus_widget = NULL;
222 window->default_widget = NULL;
223 window->resize_count = 0;
224 window->allow_shrink = FALSE;
225 window->allow_grow = TRUE;
226 window->auto_shrink = FALSE;
227 window->handling_resize = FALSE;
228 window->position = GTK_WIN_POS_NONE;
229 window->use_uposition = TRUE;
230 window->modal = FALSE;
232 gtk_container_register_toplevel (GTK_CONTAINER (window));
236 gtk_window_set_arg (GtkObject *object,
242 window = GTK_WINDOW (object);
247 window->type = GTK_VALUE_ENUM (*arg);
250 gtk_window_set_title (window, GTK_VALUE_STRING (*arg));
252 case ARG_AUTO_SHRINK:
253 window->auto_shrink = (GTK_VALUE_BOOL (*arg) != FALSE);
254 gtk_window_set_hints (GTK_WIDGET (window), >K_WIDGET (window)->requisition);
256 case ARG_ALLOW_SHRINK:
257 window->allow_shrink = (GTK_VALUE_BOOL (*arg) != FALSE);
258 gtk_window_set_hints (GTK_WIDGET (window), >K_WIDGET (window)->requisition);
261 window->allow_grow = (GTK_VALUE_BOOL (*arg) != FALSE);
262 gtk_window_set_hints (GTK_WIDGET (window), >K_WIDGET (window)->requisition);
265 gtk_window_set_position (window, GTK_VALUE_ENUM (*arg));
273 gtk_window_get_arg (GtkObject *object,
279 window = GTK_WINDOW (object);
284 GTK_VALUE_ENUM (*arg) = window->type;
287 GTK_VALUE_STRING (*arg) = g_strdup (window->title);
289 case ARG_AUTO_SHRINK:
290 GTK_VALUE_BOOL (*arg) = window->auto_shrink;
292 case ARG_ALLOW_SHRINK:
293 GTK_VALUE_BOOL (*arg) = window->allow_shrink;
296 GTK_VALUE_BOOL (*arg) = window->allow_grow;
299 GTK_VALUE_ENUM (*arg) = window->position;
302 arg->type = GTK_TYPE_INVALID;
308 gtk_window_new (GtkWindowType type)
312 window = gtk_type_new (gtk_window_get_type ());
316 return GTK_WIDGET (window);
320 gtk_window_set_title (GtkWindow *window,
323 g_return_if_fail (window != NULL);
324 g_return_if_fail (GTK_IS_WINDOW (window));
327 g_free (window->title);
328 window->title = g_strdup (title);
330 if (GTK_WIDGET_REALIZED (window))
331 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
335 gtk_window_set_wmclass (GtkWindow *window,
336 const gchar *wmclass_name,
337 const gchar *wmclass_class)
339 g_return_if_fail (window != NULL);
340 g_return_if_fail (GTK_IS_WINDOW (window));
342 g_free (window->wmclass_name);
343 window->wmclass_name = g_strdup (wmclass_name);
345 g_free (window->wmclass_class);
346 window->wmclass_class = g_strdup (wmclass_class);
348 if (GTK_WIDGET_REALIZED (window))
349 g_warning ("shouldn't set wmclass after window is realized!\n");
353 gtk_window_set_focus (GtkWindow *window,
356 g_return_if_fail (window != NULL);
357 g_return_if_fail (GTK_IS_WINDOW (window));
360 g_return_if_fail (GTK_IS_WIDGET (focus));
361 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
364 if (window->focus_widget != focus)
365 gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
369 gtk_window_set_default (GtkWindow *window,
370 GtkWidget *default_widget)
372 g_return_if_fail (window != NULL);
373 g_return_if_fail (GTK_IS_WINDOW (window));
376 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
378 if (window->default_widget != default_widget)
380 if (window->default_widget)
382 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
383 gtk_widget_draw_default (window->default_widget);
386 window->default_widget = default_widget;
388 if (window->default_widget)
390 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
391 gtk_widget_draw_default (window->default_widget);
397 gtk_window_set_policy (GtkWindow *window,
402 g_return_if_fail (window != NULL);
403 g_return_if_fail (GTK_IS_WINDOW (window));
405 window->allow_shrink = (allow_shrink != FALSE);
406 window->allow_grow = (allow_grow != FALSE);
407 window->auto_shrink = (auto_shrink != FALSE);
409 gtk_window_set_hints (GTK_WIDGET (window), >K_WIDGET (window)->requisition);
413 gtk_window_add_accel_group (GtkWindow *window,
414 GtkAccelGroup *accel_group)
416 g_return_if_fail (window != NULL);
417 g_return_if_fail (GTK_IS_WINDOW (window));
418 g_return_if_fail (accel_group != NULL);
420 gtk_accel_group_attach (accel_group, GTK_OBJECT (window));
424 gtk_window_remove_accel_group (GtkWindow *window,
425 GtkAccelGroup *accel_group)
427 g_return_if_fail (window != NULL);
428 g_return_if_fail (GTK_IS_WINDOW (window));
429 g_return_if_fail (accel_group != NULL);
431 gtk_accel_group_detach (accel_group, GTK_OBJECT (window));
435 gtk_window_set_position (GtkWindow *window,
436 GtkWindowPosition position)
438 g_return_if_fail (window != NULL);
439 g_return_if_fail (GTK_IS_WINDOW (window));
441 window->position = position;
445 gtk_window_activate_focus (GtkWindow *window)
447 g_return_val_if_fail (window != NULL, FALSE);
448 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
450 if (window->focus_widget)
452 gtk_widget_activate (window->focus_widget);
460 gtk_window_activate_default (GtkWindow *window)
462 g_return_val_if_fail (window != NULL, FALSE);
463 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
465 if (window->default_widget)
467 gtk_widget_activate (window->default_widget);
475 gtk_window_set_modal (GtkWindow *window, gboolean modal)
477 g_return_if_fail (window != NULL);
478 g_return_if_fail (GTK_IS_WINDOW (window));
480 /* If the widget was showed already, adjust it's grab state */
481 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(window)))
483 if (window->modal && !modal)
484 gtk_grab_remove (GTK_WIDGET(window));
485 else if (!window->modal && modal)
486 gtk_grab_add (GTK_WIDGET(window));
489 window->modal = modal;
493 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
495 GList *embedded_windows;
497 g_return_if_fail (window != NULL);
498 g_return_if_fail (GTK_IS_WINDOW (window));
500 g_print ("add %#x\n", xid);
502 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
503 if (embedded_windows)
504 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
505 g_quark_from_static_string ("gtk-embedded"));
506 embedded_windows = g_list_prepend (embedded_windows,
507 GUINT_TO_POINTER (xid));
509 gtk_object_set_data_full (GTK_OBJECT (window), "gtk-embedded",
512 (GtkDestroyNotify) g_list_free : NULL);
516 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
518 GList *embedded_windows;
521 g_return_if_fail (window != NULL);
522 g_return_if_fail (GTK_IS_WINDOW (window));
524 g_print ("remove %#x\n", xid);
526 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
527 if (embedded_windows)
528 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
529 g_quark_from_static_string ("gtk-embedded"));
531 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
534 embedded_windows = g_list_remove_link (embedded_windows, node);
535 g_list_free_1 (node);
538 gtk_object_set_data_full (GTK_OBJECT (window),
539 "gtk-embedded", embedded_windows,
541 (GtkDestroyNotify) g_list_free : NULL);
545 gtk_window_shutdown (GtkObject *object)
549 g_return_if_fail (object != NULL);
550 g_return_if_fail (GTK_IS_WINDOW (object));
552 window = GTK_WINDOW (object);
554 gtk_window_set_focus (window, NULL);
555 gtk_window_set_default (window, NULL);
557 GTK_OBJECT_CLASS (parent_class)->shutdown (object);
561 gtk_window_transient_parent_realized (GtkWidget *parent,
564 if (GTK_WIDGET_REALIZED (window))
565 gdk_window_set_transient_for (window->window, parent->window);
569 gtk_window_transient_parent_unrealized (GtkWidget *parent,
572 if (GTK_WIDGET_REALIZED (window))
573 gdk_property_delete (window->window,
574 gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
578 gtk_window_unset_transient_for (GtkWindow *window)
580 if (window->transient_parent)
582 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
583 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
585 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
586 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
588 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
589 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
590 &window->transient_parent);
592 window->transient_parent = NULL;
597 gtk_window_set_transient_for (GtkWindow *window,
600 g_return_if_fail (window != 0);
602 if (window->transient_parent)
604 gtk_window_unset_transient_for (window);
606 if (GTK_WIDGET_REALIZED (window) &&
607 GTK_WIDGET_REALIZED (window->transient_parent) &&
608 (!parent || !GTK_WIDGET_REALIZED (parent)))
609 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
610 GTK_WIDGET (window));
613 window->transient_parent = parent;
617 gtk_signal_connect (GTK_OBJECT (parent), "destroy",
618 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
619 &window->transient_parent);
620 gtk_signal_connect (GTK_OBJECT (parent), "realize",
621 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
623 gtk_signal_connect (GTK_OBJECT (parent), "unrealize",
624 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
627 if (GTK_WIDGET_REALIZED (window) &&
628 GTK_WIDGET_REALIZED (parent))
629 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
630 GTK_WIDGET (window));
635 gtk_window_geometry_destroy (GtkWindowGeometryInfo *info)
638 gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
639 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
644 static GtkWindowGeometryInfo *
645 gtk_window_get_geometry_info (GtkWindow *window, gboolean create)
647 GtkWindowGeometryInfo *info;
649 info = gtk_object_get_data (GTK_OBJECT (window), "gtk-window-geometry");
653 info = g_new (GtkWindowGeometryInfo, 1);
657 info->last_width = -1;
658 info->last_height = -1;
662 gtk_object_set_data_full (GTK_OBJECT (window),
664 "gtk-window-geometry",
666 (GtkDestroyNotify) gtk_window_geometry_destroy);
673 gtk_window_set_geometry_hints (GtkWindow *window,
674 GtkWidget *geometry_widget,
675 GdkGeometry *geometry,
676 GdkWindowHints geom_mask)
678 GtkWindowGeometryInfo *info;
680 g_return_if_fail (window != NULL);
682 info = gtk_window_get_geometry_info (window, TRUE);
685 gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
686 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
689 info->widget = geometry_widget;
691 gtk_signal_connect (GTK_OBJECT (geometry_widget), "destroy",
692 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
696 info->geometry = *geometry;
698 info->mask = geom_mask;
702 gtk_window_set_default_size (GtkWindow *window,
706 GtkWindowGeometryInfo *info;
708 g_return_if_fail (window != NULL);
710 info = gtk_window_get_geometry_info (window, TRUE);
713 info->height = height;
717 gtk_window_destroy (GtkObject *object)
721 g_return_if_fail (object != NULL);
722 g_return_if_fail (GTK_IS_WINDOW (object));
724 window = GTK_WINDOW (object);
726 gtk_container_unregister_toplevel (GTK_CONTAINER (object));
728 if (window->transient_parent)
729 gtk_window_unset_transient_for (window);
731 GTK_OBJECT_CLASS (parent_class)->destroy (object);
735 gtk_window_finalize (GtkObject *object)
739 g_return_if_fail (object != NULL);
740 g_return_if_fail (GTK_IS_WINDOW (object));
742 window = GTK_WINDOW (object);
743 g_free (window->title);
744 g_free (window->wmclass_name);
745 g_free (window->wmclass_class);
747 GTK_OBJECT_CLASS(parent_class)->finalize (object);
751 gtk_window_show (GtkWidget *widget)
753 g_return_if_fail (widget != NULL);
754 g_return_if_fail (GTK_IS_WINDOW (widget));
756 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
757 gtk_container_check_resize (GTK_CONTAINER (widget));
758 gtk_widget_map (widget);
760 if (GTK_WINDOW(widget)->modal)
761 gtk_grab_add(widget);
766 gtk_window_hide (GtkWidget *widget)
768 g_return_if_fail (widget != NULL);
769 g_return_if_fail (GTK_IS_WINDOW (widget));
771 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
772 gtk_widget_unmap (widget);
774 if (GTK_WINDOW(widget)->modal)
775 gtk_grab_remove(widget);
780 gtk_window_map (GtkWidget *widget)
784 g_return_if_fail (widget != NULL);
785 g_return_if_fail (GTK_IS_WINDOW (widget));
787 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
789 window = GTK_WINDOW (widget);
791 if (window->bin.child &&
792 GTK_WIDGET_VISIBLE (window->bin.child) &&
793 !GTK_WIDGET_MAPPED (window->bin.child))
794 gtk_widget_map (window->bin.child);
796 gtk_window_set_hints (widget, &widget->requisition);
797 gdk_window_show (widget->window);
801 gtk_window_unmap (GtkWidget *widget)
805 g_return_if_fail (widget != NULL);
806 g_return_if_fail (GTK_IS_WINDOW (widget));
808 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
809 gdk_window_hide (widget->window);
811 window = GTK_WINDOW (widget);
812 window->use_uposition = TRUE;
816 gtk_window_realize (GtkWidget *widget)
819 GdkWindowAttr attributes;
820 gint attributes_mask;
822 g_return_if_fail (widget != NULL);
823 g_return_if_fail (GTK_IS_WINDOW (widget));
825 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
826 window = GTK_WINDOW (widget);
828 switch (window->type)
830 case GTK_WINDOW_TOPLEVEL:
831 attributes.window_type = GDK_WINDOW_TOPLEVEL;
833 case GTK_WINDOW_DIALOG:
834 attributes.window_type = GDK_WINDOW_DIALOG;
836 case GTK_WINDOW_POPUP:
837 attributes.window_type = GDK_WINDOW_TEMP;
841 attributes.title = window->title;
842 attributes.wmclass_name = window->wmclass_name;
843 attributes.wmclass_class = window->wmclass_class;
844 attributes.width = widget->allocation.width;
845 attributes.height = widget->allocation.height;
846 attributes.wclass = GDK_INPUT_OUTPUT;
847 attributes.visual = gtk_widget_get_visual (widget);
848 attributes.colormap = gtk_widget_get_colormap (widget);
849 attributes.event_mask = gtk_widget_get_events (widget);
850 attributes.event_mask |= (GDK_EXPOSURE_MASK |
852 GDK_ENTER_NOTIFY_MASK |
853 GDK_LEAVE_NOTIFY_MASK |
854 GDK_FOCUS_CHANGE_MASK |
857 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
858 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
859 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
861 widget->window = gdk_window_new (NULL, &attributes, attributes_mask);
862 gdk_window_set_user_data (widget->window, window);
864 widget->style = gtk_style_attach (widget->style, widget->window);
865 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
866 gtk_window_paint (widget, NULL);
868 if (window->transient_parent &&
869 GTK_WIDGET_REALIZED (window->transient_parent))
870 gdk_window_set_transient_for (widget->window,
871 GTK_WIDGET (window->transient_parent)->window);
875 gtk_window_size_request (GtkWidget *widget,
876 GtkRequisition *requisition)
881 g_return_if_fail (widget != NULL);
882 g_return_if_fail (GTK_IS_WINDOW (widget));
883 g_return_if_fail (requisition != NULL);
885 window = GTK_WINDOW (widget);
886 bin = GTK_BIN (window);
888 requisition->width = GTK_CONTAINER (window)->border_width * 2;
889 requisition->height = GTK_CONTAINER (window)->border_width * 2;
891 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
893 gtk_widget_size_request (bin->child, &bin->child->requisition);
895 requisition->width += bin->child->requisition.width;
896 requisition->height += bin->child->requisition.height;
900 if (!GTK_WIDGET_VISIBLE (window))
901 GTK_CONTAINER (window)->need_resize = TRUE;
906 gtk_window_size_allocate (GtkWidget *widget,
907 GtkAllocation *allocation)
910 GtkAllocation child_allocation;
912 g_return_if_fail (widget != NULL);
913 g_return_if_fail (GTK_IS_WINDOW (widget));
914 g_return_if_fail (allocation != NULL);
916 window = GTK_WINDOW (widget);
917 widget->allocation = *allocation;
919 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
921 child_allocation.x = GTK_CONTAINER (window)->border_width;
922 child_allocation.y = GTK_CONTAINER (window)->border_width;
923 child_allocation.width = allocation->width - child_allocation.x * 2;
924 child_allocation.height = allocation->height - child_allocation.y * 2;
926 gtk_widget_size_allocate (window->bin.child, &child_allocation);
931 gtk_window_configure_event (GtkWidget *widget,
932 GdkEventConfigure *event)
935 GtkAllocation allocation;
936 gboolean need_expose = FALSE;
938 g_return_val_if_fail (widget != NULL, FALSE);
939 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
940 g_return_val_if_fail (event != NULL, FALSE);
942 window = GTK_WINDOW (widget);
944 /* If the window was merely moved, do nothing */
945 if ((widget->allocation.width == event->width) &&
946 (widget->allocation.height == event->height))
948 if (window->resize_count == 0) /* The window was merely moved */
952 /* We asked for a new size, which was rejected, so the
953 * WM sent us a synthetic configure event. We won't
954 * get the expose event we would normally get (since
955 * we have ForgetGravity), so we need to fake it.
962 window->handling_resize = TRUE;
966 allocation.width = event->width;
967 allocation.height = event->height;
969 gtk_widget_size_allocate (widget, &allocation);
971 if (window->bin.child &&
972 GTK_WIDGET_VISIBLE (window->bin.child) &&
973 !GTK_WIDGET_MAPPED (window->bin.child))
974 gtk_widget_map (window->bin.child);
976 if (window->resize_count > 0)
977 window->resize_count -= 1;
982 temp_event.type = GDK_EXPOSE;
983 temp_event.expose.window = widget->window;
984 temp_event.expose.send_event = TRUE;
985 temp_event.expose.area.x = 0;
986 temp_event.expose.area.y = 0;
987 temp_event.expose.area.width = event->width;
988 temp_event.expose.area.height = event->height;
989 temp_event.expose.count = 0;
991 gtk_widget_event (widget, &temp_event);
994 window->handling_resize = FALSE;
1000 gtk_window_key_press_event (GtkWidget *widget,
1004 GtkDirectionType direction = 0;
1007 g_return_val_if_fail (widget != NULL, FALSE);
1008 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1009 g_return_val_if_fail (event != NULL, FALSE);
1011 window = GTK_WINDOW (widget);
1015 if (window->focus_widget && GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1017 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
1021 handled = gtk_accel_groups_activate (GTK_OBJECT (window), event->keyval, event->state);
1025 switch (event->keyval)
1028 if (window->focus_widget)
1030 gtk_widget_activate (window->focus_widget);
1036 if (window->default_widget &&
1037 (!window->focus_widget ||
1038 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1040 gtk_widget_activate (window->default_widget);
1043 else if (window->focus_widget)
1045 gtk_widget_activate (window->focus_widget);
1054 case GDK_ISO_Left_Tab:
1055 switch (event->keyval)
1058 direction = GTK_DIR_UP;
1061 direction = GTK_DIR_DOWN;
1064 direction = GTK_DIR_LEFT;
1067 direction = GTK_DIR_RIGHT;
1070 case GDK_ISO_Left_Tab:
1071 if (event->state & GDK_SHIFT_MASK)
1072 direction = GTK_DIR_TAB_BACKWARD;
1074 direction = GTK_DIR_TAB_FORWARD;
1077 direction = GTK_DIR_UP; /* never reached, but makes compiler happy */
1080 gtk_container_focus (GTK_CONTAINER (widget), direction);
1082 if (!GTK_CONTAINER (window)->focus_child)
1083 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
1090 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
1091 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
1097 gtk_window_key_release_event (GtkWidget *widget,
1103 g_return_val_if_fail (widget != NULL, FALSE);
1104 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1105 g_return_val_if_fail (event != NULL, FALSE);
1107 window = GTK_WINDOW (widget);
1109 if (window->focus_widget && GTK_WIDGET_SENSITIVE (window->focus_widget))
1111 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
1114 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
1115 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
1121 gtk_window_enter_notify_event (GtkWidget *widget,
1122 GdkEventCrossing *event)
1124 g_return_val_if_fail (widget != NULL, FALSE);
1125 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1126 g_return_val_if_fail (event != NULL, FALSE);
1132 gtk_window_leave_notify_event (GtkWidget *widget,
1133 GdkEventCrossing *event)
1135 g_return_val_if_fail (widget != NULL, FALSE);
1136 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1137 g_return_val_if_fail (event != NULL, FALSE);
1143 gtk_window_focus_in_event (GtkWidget *widget,
1144 GdkEventFocus *event)
1147 GdkEventFocus fevent;
1149 g_return_val_if_fail (widget != NULL, FALSE);
1150 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1151 g_return_val_if_fail (event != NULL, FALSE);
1153 /* It appears spurious focus in events can occur when
1154 * the window is hidden. So we'll just check to see if
1155 * the window is visible before actually handling the
1158 if (GTK_WIDGET_VISIBLE (widget))
1160 window = GTK_WINDOW (widget);
1161 if (window->focus_widget && !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
1163 fevent.type = GDK_FOCUS_CHANGE;
1164 fevent.window = window->focus_widget->window;
1167 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
1175 gtk_window_focus_out_event (GtkWidget *widget,
1176 GdkEventFocus *event)
1179 GdkEventFocus fevent;
1181 g_return_val_if_fail (widget != NULL, FALSE);
1182 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1183 g_return_val_if_fail (event != NULL, FALSE);
1185 window = GTK_WINDOW (widget);
1186 if (window->focus_widget && GTK_WIDGET_HAS_FOCUS (window->focus_widget))
1188 fevent.type = GDK_FOCUS_CHANGE;
1189 fevent.window = window->focus_widget->window;
1192 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
1198 static GdkAtom atom_rcfiles = GDK_NONE;
1201 gtk_window_read_rcfiles (GtkWidget *widget,
1202 GdkEventClient *event)
1204 GList *embedded_windows;
1206 embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
1207 if (embedded_windows)
1212 for(i = 0; i < 5; i++)
1214 sev.data_format = 32;
1215 sev.message_type = atom_rcfiles;
1217 while (embedded_windows)
1219 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
1220 gdk_event_send_client_message ((GdkEvent *) &sev, xid);
1221 embedded_windows = embedded_windows->next;
1225 if (gtk_rc_reparse_all ())
1227 /* If the above returned true, some of our RC files are out
1228 * of date, so we need to reset all our widgets. Our other
1229 * toplevel windows will also get the message, but by
1230 * then, the RC file will up to date, so we have to tell
1235 toplevels = gtk_container_get_toplevels();
1238 gtk_widget_reset_rc_styles (toplevels->data);
1239 toplevels = toplevels->next;
1245 gtk_window_client_event (GtkWidget *widget,
1246 GdkEventClient *event)
1248 g_return_val_if_fail (widget != NULL, FALSE);
1249 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1250 g_return_val_if_fail (event != NULL, FALSE);
1253 atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
1255 if(event->message_type == atom_rcfiles)
1256 gtk_window_read_rcfiles (widget, event);
1262 gtk_window_check_resize (GtkContainer *container)
1266 g_return_if_fail (container != NULL);
1267 g_return_if_fail (GTK_IS_WINDOW (container));
1269 window = GTK_WINDOW (container);
1270 if (!window->handling_resize)
1272 if (GTK_WIDGET_VISIBLE (container))
1273 gtk_window_move_resize (window);
1275 GTK_CONTAINER (window)->need_resize = TRUE;
1279 /* FIXME: we leave container->resize_widgets set under some
1282 gtk_window_move_resize (GtkWindow *window)
1285 GtkWindowGeometryInfo *info;
1286 GtkContainer *container;
1289 gint new_width, new_height;
1290 gint min_width, min_height;
1293 gboolean needed_resize;
1294 gboolean size_changed;
1296 g_return_if_fail (window != NULL);
1297 g_return_if_fail (GTK_IS_WINDOW (window));
1299 widget = GTK_WIDGET (window);
1300 container = GTK_CONTAINER (widget);
1302 info = gtk_window_get_geometry_info (window, FALSE);
1304 /* Remember old size, to know if we have to reset hints */
1305 if (info && (info->last_width > 0))
1306 width = info->last_width;
1308 width = widget->requisition.width;
1310 if (info && (info->last_height > 0))
1311 height = info->last_height;
1313 height = widget->requisition.height;
1315 gtk_widget_size_request (widget, &widget->requisition);
1317 /* Figure out the new desired size */
1319 size_changed = FALSE;
1321 if (info && info->width > 0)
1323 size_changed = size_changed || (width != info->width);
1324 info->last_width = width;
1325 new_width = info->width;
1329 size_changed = size_changed || (width != widget->requisition.width);
1330 new_width = widget->requisition.width;
1333 if (info && info->height > 0)
1335 size_changed = size_changed || (height != info->height);
1336 info->last_height = height;
1337 new_height = info->height;
1341 size_changed = size_changed || (height != widget->requisition.height);
1342 new_height = widget->requisition.height;
1345 /* Figure out the new minimum size */
1347 if (info && (info->mask & (GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE)))
1349 if (info->mask && GDK_HINT_MIN_SIZE)
1351 min_width = info->geometry.min_width;
1352 min_height = info->geometry.min_height;
1356 min_width = info->geometry.base_width;
1357 min_height = info->geometry.base_height;
1362 min_width += widget->requisition.width - info->widget->requisition.width;
1363 min_height += widget->requisition.height - info->widget->requisition.height;
1368 min_width = widget->requisition.width;
1369 min_height = widget->requisition.height;
1374 gboolean saved_use_upos;
1376 saved_use_upos = window->use_uposition;
1377 gtk_window_set_hints (widget, &widget->requisition);
1378 window->use_uposition = saved_use_upos;
1384 if (window->use_uposition)
1385 switch (window->position)
1387 case GTK_WIN_POS_CENTER:
1388 x = (gdk_screen_width () - new_width) / 2;
1389 y = (gdk_screen_height () - new_height) / 2;
1390 gtk_widget_set_uposition (widget, x, y);
1392 case GTK_WIN_POS_MOUSE:
1393 gdk_window_get_pointer (NULL, &x, &y, NULL);
1396 y -= new_height / 2;
1398 screen_width = gdk_screen_width ();
1399 screen_height = gdk_screen_height ();
1403 else if (x > (screen_width - new_width))
1404 x = screen_width - new_width;
1408 else if (y > (screen_height - new_height))
1409 y = screen_height - new_height;
1411 gtk_widget_set_uposition (widget, x, y);
1415 /* Now, do the resizing */
1417 needed_resize = container->need_resize;
1418 container->need_resize = FALSE;
1420 if ((new_width == 0) || (new_height == 0))
1426 if (!GTK_WIDGET_REALIZED (window))
1428 GtkAllocation allocation;
1432 allocation.width = new_width;
1433 allocation.height = new_height;
1435 gtk_widget_size_allocate (widget, &allocation);
1440 gdk_window_get_geometry (widget->window, NULL, NULL, &width, &height, NULL);
1442 /* As an optimization, we don't try to get a new size from the
1443 * window manager if we asked for the same size last time and
1447 (((window->auto_shrink &&
1448 ((width != new_width) ||
1449 (height != new_height)))) ||
1450 ((width < min_width) ||
1451 (height < min_height))))
1453 window->resize_count += 1;
1455 if (!window->auto_shrink)
1457 new_width = MAX(width, min_width);
1458 new_height = MAX(height, min_height);
1461 if ((x != -1) && (y != -1))
1462 gdk_window_move_resize (widget->window, x, y,
1466 gdk_window_resize (widget->window,
1470 else if (needed_resize)
1472 /* The windows contents changed size while it was not
1473 * visible, so reallocate everything, since we didn't
1474 * keep track of what changed
1476 GtkAllocation allocation;
1480 allocation.width = new_width;
1481 allocation.height = new_height;
1483 gtk_widget_size_allocate (widget, &allocation);
1487 if ((x != -1) && (y != -1))
1488 gdk_window_move (widget->window, x, y);
1490 gtk_container_resize_children (GTK_CONTAINER (window));
1495 gtk_window_real_set_focus (GtkWindow *window,
1498 GdkEventFocus event;
1499 gboolean def_flags = 0;
1501 g_return_if_fail (window != NULL);
1502 g_return_if_fail (GTK_IS_WINDOW (window));
1504 if (window->default_widget)
1505 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
1507 if (window->focus_widget)
1509 event.type = GDK_FOCUS_CHANGE;
1510 event.window = window->focus_widget->window;
1513 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
1514 (window->focus_widget != window->default_widget))
1516 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
1517 /* if any widget had the default set there should be
1518 a default_widget, but might not so this is a sanity
1520 if (window->default_widget)
1521 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1524 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
1527 window->focus_widget = focus;
1529 if (window->focus_widget)
1531 event.type = GDK_FOCUS_CHANGE;
1532 event.window = window->focus_widget->window;
1535 if (window->default_widget)
1537 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
1538 (window->focus_widget != window->default_widget))
1540 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
1541 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
1542 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1546 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1550 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
1552 else if (window->default_widget)
1554 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1557 if (window->default_widget &&
1558 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
1559 gtk_widget_queue_draw (window->default_widget);
1563 gtk_window_set_hints (GtkWidget *widget,
1564 GtkRequisition *requisition)
1567 GtkWidgetAuxInfo *aux_info;
1568 GtkWindowGeometryInfo *geometry_info;
1569 GdkGeometry new_geometry;
1572 gint extra_width = 0;
1573 gint extra_height = 0;
1575 g_return_if_fail (widget != NULL);
1576 g_return_if_fail (GTK_IS_WINDOW (widget));
1577 g_return_if_fail (requisition != NULL);
1579 if (GTK_WIDGET_REALIZED (widget))
1581 window = GTK_WINDOW (widget);
1583 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
1587 flags = geometry_info->mask;
1588 new_geometry = geometry_info->geometry;
1590 if (geometry_info->widget)
1592 extra_width = requisition->width - geometry_info->widget->requisition.width;
1593 extra_height = requisition->height - geometry_info->widget->requisition.height;
1602 aux_info = gtk_object_get_data (GTK_OBJECT (widget), "gtk-aux-info");
1603 if (aux_info && (aux_info->x != -1) && (aux_info->y != -1))
1607 flags |= GDK_HINT_POS;
1610 if (flags & GDK_HINT_BASE_SIZE)
1612 new_geometry.base_width += extra_width;
1613 new_geometry.base_height += extra_height;
1615 else if (!(flags & GDK_HINT_MIN_SIZE) &&
1616 (flags & GDK_HINT_RESIZE_INC) &&
1617 ((extra_width != 0) || (extra_height != 0)))
1619 flags |= GDK_HINT_BASE_SIZE;
1621 new_geometry.base_width = extra_width;
1622 new_geometry.base_height = extra_height;
1625 if (flags & GDK_HINT_MIN_SIZE)
1627 new_geometry.min_width += extra_width;
1628 new_geometry.min_height += extra_height;
1630 else if (!window->allow_shrink)
1632 flags |= GDK_HINT_MIN_SIZE;
1634 new_geometry.min_width = requisition->width;
1635 new_geometry.min_height = requisition->height;
1638 if (flags & GDK_HINT_MAX_SIZE)
1640 new_geometry.max_width += extra_width;
1641 new_geometry.max_height += extra_height;
1643 else if (!window->allow_grow)
1645 flags |= GDK_HINT_MAX_SIZE;
1647 new_geometry.max_width = requisition->width;
1648 new_geometry.max_height = requisition->height;
1651 gdk_window_set_geometry_hints (widget->window, &new_geometry, flags);
1653 if (window->use_uposition && (flags & GDK_HINT_POS))
1655 window->use_uposition = FALSE;
1656 gdk_window_move (widget->window, ux, uy);
1662 gtk_window_paint (GtkWidget *widget,
1665 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
1666 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
1670 gtk_window_expose (GtkWidget *widget,
1671 GdkEventExpose *event)
1673 g_return_val_if_fail (widget != NULL, FALSE);
1674 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1675 g_return_val_if_fail (event != NULL, FALSE);
1677 if (!GTK_WIDGET_APP_PAINTABLE (widget))
1678 gtk_window_paint (widget, &event->area);
1680 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
1681 return (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
1687 gtk_window_draw (GtkWidget *widget,
1690 if (!GTK_WIDGET_APP_PAINTABLE (widget))
1691 gtk_window_paint (widget, area);
1693 if (GTK_WIDGET_CLASS (parent_class)->draw)
1694 (* GTK_WIDGET_CLASS (parent_class)->draw) (widget, area);
1698 gtk_window_style_set (GtkWidget *widget,
1699 GtkStyle *previous_style)
1703 if (GTK_WIDGET_REALIZED (widget) &&
1704 !GTK_WIDGET_NO_WINDOW (widget))
1706 gtk_style_set_background (widget->style, widget->window, widget->state);
1710 area.width = widget->allocation.width;
1711 area.height = widget->allocation.height;
1712 gtk_window_draw(widget, &area);
1714 if (GTK_WIDGET_DRAWABLE (widget))
1715 gdk_window_clear (widget->window);