]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkwindow.c
Adapt cast macros to standard.
[~andy/gtk] / gtk / gtkwindow.c
index a4532a368ed3752e78cef69536605fa2c82253a6..ea08918635bf0a7904aa632545cf7d2695d66378 100644 (file)
  * Library General Public License for more details.
  *
  * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
  */
+
+/*
+ * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
 #include <string.h>
 #include <limits.h>
 #include "gdk/gdk.h"
 #include "gdk/gdkkeysyms.h"
-#include "gdk/gdkx.h"
+#include "gdkx.h"              /* For gdk_progclass */
 #include "gtkprivate.h"
+#include "gtkrc.h"
 #include "gtksignal.h"
 #include "gtkwindow.h"
+#include "gtkbindings.h"
+#include "gtkmain.h"
+
+/* TODO: remove this define and assorted code in 1.3 and fix up the
+ * real culprits.
+ */
+#define FIXME_ZVT_ME_HARDER
 
 enum {
-  MOVE_RESIZE,
   SET_FOCUS,
   LAST_SIGNAL
 };
@@ -36,35 +52,40 @@ enum {
   ARG_AUTO_SHRINK,
   ARG_ALLOW_SHRINK,
   ARG_ALLOW_GROW,
-  ARG_WIN_POS
+  ARG_MODAL,
+  ARG_WIN_POS,
+  ARG_DEFAULT_WIDTH,
+  ARG_DEFAULT_HEIGHT
 };
 
-typedef gint (*GtkWindowSignal1) (GtkObject *object,
-                                 gpointer   arg1,
-                                 gpointer   arg2,
-                                 gint       arg3,
-                                 gint       arg4,
-                                 gpointer   data);
-typedef void (*GtkWindowSignal2) (GtkObject *object,
-                                 gpointer   arg1,
-                                 gpointer   data);
-
-static void gtk_window_marshal_signal_1 (GtkObject      *object,
-                                        GtkSignalFunc   func,
-                                        gpointer        func_data,
-                                        GtkArg         *args);
-static void gtk_window_marshal_signal_2 (GtkObject      *object,
-                                        GtkSignalFunc   func,
-                                        gpointer        func_data,
-                                        GtkArg         *args);
+typedef struct {
+  GdkGeometry    geometry; /* Last set of geometry hints we set */
+  GdkWindowHints flags;
+  gint           width;
+  gint           height;
+} GtkWindowLastGeometryInfo;
+
+typedef struct {
+  /* Properties that the app has set on the window
+   */
+  GdkGeometry    geometry;     /* Geometry hints */
+  GdkWindowHints mask;
+  GtkWidget     *widget;       /* subwidget to which hints apply */
+  gint           width;                /* Default size */
+  gint           height;
+
+  GtkWindowLastGeometryInfo last;
+} GtkWindowGeometryInfo;
+
 static void gtk_window_class_init         (GtkWindowClass    *klass);
 static void gtk_window_init               (GtkWindow         *window);
-static void gtk_window_set_arg            (GtkWindow         *window,
+static void gtk_window_set_arg            (GtkObject         *object,
                                           GtkArg            *arg,
                                           guint              arg_id);
-static void gtk_window_get_arg            (GtkWindow         *window,
+static void gtk_window_get_arg            (GtkObject         *object,
                                           GtkArg            *arg,
                                           guint              arg_id);
+static void gtk_window_shutdown           (GtkObject         *object);
 static void gtk_window_destroy            (GtkObject         *object);
 static void gtk_window_finalize           (GtkObject         *object);
 static void gtk_window_show               (GtkWidget         *widget);
@@ -76,8 +97,6 @@ static void gtk_window_size_request       (GtkWidget         *widget,
                                           GtkRequisition    *requisition);
 static void gtk_window_size_allocate      (GtkWidget         *widget,
                                           GtkAllocation     *allocation);
-static gint gtk_window_expose_event       (GtkWidget         *widget,
-                                          GdkEventExpose    *event);
 static gint gtk_window_configure_event    (GtkWidget         *widget,
                                           GdkEventConfigure *event);
 static gint gtk_window_key_press_event    (GtkWidget         *widget,
@@ -94,42 +113,73 @@ static gint gtk_window_focus_out_event    (GtkWidget         *widget,
                                           GdkEventFocus     *event);
 static gint gtk_window_client_event      (GtkWidget         *widget,
                                           GdkEventClient    *event);
-static gint gtk_window_need_resize        (GtkContainer      *container);
-static gint gtk_real_window_move_resize   (GtkWindow         *window,
-                                          gint              *x,
-                                          gint              *y,
-                                          gint               width,
-                                          gint               height);
-static void gtk_real_window_set_focus     (GtkWindow         *window,
+static void gtk_window_check_resize       (GtkContainer      *container);
+static void gtk_window_real_set_focus     (GtkWindow         *window,
                                           GtkWidget         *focus);
-static gint gtk_window_move_resize        (GtkWidget         *widget);
-static void gtk_window_set_hints          (GtkWidget         *widget,
-                                          GtkRequisition    *requisition);
-static gint gtk_window_check_accelerator  (GtkWindow         *window,
-                                          gint               key,
-                                          guint              mods);
 
+static void gtk_window_move_resize        (GtkWindow         *window);
+static gboolean gtk_window_compare_hints  (GdkGeometry       *geometry_a,
+                                          guint              flags_a,
+                                          GdkGeometry       *geometry_b,
+                                          guint              flags_b);
+static void gtk_window_compute_default_size (GtkWindow       *window,
+                                            guint           *width,
+                                            guint           *height);
+static void  gtk_window_constrain_size      (GtkWindow       *window,
+                                            GdkGeometry     *geometry,
+                                            guint            flags,
+                                            gint             width,
+                                            gint             height,
+                                            gint            *new_width,
+                                            gint            *new_height);
+static void gtk_window_compute_hints      (GtkWindow         *window, 
+                                          GdkGeometry       *new_geometry,
+                                          guint             *new_flags);
+static void gtk_window_compute_reposition (GtkWindow         *window,
+                                          gint               new_width,
+                                          gint               new_height,
+                                          gint              *x,
+                                          gint              *y);
+
+static void gtk_window_read_rcfiles       (GtkWidget         *widget,
+                                          GdkEventClient    *event);
+static void gtk_window_draw               (GtkWidget         *widget,
+                                          GdkRectangle      *area);
+static void gtk_window_paint              (GtkWidget         *widget,
+                                          GdkRectangle      *area);
+static gint gtk_window_expose             (GtkWidget         *widget,
+                                          GdkEventExpose    *event);
+static void gtk_window_unset_transient_for         (GtkWindow  *window);
+static void gtk_window_transient_parent_realized   (GtkWidget  *parent,
+                                                   GtkWidget  *window);
+static void gtk_window_transient_parent_unrealized (GtkWidget  *parent,
+                                                   GtkWidget  *window);
+
+static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
+                                                           gboolean   create);
+static void gtk_window_geometry_destroy  (GtkWindowGeometryInfo *info);
 
 static GtkBinClass *parent_class = NULL;
-static gint window_signals[LAST_SIGNAL] = { 0 };
+static guint window_signals[LAST_SIGNAL] = { 0 };
 
 
-guint
-gtk_window_get_type ()
+GtkType
+gtk_window_get_type (void)
 {
-  static guint window_type = 0;
+  static GtkType window_type = 0;
 
   if (!window_type)
     {
-      GtkTypeInfo window_info =
+      static const GtkTypeInfo window_info =
       {
        "GtkWindow",
        sizeof (GtkWindow),
        sizeof (GtkWindowClass),
        (GtkClassInitFunc) gtk_window_class_init,
        (GtkObjectInitFunc) gtk_window_init,
-       (GtkArgSetFunc) gtk_window_set_arg,
-       (GtkArgGetFunc) gtk_window_get_arg,
+        /* reserved_1 */ NULL,
+       /* reserved_2 */ NULL,
+       (GtkClassInitFunc) NULL,
       };
 
       window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
@@ -151,34 +201,30 @@ gtk_window_class_init (GtkWindowClass *klass)
 
   parent_class = gtk_type_class (gtk_bin_get_type ());
 
-  gtk_object_add_arg_type ("GtkWindow::type", GTK_TYPE_WINDOW_TYPE, ARG_TYPE);
-  gtk_object_add_arg_type ("GtkWindow::title", GTK_TYPE_STRING, ARG_TITLE);
-  gtk_object_add_arg_type ("GtkWindow::auto_shrink", GTK_TYPE_BOOL, ARG_AUTO_SHRINK);
-  gtk_object_add_arg_type ("GtkWindow::allow_shrink", GTK_TYPE_BOOL, ARG_ALLOW_SHRINK);
-  gtk_object_add_arg_type ("GtkWindow::allow_grow", GTK_TYPE_BOOL, ARG_ALLOW_GROW);
-  gtk_object_add_arg_type ("GtkWindow::window_position", GTK_TYPE_ENUM, ARG_WIN_POS);
-
-  window_signals[MOVE_RESIZE] =
-    gtk_signal_new ("move_resize",
-                    GTK_RUN_LAST,
-                    object_class->type,
-                    GTK_SIGNAL_OFFSET (GtkWindowClass, move_resize),
-                    gtk_window_marshal_signal_1,
-                   GTK_TYPE_BOOL, 4,
-                    GTK_TYPE_POINTER, GTK_TYPE_POINTER,
-                    GTK_TYPE_INT, GTK_TYPE_INT);
-
+  gtk_object_add_arg_type ("GtkWindow::type", GTK_TYPE_WINDOW_TYPE, GTK_ARG_READWRITE, ARG_TYPE);
+  gtk_object_add_arg_type ("GtkWindow::title", GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_TITLE);
+  gtk_object_add_arg_type ("GtkWindow::auto_shrink", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_AUTO_SHRINK);
+  gtk_object_add_arg_type ("GtkWindow::allow_shrink", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ALLOW_SHRINK);
+  gtk_object_add_arg_type ("GtkWindow::allow_grow", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ALLOW_GROW);
+  gtk_object_add_arg_type ("GtkWindow::modal", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_MODAL);
+  gtk_object_add_arg_type ("GtkWindow::window_position", GTK_TYPE_WINDOW_POSITION, GTK_ARG_READWRITE, ARG_WIN_POS);
+  gtk_object_add_arg_type ("GtkWindow::default_width", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_DEFAULT_WIDTH);
+  gtk_object_add_arg_type ("GtkWindow::default_height", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_DEFAULT_HEIGHT);
+  
   window_signals[SET_FOCUS] =
     gtk_signal_new ("set_focus",
                     GTK_RUN_LAST,
                     object_class->type,
                     GTK_SIGNAL_OFFSET (GtkWindowClass, set_focus),
-                    gtk_window_marshal_signal_2,
+                    gtk_marshal_NONE__POINTER,
                    GTK_TYPE_NONE, 1,
-                    GTK_TYPE_POINTER);
+                    GTK_TYPE_WIDGET);
 
   gtk_object_class_add_signals (object_class, window_signals, LAST_SIGNAL);
 
+  object_class->set_arg = gtk_window_set_arg;
+  object_class->get_arg = gtk_window_get_arg;
+  object_class->shutdown = gtk_window_shutdown;
   object_class->destroy = gtk_window_destroy;
   object_class->finalize = gtk_window_finalize;
 
@@ -189,7 +235,6 @@ gtk_window_class_init (GtkWindowClass *klass)
   widget_class->realize = gtk_window_realize;
   widget_class->size_request = gtk_window_size_request;
   widget_class->size_allocate = gtk_window_size_allocate;
-  widget_class->expose_event = gtk_window_expose_event;
   widget_class->configure_event = gtk_window_configure_event;
   widget_class->key_press_event = gtk_window_key_press_event;
   widget_class->key_release_event = gtk_window_key_release_event;
@@ -199,10 +244,12 @@ gtk_window_class_init (GtkWindowClass *klass)
   widget_class->focus_out_event = gtk_window_focus_out_event;
   widget_class->client_event = gtk_window_client_event;
 
-  container_class->need_resize = gtk_window_need_resize;
+  widget_class->draw = gtk_window_draw;
+  widget_class->expose_event = gtk_window_expose;
+   
+  container_class->check_resize = gtk_window_check_resize;
 
-  klass->move_resize = gtk_real_window_move_resize;
-  klass->set_focus = gtk_real_window_set_focus;
+  klass->set_focus = gtk_window_real_set_focus;
 }
 
 static void
@@ -211,30 +258,35 @@ gtk_window_init (GtkWindow *window)
   GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
   GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
 
+  gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
+
   window->title = NULL;
-  window->wmclass_name = NULL;
-  window->wmclass_class = NULL;
+  window->wmclass_name = g_strdup (g_get_prgname ());
+  window->wmclass_class = g_strdup (gdk_progclass);
   window->type = GTK_WINDOW_TOPLEVEL;
-  window->accelerator_tables = NULL;
   window->focus_widget = NULL;
   window->default_widget = NULL;
   window->resize_count = 0;
-  window->need_resize = FALSE;
   window->allow_shrink = FALSE;
   window->allow_grow = TRUE;
   window->auto_shrink = FALSE;
   window->handling_resize = FALSE;
   window->position = GTK_WIN_POS_NONE;
   window->use_uposition = TRUE;
+  window->modal = FALSE;
   
   gtk_container_register_toplevel (GTK_CONTAINER (window));
 }
 
 static void
-gtk_window_set_arg (GtkWindow  *window,
+gtk_window_set_arg (GtkObject  *object,
                    GtkArg     *arg,
                    guint       arg_id)
 {
+  GtkWindow  *window;
+
+  window = GTK_WINDOW (object);
+
   switch (arg_id)
     {
     case ARG_TYPE:
@@ -245,29 +297,45 @@ gtk_window_set_arg (GtkWindow  *window,
       break;
     case ARG_AUTO_SHRINK:
       window->auto_shrink = (GTK_VALUE_BOOL (*arg) != FALSE);
+      gtk_widget_queue_resize (GTK_WIDGET (window));
       break;
     case ARG_ALLOW_SHRINK:
       window->allow_shrink = (GTK_VALUE_BOOL (*arg) != FALSE);
+      gtk_widget_queue_resize (GTK_WIDGET (window));
       break;
     case ARG_ALLOW_GROW:
       window->allow_grow = (GTK_VALUE_BOOL (*arg) != FALSE);
+      gtk_widget_queue_resize (GTK_WIDGET (window));
+      break;
+    case ARG_MODAL:
+      gtk_window_set_modal (window, GTK_VALUE_BOOL (*arg));
       break;
     case ARG_WIN_POS:
-      gtk_window_position (window, GTK_VALUE_ENUM (*arg));
+      gtk_window_set_position (window, GTK_VALUE_ENUM (*arg));
+      break;
+    case ARG_DEFAULT_WIDTH:
+      gtk_window_set_default_size (window, GTK_VALUE_INT (*arg), -2);
+      break;
+    case ARG_DEFAULT_HEIGHT:
+      gtk_window_set_default_size (window, -2, GTK_VALUE_INT (*arg));
       break;
     default:
-      arg->type = GTK_TYPE_INVALID;
       break;
     }
 }
 
 static void
-gtk_window_get_arg (GtkWindow  *window,
+gtk_window_get_arg (GtkObject  *object,
                    GtkArg     *arg,
                    guint       arg_id)
 {
+  GtkWindow  *window;
+
+  window = GTK_WINDOW (object);
+
   switch (arg_id)
     {
+      GtkWindowGeometryInfo *info;
     case ARG_TYPE:
       GTK_VALUE_ENUM (*arg) = window->type;
       break;
@@ -283,9 +351,26 @@ gtk_window_get_arg (GtkWindow  *window,
     case ARG_ALLOW_GROW:
       GTK_VALUE_BOOL (*arg) = window->allow_grow;
       break;
+    case ARG_MODAL:
+      GTK_VALUE_BOOL (*arg) = window->modal;
+      break;
     case ARG_WIN_POS:
       GTK_VALUE_ENUM (*arg) = window->position;
       break;
+    case ARG_DEFAULT_WIDTH:
+      info = gtk_window_get_geometry_info (window, FALSE);
+      if (!info)
+       GTK_VALUE_INT (*arg) = -1;
+      else
+       GTK_VALUE_INT (*arg) = info->width;
+      break;
+    case ARG_DEFAULT_HEIGHT:
+      info = gtk_window_get_geometry_info (window, FALSE);
+      if (!info)
+       GTK_VALUE_INT (*arg) = -1;
+      else
+       GTK_VALUE_INT (*arg) = info->height;
+      break;
     default:
       arg->type = GTK_TYPE_INVALID;
       break;
@@ -297,7 +382,9 @@ gtk_window_new (GtkWindowType type)
 {
   GtkWindow *window;
 
-  window = gtk_type_new (gtk_window_get_type ());
+  g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
+
+  window = gtk_type_new (GTK_TYPE_WINDOW);
 
   window->type = type;
 
@@ -321,18 +408,16 @@ gtk_window_set_title (GtkWindow   *window,
 
 void
 gtk_window_set_wmclass (GtkWindow *window,
-                       gchar     *wmclass_name,
-                       gchar     *wmclass_class)
+                       const gchar *wmclass_name,
+                       const gchar *wmclass_class)
 {
   g_return_if_fail (window != NULL);
   g_return_if_fail (GTK_IS_WINDOW (window));
 
-  if (window->wmclass_name)
-    g_free (window->wmclass_name);
+  g_free (window->wmclass_name);
   window->wmclass_name = g_strdup (wmclass_name);
 
-  if (window->wmclass_class)
-    g_free (window->wmclass_class);
+  g_free (window->wmclass_class);
   window->wmclass_class = g_strdup (wmclass_class);
 
   if (GTK_WIDGET_REALIZED (window))
@@ -343,18 +428,30 @@ void
 gtk_window_set_focus (GtkWindow *window,
                      GtkWidget *focus)
 {
-  gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GTK_IS_WINDOW (window));
+  if (focus)
+    {
+      g_return_if_fail (GTK_IS_WIDGET (focus));
+      g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
+    }
+
+  if ((window->focus_widget != focus) ||
+      (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
+    gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
 }
 
 void
 gtk_window_set_default (GtkWindow *window,
-                       GtkWidget *defaultw)
+                       GtkWidget *default_widget)
 {
   g_return_if_fail (window != NULL);
   g_return_if_fail (GTK_IS_WINDOW (window));
-  g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (defaultw));
 
-  if (window->default_widget != defaultw)
+  if (default_widget)
+    g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
+
+  if (window->default_widget != default_widget)
     {
       if (window->default_widget)
        {
@@ -362,7 +459,7 @@ gtk_window_set_default (GtkWindow *window,
          gtk_widget_draw_default (window->default_widget);
        }
 
-      window->default_widget = defaultw;
+      window->default_widget = default_widget;
 
       if (window->default_widget)
        {
@@ -384,35 +481,35 @@ gtk_window_set_policy (GtkWindow *window,
   window->allow_shrink = (allow_shrink != FALSE);
   window->allow_grow = (allow_grow != FALSE);
   window->auto_shrink = (auto_shrink != FALSE);
+
+  gtk_widget_queue_resize (GTK_WIDGET (window));
 }
 
 void
-gtk_window_add_accelerator_table (GtkWindow           *window,
-                                 GtkAcceleratorTable *table)
+gtk_window_add_accel_group (GtkWindow        *window,
+                           GtkAccelGroup    *accel_group)
 {
   g_return_if_fail (window != NULL);
   g_return_if_fail (GTK_IS_WINDOW (window));
+  g_return_if_fail (accel_group != NULL);
 
-  gtk_accelerator_table_ref (table);
-  window->accelerator_tables = g_list_prepend (window->accelerator_tables,
-                                              table);
+  gtk_accel_group_attach (accel_group, GTK_OBJECT (window));
 }
 
 void
-gtk_window_remove_accelerator_table (GtkWindow           *window,
-                                    GtkAcceleratorTable *table)
+gtk_window_remove_accel_group (GtkWindow       *window,
+                              GtkAccelGroup   *accel_group)
 {
   g_return_if_fail (window != NULL);
   g_return_if_fail (GTK_IS_WINDOW (window));
+  g_return_if_fail (accel_group != NULL);
 
-  window->accelerator_tables = g_list_remove (window->accelerator_tables,
-                                             table);
-  gtk_accelerator_table_unref (table);
+  gtk_accel_group_detach (accel_group, GTK_OBJECT (window));
 }
 
 void
-gtk_window_position (GtkWindow         *window,
-                    GtkWindowPosition  position)
+gtk_window_set_position (GtkWindow         *window,
+                        GtkWindowPosition  position)
 {
   g_return_if_fail (window != NULL);
   g_return_if_fail (GTK_IS_WINDOW (window));
@@ -428,7 +525,8 @@ gtk_window_activate_focus (GtkWindow      *window)
 
   if (window->focus_widget)
     {
-      gtk_widget_activate (window->focus_widget);
+      if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
+       gtk_widget_activate (window->focus_widget);
       return TRUE;
     }
 
@@ -441,7 +539,7 @@ gtk_window_activate_default (GtkWindow      *window)
   g_return_val_if_fail (window != NULL, FALSE);
   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
 
-  if (window->default_widget)
+  if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget))
     {
       gtk_widget_activate (window->default_widget);
       return TRUE;
@@ -450,49 +548,292 @@ gtk_window_activate_default (GtkWindow      *window)
   return FALSE;
 }
 
+void
+gtk_window_set_modal (GtkWindow *window,
+                     gboolean   modal)
+{
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GTK_IS_WINDOW (window));
+
+  window->modal = modal != FALSE;
+
+  /* adjust desired modality state */
+  if (GTK_WIDGET_VISIBLE (window) && window->modal)
+    gtk_grab_add (GTK_WIDGET (window));
+  else
+    gtk_grab_remove (GTK_WIDGET (window));
+}
+
+void
+gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
+{
+  GList *embedded_windows;
+
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GTK_IS_WINDOW (window));
+
+  embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
+  if (embedded_windows)
+    gtk_object_remove_no_notify_by_id (GTK_OBJECT (window), 
+                                      g_quark_from_static_string ("gtk-embedded"));
+  embedded_windows = g_list_prepend (embedded_windows,
+                                    GUINT_TO_POINTER (xid));
+
+  gtk_object_set_data_full (GTK_OBJECT (window), "gtk-embedded", 
+                           embedded_windows,
+                           embedded_windows ?
+                             (GtkDestroyNotify) g_list_free : NULL);
+}
+
+void
+gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
+{
+  GList *embedded_windows;
+  GList *node;
+
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GTK_IS_WINDOW (window));
+  
+  embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
+  if (embedded_windows)
+    gtk_object_remove_no_notify_by_id (GTK_OBJECT (window), 
+                                      g_quark_from_static_string ("gtk-embedded"));
+
+  node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
+  if (node)
+    {
+      embedded_windows = g_list_remove_link (embedded_windows, node);
+      g_list_free_1 (node);
+    }
+  
+  gtk_object_set_data_full (GTK_OBJECT (window), 
+                           "gtk-embedded", embedded_windows,
+                           embedded_windows ?
+                             (GtkDestroyNotify) g_list_free : NULL);
+}
+
+void       
+gtk_window_reposition (GtkWindow *window,
+                      gint       x,
+                      gint       y)
+{
+  GtkWindowGeometryInfo *info;
+  
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GTK_IS_WINDOW (window));
+
+  /* keep this in sync with gtk_window_compute_reposition()
+   */
+  if (GTK_WIDGET_REALIZED (window))
+    {
+      info = gtk_window_get_geometry_info (window, TRUE);
+
+      if (!(info->last.flags & GDK_HINT_POS))
+       {
+         info->last.flags |= GDK_HINT_POS;
+         gdk_window_set_geometry_hints (GTK_WIDGET (window)->window,
+                                        &info->last.geometry,
+                                        info->last.flags);
+       }
+  
+      gdk_window_move (GTK_WIDGET (window)->window, x, y);
+    }
+}
+
 static void
-gtk_window_marshal_signal_1 (GtkObject      *object,
-                            GtkSignalFunc   func,
-                            gpointer        func_data,
-                            GtkArg         *args)
+gtk_window_shutdown (GtkObject *object)
 {
-  GtkWindowSignal1 rfunc;
-  gint *return_val;
-
-  rfunc = (GtkWindowSignal1) func;
-  return_val = GTK_RETLOC_BOOL (args[4]);
-
-  *return_val = (* rfunc) (object,
-                          GTK_VALUE_POINTER (args[0]),
-                          GTK_VALUE_POINTER (args[1]),
-                          GTK_VALUE_INT (args[2]),
-                          GTK_VALUE_INT (args[3]),
-                          func_data);
+  GtkWindow *window;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (GTK_IS_WINDOW (object));
+
+  window = GTK_WINDOW (object);
+
+  gtk_window_set_focus (window, NULL);
+  gtk_window_set_default (window, NULL);
+
+  GTK_OBJECT_CLASS (parent_class)->shutdown (object);
+}
+
+static void
+gtk_window_transient_parent_realized (GtkWidget *parent,
+                                     GtkWidget *window)
+{
+  if (GTK_WIDGET_REALIZED (window))
+    gdk_window_set_transient_for (window->window, parent->window);
+}
+
+static void
+gtk_window_transient_parent_unrealized (GtkWidget *parent,
+                                       GtkWidget *window)
+{
+  if (GTK_WIDGET_REALIZED (window))
+    gdk_property_delete (window->window, 
+                        gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
+}
+
+static void       
+gtk_window_unset_transient_for  (GtkWindow *window)
+{
+  if (window->transient_parent)
+    {
+      gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
+                                    GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
+                                    window);
+      gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
+                                    GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
+                                    window);
+      gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
+                                    GTK_SIGNAL_FUNC (gtk_widget_destroyed),
+                                    &window->transient_parent);
+
+      window->transient_parent = NULL;
+    }
+}
+
+void       
+gtk_window_set_transient_for  (GtkWindow *window, 
+                              GtkWindow *parent)
+{
+  g_return_if_fail (window != 0);
+
+  if (window->transient_parent)
+    {
+      if (GTK_WIDGET_REALIZED (window) && 
+         GTK_WIDGET_REALIZED (window->transient_parent) && 
+         (!parent || !GTK_WIDGET_REALIZED (parent)))
+       gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
+                                               GTK_WIDGET (window));
+
+      gtk_window_unset_transient_for (window);
+    }
+
+  window->transient_parent = parent;
+
+  if (parent)
+    {
+      gtk_signal_connect (GTK_OBJECT (parent), "destroy",
+                         GTK_SIGNAL_FUNC (gtk_widget_destroyed),
+                         &window->transient_parent);
+      gtk_signal_connect (GTK_OBJECT (parent), "realize",
+                         GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
+                         window);
+      gtk_signal_connect (GTK_OBJECT (parent), "unrealize",
+                         GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
+                         window);
+
+      if (GTK_WIDGET_REALIZED (window) &&
+         GTK_WIDGET_REALIZED (parent))
+       gtk_window_transient_parent_realized (GTK_WIDGET (parent),
+                                             GTK_WIDGET (window));
+    }
 }
 
 static void
-gtk_window_marshal_signal_2 (GtkObject      *object,
-                            GtkSignalFunc   func,
-                            gpointer        func_data,
-                            GtkArg         *args)
+gtk_window_geometry_destroy (GtkWindowGeometryInfo *info)
+{
+  if (info->widget)
+    gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
+                                  GTK_SIGNAL_FUNC (gtk_widget_destroyed),
+                                  &info->widget);
+  g_free (info);
+}
+
+static GtkWindowGeometryInfo*
+gtk_window_get_geometry_info (GtkWindow *window,
+                             gboolean   create)
 {
-  GtkWindowSignal2 rfunc;
+  GtkWindowGeometryInfo *info;
+
+  info = gtk_object_get_data (GTK_OBJECT (window), "gtk-window-geometry");
+
+  if (!info && create)
+    {
+      info = g_new0 (GtkWindowGeometryInfo, 1);
+
+      info->width = 0;
+      info->height = 0;
+      info->last.width = -1;
+      info->last.height = -1;
+      info->widget = NULL;
+      info->mask = 0;
+
+      gtk_object_set_data_full (GTK_OBJECT (window), 
+                               "gtk-window-geometry",
+                               info, 
+                               (GtkDestroyNotify) gtk_window_geometry_destroy);
+    }
+
+  return info;
+}
+
+void       
+gtk_window_set_geometry_hints (GtkWindow       *window,
+                              GtkWidget       *geometry_widget,
+                              GdkGeometry     *geometry,
+                              GdkWindowHints   geom_mask)
+{
+  GtkWindowGeometryInfo *info;
+
+  g_return_if_fail (window != NULL);
+
+  info = gtk_window_get_geometry_info (window, TRUE);
+  
+  if (info->widget)
+    gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
+                                  GTK_SIGNAL_FUNC (gtk_widget_destroyed),
+                                  &info->widget);
+  
+  info->widget = geometry_widget;
+  if (info->widget)
+    gtk_signal_connect (GTK_OBJECT (geometry_widget), "destroy",
+                       GTK_SIGNAL_FUNC (gtk_widget_destroyed),
+                       &info->widget);
 
-  rfunc = (GtkWindowSignal2) func;
+  if (geometry)
+    info->geometry = *geometry;
 
-  (* rfunc) (object, GTK_VALUE_POINTER (args[0]), func_data);
+  info->mask = geom_mask;
+
+  gtk_widget_queue_resize (GTK_WIDGET (window));
 }
 
+void       
+gtk_window_set_default_size (GtkWindow   *window,
+                            gint         width,
+                            gint         height)
+{
+  GtkWindowGeometryInfo *info;
+
+  g_return_if_fail (GTK_IS_WINDOW (window));
+
+  info = gtk_window_get_geometry_info (window, TRUE);
+
+  if (width >= 0)
+    info->width = width;
+  if (height >= 0)
+    info->height = height;
+
+  gtk_widget_queue_resize (GTK_WIDGET (window));
+}
+  
 static void
 gtk_window_destroy (GtkObject *object)
 {
+  GtkWindow *window;
+  
   g_return_if_fail (object != NULL);
   g_return_if_fail (GTK_IS_WINDOW (object));
 
+  window = GTK_WINDOW (object);
+  
   gtk_container_unregister_toplevel (GTK_CONTAINER (object));
 
-  if (GTK_OBJECT_CLASS (parent_class)->destroy)
-    (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+  if (window->transient_parent)
+    gtk_window_unset_transient_for (window);
+
+  GTK_OBJECT_CLASS (parent_class)->destroy (object);
 }
 
 static void
@@ -505,6 +846,8 @@ gtk_window_finalize (GtkObject *object)
 
   window = GTK_WINDOW (object);
   g_free (window->title);
+  g_free (window->wmclass_name);
+  g_free (window->wmclass_class);
 
   GTK_OBJECT_CLASS(parent_class)->finalize (object);
 }
@@ -512,22 +855,71 @@ gtk_window_finalize (GtkObject *object)
 static void
 gtk_window_show (GtkWidget *widget)
 {
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_WINDOW (widget));
+  GtkWindow *window = GTK_WINDOW (widget);
+  GtkContainer *container = GTK_CONTAINER (window);
+  gboolean need_resize;
 
   GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
-  gtk_container_need_resize (GTK_CONTAINER (widget));
+
+  need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
+  container->need_resize = FALSE;
+
+  if (need_resize)
+    {
+      GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
+      GtkAllocation allocation = { 0, 0 };
+      GdkGeometry new_geometry;
+      guint width, height, new_flags;
+
+      /* determine default size to initially show the window with */
+      gtk_widget_size_request (widget, NULL);
+      gtk_window_compute_default_size (window, &width, &height);
+
+      /* save away the last default size for later comparisions */
+      info->last.width = width;
+      info->last.height = height;
+
+      /* constrain size to geometry */
+      gtk_window_compute_hints (window, &new_geometry, &new_flags);
+      gtk_window_constrain_size (window,
+                                &new_geometry, new_flags,
+                                width, height,
+                                &width, &height);
+
+      /* and allocate the window */
+      allocation.width  = width;
+      allocation.height = height;
+      gtk_widget_size_allocate (widget, &allocation);
+      
+      if (GTK_WIDGET_REALIZED (widget))
+       gdk_window_resize (widget->window, width, height);
+      else
+       gtk_widget_realize (widget);
+    }
+  
+  gtk_container_check_resize (container);
+
   gtk_widget_map (widget);
+
+  if (window->modal)
+    gtk_grab_add (widget);
 }
 
 static void
 gtk_window_hide (GtkWidget *widget)
 {
+  GtkWindow *window;
+
   g_return_if_fail (widget != NULL);
   g_return_if_fail (GTK_IS_WINDOW (widget));
 
+  window = GTK_WINDOW (widget);
+
   GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
   gtk_widget_unmap (widget);
+
+  if (window->modal)
+    gtk_grab_remove (widget);
 }
 
 static void
@@ -540,7 +932,6 @@ gtk_window_map (GtkWidget *widget)
 
   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
 
-  gtk_window_move_resize (widget);
   window = GTK_WINDOW (widget);
 
   if (window->bin.child &&
@@ -548,7 +939,6 @@ gtk_window_map (GtkWidget *widget)
       !GTK_WIDGET_MAPPED (window->bin.child))
     gtk_widget_map (window->bin.child);
 
-  gtk_window_set_hints (widget, &widget->requisition);
   gdk_window_show (widget->window);
 }
 
@@ -565,6 +955,8 @@ gtk_window_unmap (GtkWidget *widget)
 
   window = GTK_WINDOW (widget);
   window->use_uposition = TRUE;
+  window->resize_count = 0;
+  window->handling_resize = FALSE;
 }
 
 static void
@@ -573,13 +965,36 @@ gtk_window_realize (GtkWidget *widget)
   GtkWindow *window;
   GdkWindowAttr attributes;
   gint attributes_mask;
-
-  g_return_if_fail (widget != NULL);
+  
   g_return_if_fail (GTK_IS_WINDOW (widget));
 
-  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
   window = GTK_WINDOW (widget);
 
+  /* ensure widget tree is properly size allocated */
+  if (widget->allocation.x == -1 &&
+      widget->allocation.y == -1 &&
+      widget->allocation.width == 1 &&
+      widget->allocation.height == 1)
+    {
+      GtkRequisition requisition;
+      GtkAllocation allocation = { 0, 0, 200, 200 };
+
+      gtk_widget_size_request (widget, &requisition);
+      if (requisition.width || requisition.height)
+       {
+         /* non-empty window */
+         allocation.width = requisition.width;
+         allocation.height = requisition.height;
+       }
+      gtk_widget_size_allocate (widget, &allocation);
+      
+      gtk_container_queue_resize (GTK_CONTAINER (widget));
+
+      g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
+    }
+  
+  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+  
   switch (window->type)
     {
     case GTK_WINDOW_TOPLEVEL:
@@ -592,7 +1007,7 @@ gtk_window_realize (GtkWidget *widget)
       attributes.window_type = GDK_WINDOW_TEMP;
       break;
     }
-
+   
   attributes.title = window->title;
   attributes.wmclass_name = window->wmclass_name;
   attributes.wmclass_class = window->wmclass_class;
@@ -608,16 +1023,22 @@ gtk_window_realize (GtkWidget *widget)
                            GDK_LEAVE_NOTIFY_MASK |
                            GDK_FOCUS_CHANGE_MASK |
                            GDK_STRUCTURE_MASK);
-
+   
   attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
   attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
   attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
-
+   
   widget->window = gdk_window_new (NULL, &attributes, attributes_mask);
   gdk_window_set_user_data (widget->window, window);
 
   widget->style = gtk_style_attach (widget->style, widget->window);
   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+  gtk_window_paint (widget, NULL);
+
+  if (window->transient_parent &&
+      GTK_WIDGET_REALIZED (window->transient_parent))
+    gdk_window_set_transient_for (widget->window,
+                                 GTK_WIDGET (window->transient_parent)->window);
 }
 
 static void
@@ -625,27 +1046,26 @@ gtk_window_size_request (GtkWidget      *widget,
                         GtkRequisition *requisition)
 {
   GtkWindow *window;
+  GtkBin *bin;
 
   g_return_if_fail (widget != NULL);
   g_return_if_fail (GTK_IS_WINDOW (widget));
   g_return_if_fail (requisition != NULL);
 
   window = GTK_WINDOW (widget);
+  bin = GTK_BIN (window);
+  
+  requisition->width = GTK_CONTAINER (window)->border_width * 2;
+  requisition->height = GTK_CONTAINER (window)->border_width * 2;
 
-  if (window->bin.child)
+  if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
     {
-      requisition->width = GTK_CONTAINER (window)->border_width * 2;
-      requisition->height = GTK_CONTAINER (window)->border_width * 2;
+      GtkRequisition child_requisition;
+      
+      gtk_widget_size_request (bin->child, &child_requisition);
 
-      gtk_widget_size_request (window->bin.child, &window->bin.child->requisition);
-
-      requisition->width += window->bin.child->requisition.width;
-      requisition->height += window->bin.child->requisition.height;
-    }
-  else
-    {
-      if (!GTK_WIDGET_VISIBLE (window))
-       window->need_resize = TRUE;
+      requisition->width += child_requisition.width;
+      requisition->height += child_requisition.height;
     }
 }
 
@@ -667,76 +1087,64 @@ gtk_window_size_allocate (GtkWidget     *widget,
     {
       child_allocation.x = GTK_CONTAINER (window)->border_width;
       child_allocation.y = GTK_CONTAINER (window)->border_width;
-      child_allocation.width = allocation->width - child_allocation.x * 2;
-      child_allocation.height = allocation->height - child_allocation.y * 2;
+      child_allocation.width =
+       MAX (1, (gint)allocation->width - child_allocation.x * 2);
+      child_allocation.height =
+       MAX (1, (gint)allocation->height - child_allocation.y * 2);
 
       gtk_widget_size_allocate (window->bin.child, &child_allocation);
     }
 }
 
-static gint
-gtk_window_expose_event (GtkWidget      *widget,
-                        GdkEventExpose *event)
-{
-  g_return_val_if_fail (widget != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
-  g_return_val_if_fail (event != NULL, FALSE);
-
-  if (GTK_WIDGET_DRAWABLE (widget))
-    if (GTK_WIDGET_CLASS (parent_class)->expose_event)
-      return (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
-
-  return FALSE;
-}
-
 static gint
 gtk_window_configure_event (GtkWidget         *widget,
                            GdkEventConfigure *event)
 {
   GtkWindow *window;
-  GtkAllocation allocation;
-
+  
   g_return_val_if_fail (widget != NULL, FALSE);
   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
   g_return_val_if_fail (event != NULL, FALSE);
-
+  
   window = GTK_WINDOW (widget);
-  window->handling_resize = TRUE;
-
-  allocation.x = 0;
-  allocation.y = 0;
-  allocation.width = event->width;
-  allocation.height = event->height;
 
-  gtk_widget_size_allocate (widget, &allocation);
-
-  if (window->bin.child &&
-      GTK_WIDGET_VISIBLE (window->bin.child) &&
-      !GTK_WIDGET_MAPPED (window->bin.child))
-    gtk_widget_map (window->bin.child);
+  /* we got a configure event specifying the new window size and position,
+   * in principle we have to distinguish 4 cases here:
+   * 1) the size didn't change and resize_count == 0
+   *    -> the window was merely moved (sometimes not even that)
+   * 2) the size didn't change and resize_count > 0
+   *    -> we requested a new size, but didn't get it
+   * 3) the size changed and resize_count > 0
+   *    -> we asked for a new size and we got one
+   * 4) the size changed and resize_count == 0
+   *    -> we got resized from outside the toolkit, and have to
+   *    accept that size since we don't want to fight neither the
+   *    window manager nor the user
+   * in the three latter cases we have to reallocate the widget tree,
+   * which happens in gtk_window_move_resize(), so we set a flag for
+   * that function and assign the new size. if resize_count > 1,
+   * we simply do nothing and wait for more configure events.
+   */
 
-  if (window->resize_count > 1)
-    window->resize_count -= 1;
-  else
+  if (window->resize_count > 0 ||
+      widget->allocation.width != event->width ||
+      widget->allocation.height != event->height)
     {
-      if ((window->auto_shrink &&
-          ((event->width != widget->requisition.width) ||
-           (event->height != widget->requisition.height))) ||
-         (event->width < widget->requisition.width) ||
-         (event->height < widget->requisition.height))
+      if (window->resize_count > 0)
+       window->resize_count -= 1;
+
+      if (window->resize_count == 0)
        {
-         window->resize_count = 1;
-         gdk_window_resize (widget->window,
-                            widget->requisition.width,
-                            widget->requisition.height);
+         window->handling_resize = TRUE;
+         
+         widget->allocation.width = event->width;
+         widget->allocation.height = event->height;
+         
+         gtk_widget_queue_resize (widget);
        }
-      else
-       window->resize_count = 0;
     }
-  
-  window->handling_resize = FALSE;
-  
-  return FALSE;
+
+  return TRUE;
 }
 
 static gint
@@ -745,7 +1153,7 @@ gtk_window_key_press_event (GtkWidget   *widget,
 {
   GtkWindow *window;
   GtkDirectionType direction = 0;
-  gint return_val;
+  gboolean handled;
 
   g_return_val_if_fail (widget != NULL, FALSE);
   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
@@ -753,57 +1161,75 @@ gtk_window_key_press_event (GtkWidget   *widget,
 
   window = GTK_WINDOW (widget);
 
-  return_val = FALSE;
-  if (window->focus_widget)
-    return_val = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
-
-  if (!return_val && gtk_window_check_accelerator (window, event->keyval, event->state))
-    return_val = TRUE;
+  handled = FALSE;
+  
+  if (window->focus_widget &&
+      window->focus_widget != widget &&
+      GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
+    {
+      handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
+    }
+    
+  if (!handled)
+    handled = gtk_accel_groups_activate (GTK_OBJECT (window), event->keyval, event->state);
 
-  if (!return_val)
+  if (!handled)
     {
       switch (event->keyval)
        {
        case GDK_space:
          if (window->focus_widget)
            {
-             gtk_widget_activate (window->focus_widget);
-             return_val = TRUE;
+             if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
+               gtk_widget_activate (window->focus_widget);
+             handled = TRUE;
            }
          break;
        case GDK_Return:
        case GDK_KP_Enter:
-         if (window->default_widget)
+         if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
+             (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
            {
              gtk_widget_activate (window->default_widget);
-             return_val = TRUE;
+             handled = TRUE;
            }
           else if (window->focus_widget)
            {
-             gtk_widget_activate (window->focus_widget);
-             return_val = TRUE;
+             if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
+               gtk_widget_activate (window->focus_widget);
+             handled = TRUE;
            }
          break;
        case GDK_Up:
        case GDK_Down:
        case GDK_Left:
        case GDK_Right:
+       case GDK_KP_Up:
+       case GDK_KP_Down:
+       case GDK_KP_Left:
+       case GDK_KP_Right:
        case GDK_Tab:
+       case GDK_ISO_Left_Tab:
          switch (event->keyval)
            {
            case GDK_Up:
+           case GDK_KP_Up:
              direction = GTK_DIR_UP;
              break;
            case GDK_Down:
+           case GDK_KP_Down:
              direction = GTK_DIR_DOWN;
              break;
            case GDK_Left:
+           case GDK_KP_Left:
              direction = GTK_DIR_LEFT;
              break;
            case GDK_Right:
+           case GDK_KP_Right:
              direction = GTK_DIR_RIGHT;
              break;
            case GDK_Tab:
+           case GDK_ISO_Left_Tab:
              if (event->state & GDK_SHIFT_MASK)
                direction = GTK_DIR_TAB_BACKWARD;
              else
@@ -818,12 +1244,15 @@ gtk_window_key_press_event (GtkWidget   *widget,
          if (!GTK_CONTAINER (window)->focus_child)
            gtk_window_set_focus (GTK_WINDOW (widget), NULL);
          else
-           return_val = TRUE;
+           handled = TRUE;
          break;
        }
     }
 
-  return return_val;
+  if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
+    handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
+
+  return handled;
 }
 
 static gint
@@ -831,18 +1260,25 @@ gtk_window_key_release_event (GtkWidget   *widget,
                              GdkEventKey *event)
 {
   GtkWindow *window;
-  gint return_val;
-
+  gint handled;
+  
   g_return_val_if_fail (widget != NULL, FALSE);
   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
   g_return_val_if_fail (event != NULL, FALSE);
-
+  
   window = GTK_WINDOW (widget);
-  return_val = FALSE;
-  if (window->focus_widget)
-    return_val = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
+  handled = FALSE;
+  if (window->focus_widget &&
+      window->focus_widget != widget &&
+      GTK_WIDGET_SENSITIVE (window->focus_widget))
+    {
+      handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
+    }
 
-  return return_val;
+  if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
+    handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
+
+  return handled;
 }
 
 static gint
@@ -886,7 +1322,9 @@ gtk_window_focus_in_event (GtkWidget     *widget,
   if (GTK_WIDGET_VISIBLE (widget))
     {
       window = GTK_WINDOW (widget);
-      if (window->focus_widget && !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
+      if (window->focus_widget &&
+         window->focus_widget != widget &&
+         !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
        {
          fevent.type = GDK_FOCUS_CHANGE;
          fevent.window = window->focus_widget->window;
@@ -911,7 +1349,9 @@ gtk_window_focus_out_event (GtkWidget     *widget,
   g_return_val_if_fail (event != NULL, FALSE);
 
   window = GTK_WINDOW (widget);
-  if (window->focus_widget && GTK_WIDGET_HAS_FOCUS (window->focus_widget))
+  if (window->focus_widget &&
+      window->focus_widget != widget &&
+      GTK_WIDGET_HAS_FOCUS (window->focus_widget))
     {
       fevent.type = GDK_FOCUS_CHANGE;
       fevent.window = window->focus_widget->window;
@@ -923,408 +1363,768 @@ gtk_window_focus_out_event (GtkWidget     *widget,
   return FALSE;
 }
 
+static GdkAtom atom_rcfiles = GDK_NONE;
+
 static void
-gtk_window_style_set_event (GtkWidget *widget,
-                           GdkEventClient *event)
+gtk_window_read_rcfiles (GtkWidget *widget,
+                        GdkEventClient *event)
 {
-  GdkAtom atom_default_colors;
-  GtkStyle *style_newdefault;
-  GdkAtom realtype;
-  gint retfmt, retlen;
-  GdkColor *data, *stylecolors;
-  int i = 0;
-  GdkColormap *widget_cmap;
-  
-  atom_default_colors = gdk_atom_intern("_GTK_DEFAULT_COLORS", FALSE);
-  
-  if(gdk_property_get (GDK_ROOT_PARENT(),
-                      atom_default_colors,
-                      gdk_atom_intern("STRING", FALSE),
-                      0,
-                      sizeof(GdkColor) * GTK_STYLE_NUM_STYLECOLORS(),
-                      FALSE,
-                      &realtype,
-                      &retfmt,
-                      &retlen,
-                      (guchar **)&data) != TRUE) {
-    g_warning("gdk_property_get() failed in _GTK_STYLE_CHANGED handler\n");
-    return;
-  }
-  if(retfmt != sizeof(gushort)*8) {
-    g_warning("retfmt (%d) != sizeof(gushort)*8 (%d)\n", retfmt,
-       sizeof(gushort)*8);
-    return;
-  }
-  /* We have the color data, now let's interpret it */
-  style_newdefault = gtk_widget_get_default_style();
-  gtk_style_ref(style_newdefault);
-  stylecolors = (GdkColor *) style_newdefault;
-
-  widget_cmap = gtk_widget_get_colormap(widget);
-  for(i = 0; i < GTK_STYLE_NUM_STYLECOLORS(); i++) {
-    stylecolors[i] = data[i];
-    gdk_color_alloc(widget_cmap, &stylecolors[i]);
-  }
-
-  gtk_widget_set_default_style(style_newdefault);
-  gtk_style_unref(style_newdefault);
-
-  /* Now we need to redraw everything */
-  gtk_widget_draw(widget, NULL);
-  gtk_widget_draw_children(widget);
+  GList *embedded_windows;
+
+  embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
+  if (embedded_windows)
+    {
+      GdkEventClient sev;
+      int i;
+      
+      for(i = 0; i < 5; i++)
+       sev.data.l[i] = 0;
+      sev.data_format = 32;
+      sev.message_type = atom_rcfiles;
+      
+      while (embedded_windows)
+       {
+         guint xid = GPOINTER_TO_UINT (embedded_windows->data);
+         gdk_event_send_client_message ((GdkEvent *) &sev, xid);
+         embedded_windows = embedded_windows->next;
+       }
+    }
+
+  if (gtk_rc_reparse_all ())
+    {
+      /* If the above returned true, some of our RC files are out
+       * of date, so we need to reset all our widgets. Our other
+       * toplevel windows will also get the message, but by
+       * then, the RC file will up to date, so we have to tell
+       * them now.
+       */
+      GList *toplevels;
+      
+      toplevels = gtk_container_get_toplevels();
+      while (toplevels)
+       {
+         gtk_widget_reset_rc_styles (toplevels->data);
+         toplevels = toplevels->next;
+       }
+    }
 }
 
 static gint
 gtk_window_client_event (GtkWidget     *widget,
                         GdkEventClient *event)
 {
-  GdkAtom atom_styleset;
   g_return_val_if_fail (widget != NULL, FALSE);
   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
   g_return_val_if_fail (event != NULL, FALSE);
 
-  atom_styleset = gdk_atom_intern("_GTK_STYLE_CHANGED", FALSE);
+  if (!atom_rcfiles)
+    atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
+
+  if(event->message_type == atom_rcfiles) 
+    gtk_window_read_rcfiles (widget, event);    
 
-  if(event->message_type == atom_styleset) {
-    gtk_window_style_set_event(widget, event);    
-  }
   return FALSE;
 }
 
-static gint
-gtk_window_need_resize (GtkContainer *container)
+static void
+gtk_window_check_resize (GtkContainer *container)
 {
   GtkWindow *window;
-  gint return_val;
 
-  g_return_val_if_fail (container != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_WINDOW (container), FALSE);
-
-  return_val = FALSE;
+  g_return_if_fail (container != NULL);
+  g_return_if_fail (GTK_IS_WINDOW (container));
 
   window = GTK_WINDOW (container);
-  if (window->handling_resize)
-    return return_val;
 
   if (GTK_WIDGET_VISIBLE (container))
+    gtk_window_move_resize (window);
+}
+
+static void
+gtk_window_real_set_focus (GtkWindow *window,
+                          GtkWidget *focus)
+{
+  GdkEventFocus event;
+  gboolean def_flags = 0;
+
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GTK_IS_WINDOW (window));
+  
+  if (window->default_widget)
+    def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
+  
+  if (window->focus_widget)
     {
-      window->need_resize = TRUE;
-      return_val = gtk_window_move_resize (GTK_WIDGET (window));
-      window->need_resize = FALSE;
+      event.type = GDK_FOCUS_CHANGE;
+      event.window = window->focus_widget->window;
+      event.in = FALSE;
+      
+      if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
+         (window->focus_widget != window->default_widget))
+        {
+         GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
+         /* if any widget had the default set there should be
+            a default_widget, but might not so this is a sanity
+            check */
+         if (window->default_widget)
+           GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
+        }
+       
+      gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
     }
+  
+  window->focus_widget = focus;
+  
+  if (window->focus_widget)
+    {
+      event.type = GDK_FOCUS_CHANGE;
+      event.window = window->focus_widget->window;
+      event.in = TRUE;
 
-  return return_val;
+      if (window->default_widget)
+        {
+          if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
+             (window->focus_widget != window->default_widget))
+            {
+             if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
+               GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
+             GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
+            }
+         else
+           {
+             GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
+           }
+       }
+      
+      gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
+    }
+  else if (window->default_widget)
+    {
+      GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
+    }
+  
+  if (window->default_widget &&
+      (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
+    gtk_widget_queue_draw (window->default_widget);
 }
 
-static gint
-gtk_real_window_move_resize (GtkWindow *window,
-                            gint      *x,
-                            gint      *y,
-                            gint       width,
-                            gint       height)
+/*********************************
+ * Functions related to resizing *
+ *********************************/
+
+static void
+gtk_window_move_resize (GtkWindow *window)
 {
   GtkWidget *widget;
-  GtkWidget *resize_container, *child;
-  GSList *resize_containers;
-  GSList *tmp_list;
-  gint return_val;
-
-  g_return_val_if_fail (window != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
-  g_return_val_if_fail ((x != NULL) || (y != NULL), FALSE);
+  GtkContainer *container;
+  GtkWindowGeometryInfo *info;
+  GtkWindowLastGeometryInfo saved_last_info;
+  GdkGeometry new_geometry;
+  guint new_flags;
+  gint x, y;
+  gint width, height;
+  gint new_width, new_height;
+  gboolean default_size_changed = FALSE;
+  gboolean hints_changed = FALSE;
 
-  return_val = FALSE;
+  g_return_if_fail (GTK_IS_WINDOW (window));
+  g_return_if_fail (GTK_WIDGET_REALIZED (window));
 
   widget = GTK_WIDGET (window);
+  container = GTK_CONTAINER (widget);
+  info = gtk_window_get_geometry_info (window, TRUE);
+  saved_last_info = info->last;
 
-  if ((*x != -1) && (*y != -1))
-    gdk_window_move (widget->window, *x, *y);
+  gtk_widget_size_request (widget, NULL);
+  gtk_window_compute_default_size (window, &new_width, &new_height);
+  
+  if (info->last.width < 0 ||
+      info->last.width != new_width ||
+      info->last.height != new_height)
+    {
+      default_size_changed = TRUE;
+      info->last.width = new_width;
+      info->last.height = new_height;
 
-  if ((widget->requisition.width == 0) ||
-      (widget->requisition.height == 0))
+      /* We need to force a reposition in this case
+       */
+      if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
+       window->use_uposition = TRUE;
+    }
+  
+  /* Compute new set of hints for the window
+   */
+  gtk_window_compute_hints (window, &new_geometry, &new_flags);
+  if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
+                                &new_geometry, new_flags))
     {
-      widget->requisition.width = 200;
-      widget->requisition.height = 200;
+      hints_changed = TRUE;
+      info->last.geometry = new_geometry;
+      info->last.flags = new_flags;
     }
 
-  gdk_window_get_geometry (widget->window, NULL, NULL, &width, &height, NULL);
-
-  resize_containers = NULL;
-
-  if ((window->auto_shrink &&
-       ((width != widget->requisition.width) ||
-       (height != widget->requisition.height))) ||
-      (width < widget->requisition.width) ||
-      (height < widget->requisition.height))
+  /* From the default size and the allocation, figure out the size
+   * the window should be.
+   */
+  if (!default_size_changed ||
+      (!window->auto_shrink &&
+       new_width <= widget->allocation.width &&
+       new_height <= widget->allocation.height))
     {
-      if (window->resize_count == 0)
-       {
-         window->resize_count = 1;
-         gdk_window_resize (widget->window,
-                            widget->requisition.width,
-                            widget->requisition.height);
-       }
+      new_width = widget->allocation.width;
+      new_height = widget->allocation.height;
     }
-  else
-    {
-      /* The window hasn't changed size but one of its children
-       *  queued a resize request. Which means that the allocation
-       *  is not sufficient for the requisition of some child.
-       *  We've already performed a size request at this point,
-       *  so we simply need to run through the list of resize
-       *  widgets and reallocate their sizes appropriately. We
-       *  make the optimization of not performing reallocation
-       *  for a widget who also has a parent in the resize widgets
-       *  list. GTK_RESIZE_NEEDED is used for flagging those
-       *  parents inside this function.
-       */
-      GSList *resize_widgets, *node;
 
-      resize_widgets = GTK_CONTAINER (window)->resize_widgets;
-      GTK_CONTAINER (window)->resize_widgets = NULL;
+  /* constrain the window size to the specified geometry */
+  gtk_window_constrain_size (window,
+                            &new_geometry, new_flags,
+                            new_width, new_height,
+                            &new_width, &new_height);
 
-      for (node = resize_widgets; node; node = node->next)
-       {
-         child = (GtkWidget *)node->data;
-
-         GTK_PRIVATE_UNSET_FLAG (child, GTK_RESIZE_NEEDED);
+  /* compute new window position if a move is required
+   */
+  gtk_window_compute_reposition (window, new_width, new_height, &x, &y);
+  if (x != 1 && y != -1 && !(new_flags & GDK_HINT_POS))
+    {
+      new_flags |= GDK_HINT_POS;
+      hints_changed = TRUE;
+    }
 
-         widget = child->parent;
-         while (widget &&
-                ((widget->allocation.width < widget->requisition.width) ||
-                 (widget->allocation.height < widget->requisition.height)))
-           widget = widget->parent;
 
-         if (widget)
-           GTK_PRIVATE_SET_FLAG (widget, GTK_RESIZE_NEEDED);
-       }
+  /* handle actual resizing:
+   * - handle reallocations due to configure events
+   * - figure whether we need to request a new window size
+   * - handle simple resizes within our widget tree
+   * - reposition window if neccessary
+   */
+  width = widget->allocation.width;
+  height = widget->allocation.height;
 
-      for (node = resize_widgets; node; node = node->next)
+  if (window->handling_resize)
+    { 
+      GtkAllocation allocation;
+      
+      /* if we are just responding to a configure event, which
+       * might be due to a resize by the window manager, the
+       * user, or a response to a resizing request we made
+       * earlier, we go ahead, allocate the new size and we're done
+       * (see gtk_window_configure_event() for more details).
+       */
+      
+      window->handling_resize = FALSE;
+      
+      allocation = widget->allocation;
+      
+      gtk_widget_size_allocate (widget, &allocation);
+      gtk_widget_queue_draw (widget);
+
+#ifdef FIXME_ZVT_ME_HARDER
+      if ((default_size_changed || hints_changed) && (width != new_width || height != new_height))
        {
-         child = (GtkWidget *)node->data;
-
-         resize_container = child->parent;
-         while (resize_container &&
-                !GTK_WIDGET_RESIZE_NEEDED (resize_container))
-           resize_container = resize_container->parent;
-
-         if (resize_container)
-           widget = resize_container->parent;
-         else
-           widget = NULL;
-
-         while (widget)
-           {
-             if (GTK_WIDGET_RESIZE_NEEDED (widget))
-               {
-                 GTK_PRIVATE_UNSET_FLAG (resize_container, GTK_RESIZE_NEEDED);
-                 resize_container = widget;
-               }
-             widget = widget->parent;
-           }
-
-         if (resize_container &&
-             !g_slist_find (resize_containers, resize_container))
-           resize_containers = g_slist_prepend (resize_containers,
-                                                resize_container);
+         /* We could be here for two reasons
+          *  1) We coincidentally got a resize while handling
+          *     another resize.
+          *  2) Our computation of default_size_changed was completely
+          *     screwed up, probably because one of our children
+          *     is broken (i.e. changes requisition during
+          *     size allocation). It's probably a zvt widget.
+          *
+          * For 1), we could just go ahead and ask for the
+          * new size right now, but doing that for 2)
+          * might well be fighting the user (and can even
+          * trigger a loop). Since we really don't want to
+          * do that, we requeue a resize in hopes that
+          * by the time it gets handled, the child has seen
+          * the light and is willing to go along with the
+          * new size. (this happens for the zvt widget, since
+          * the size_allocate() above will have stored the
+          * requisition corresponding to the new size in the
+          * zvt widget)
+          *
+          * This doesn't buy us anything for 1), but it shouldn't
+          * hurt us too badly, since it is what would have
+          * happened if we had gotten the configure event before
+          * the new size had been set.
+          */
+         
+         if (x != -1 && y != -1)
+           gdk_window_move (widget->window, x, y);
+
+         /* we have to preserve the values and flags that are used
+          * for computation of default_size_changed and hints_changed
+          */
+
+         info->last = saved_last_info;
+         
+         gtk_widget_queue_resize (widget);
+
+         return;
        }
+#endif /* FIXME_ZVT_ME_HARDER */
+    }
 
-      g_slist_free (resize_widgets);
-
-      tmp_list = resize_containers;
-      while (tmp_list)
-       {
-         widget = tmp_list->data;
-         tmp_list = tmp_list->next;
-
-        GTK_PRIVATE_UNSET_FLAG (widget, GTK_RESIZE_NEEDED);
-         gtk_widget_size_allocate (widget, &widget->allocation);
-         gtk_widget_queue_draw (widget);
-       }
+  /* Now set hints if necessary
+   */
+  if (hints_changed)
+    gdk_window_set_geometry_hints (widget->window,
+                                  &new_geometry,
+                                  new_flags);
 
-      g_slist_free (resize_containers);
+  if ((default_size_changed || hints_changed) &&
+      (width != new_width || height != new_height))
+    {
+      /* given that (width != new_width || height != new_height), we are in one
+       * of the following situations:
+       * 
+       * default_size_changed
+       *   our requisition has changed and we need a different window size,
+       *   so we request it from the window manager.
+       *
+       * !default_size_changed
+       *   the window manager wouldn't assign us the size we requested, in this
+       *   case we don't try to request a new size with every resize.
+       *
+       * !default_size_changed && hints_changed
+       *   the window manager rejects our size, but we have just changed the
+       *   window manager hints, so there's a certain chance our request will
+       *   be honoured this time, so we try again.
+       */
+      
+      /* request a new window size */
+      if (x != -1 && y != -1)
+       gdk_window_move_resize (GTK_WIDGET (window)->window, x, y, new_width, new_height);
+      else
+       gdk_window_resize (GTK_WIDGET (window)->window, new_width, new_height);
+      window->resize_count += 1;
+      
+      /* we are now awaiting the new configure event in response to our
+       * resizing request. the configure event will cause a new resize
+       * with ->handling_resize=TRUE.
+       * until then, we want to
+       * - discard expose events
+       * - coalesce resizes for our children
+       * - defer any window resizes until the configure event arrived
+       * to achive this, we queue a resize for the window, but remove its
+       * resizing handler, so resizing will not be handled from the next
+       * idle handler but when the configure event arrives.
+       *
+       * FIXME: we should also dequeue the pending redraws here, since
+       * we handle those ourselves in ->handling_resize==TRUE.
+       */
+      gtk_widget_queue_resize (GTK_WIDGET (container));
+      if (container->resize_mode == GTK_RESIZE_QUEUE)
+       gtk_container_dequeue_resize_handler (container);
     }
+  else
+    {
+      if (x != -1 && y != -1)
+       gdk_window_move (widget->window, x, y);
 
-  return return_val;
+      if (container->resize_widgets)
+       gtk_container_resize_children (GTK_CONTAINER (window));
+    }
 }
 
-static gint
-gtk_window_move_resize (GtkWidget *widget)
+/* Compare two sets of Geometry hints for equality.
+ */
+static gboolean
+gtk_window_compare_hints (GdkGeometry *geometry_a,
+                         guint        flags_a,
+                         GdkGeometry *geometry_b,
+                         guint        flags_b)
 {
-  GtkWindow *window;
-  gint x, y;
-  gint width, height;
-  gint screen_width;
-  gint screen_height;
-  gint return_val;
-
-  g_return_val_if_fail (widget != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
+  if (flags_a != flags_b)
+    return FALSE;
+  
+  if ((flags_a & GDK_HINT_MIN_SIZE) &&
+      (geometry_a->min_width != geometry_b->min_width ||
+       geometry_a->min_height != geometry_b->min_height))
+    return FALSE;
+
+  if ((flags_a & GDK_HINT_MAX_SIZE) &&
+      (geometry_a->max_width != geometry_b->max_width ||
+       geometry_a->max_height != geometry_b->max_height))
+    return FALSE;
+
+  if ((flags_a & GDK_HINT_BASE_SIZE) &&
+      (geometry_a->base_width != geometry_b->base_width ||
+       geometry_a->base_height != geometry_b->base_height))
+    return FALSE;
+
+  if ((flags_a & GDK_HINT_ASPECT) &&
+      (geometry_a->min_aspect != geometry_b->min_aspect ||
+       geometry_a->max_aspect != geometry_b->max_aspect))
+    return FALSE;
+
+  if ((flags_a & GDK_HINT_RESIZE_INC) &&
+      (geometry_a->width_inc != geometry_b->width_inc ||
+       geometry_a->height_inc != geometry_b->height_inc))
+    return FALSE;
+
+  return TRUE;
+}
 
-  return_val = FALSE;
+/* Compute the default_size for a window. The result will
+ * be stored in *width and *height. The default size is
+ * the size the window should have when initially mapped.
+ * This routine does not attempt to constrain the size
+ * to obey the geometry hints - that must be done elsewhere.
+ */
+static void 
+gtk_window_compute_default_size (GtkWindow       *window,
+                                guint           *width,
+                                guint           *height)
+{
+  GtkRequisition requisition;
+  GtkWindowGeometryInfo *info;
+  
+  gtk_widget_get_child_requisition (GTK_WIDGET (window), &requisition);
+  *width = requisition.width;
+  *height = requisition.height;
 
-  if (GTK_WIDGET_REALIZED (widget))
+  info = gtk_window_get_geometry_info (window, FALSE);
+  
+  if (*width == 0 && *height == 0)
     {
-      window = GTK_WINDOW (widget);
-
-      /* Remember old size, to know if we have to reset hints */
-      width = widget->requisition.width;
-      height = widget->requisition.height;
-      gtk_widget_size_request (widget, &widget->requisition);
-
-      if (GTK_WIDGET_MAPPED (widget) &&
-         (width != widget->requisition.width ||
-          height != widget->requisition.height))
-       gtk_window_set_hints (widget, &widget->requisition);
-
-      x = -1;
-      y = -1;
-      width = widget->requisition.width;
-      height = widget->requisition.height;
-
-      if (window->use_uposition)
-       switch (window->position)
-         {
-         case GTK_WIN_POS_CENTER:
-           x = (gdk_screen_width () - width) / 2;
-           y = (gdk_screen_height () - height) / 2;
-           gtk_widget_set_uposition (widget, x, y);
-           break;
-         case GTK_WIN_POS_MOUSE:
-           gdk_window_get_pointer (NULL, &x, &y, NULL);
-
-           x -= width / 2;
-           y -= height / 2;
-
-           screen_width = gdk_screen_width ();
-           screen_height = gdk_screen_height ();
-
-           if (x < 0)
-             x = 0;
-           else if (x > (screen_width - width))
-             x = screen_width - width;
-
-           if (y < 0)
-             y = 0;
-           else if (y > (screen_height - height))
-             y = screen_height - height;
-
-           gtk_widget_set_uposition (widget, x, y);
-           break;
-         }
-
-      gtk_signal_emit (GTK_OBJECT (widget), window_signals[MOVE_RESIZE],
-                       &x, &y, width, height, &return_val);
+      /* empty window */
+      *width = 200;
+      *height = 200;
+    }
+  
+  if (info)
+    {
+      *width = info->width > 0 ? info->width : *width;
+      *height = info->height > 0 ? info->height : *height;
     }
-
-  return return_val;
 }
 
-static void
-gtk_real_window_set_focus (GtkWindow *window,
-                          GtkWidget *focus)
+/* Constrain a window size to obey the hints passed in geometry
+ * and flags. The result will be stored in *new_width and *new_height
+ *
+ * This routine is partially borrowed from fvwm.
+ *
+ * Copyright 1993, Robert Nation
+ *     You may use this code for any purpose, as long as the original
+ *     copyright remains in the source code and all documentation
+ *
+ * which in turn borrows parts of the algorithm from uwm
+ */
+static void 
+gtk_window_constrain_size (GtkWindow   *window,
+                          GdkGeometry *geometry,
+                          guint        flags,
+                          gint         width,
+                          gint         height,
+                          gint        *new_width,
+                          gint        *new_height)
 {
-  GdkEventFocus event;
+  gint min_width = 0;
+  gint min_height = 0;
+  gint base_width = 0;
+  gint base_height = 0;
+  gint xinc = 1;
+  gint yinc = 1;
+  gint max_width = G_MAXINT;
+  gint max_height = G_MAXINT;
+  
+#define FLOOR(value, base)     ( ((gint) ((value) / (base))) * (base) )
 
-  g_return_if_fail (window != NULL);
-  g_return_if_fail (GTK_IS_WINDOW (window));
+  if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
+    {
+      base_width = geometry->base_width;
+      base_height = geometry->base_height;
+      min_width = geometry->min_width;
+      min_height = geometry->min_height;
+    }
+  else if (flags & GDK_HINT_BASE_SIZE)
+    {
+      base_width = geometry->base_width;
+      base_height = geometry->base_height;
+      min_width = geometry->base_width;
+      min_height = geometry->base_height;
+    }
+  else if (flags & GDK_HINT_MIN_SIZE)
+    {
+      base_width = geometry->min_width;
+      base_height = geometry->min_height;
+      min_width = geometry->min_width;
+      min_height = geometry->min_height;
+    }
 
-  if (focus && !GTK_WIDGET_CAN_FOCUS (focus))
-    return;
+  if (flags & GDK_HINT_MAX_SIZE)
+    {
+      max_width = geometry->max_width ;
+      max_height = geometry->max_height;
+    }
 
-  if (window->focus_widget != focus)
+  if (flags & GDK_HINT_RESIZE_INC)
     {
-      if (window->focus_widget)
-       {
-         event.type = GDK_FOCUS_CHANGE;
-         event.window = window->focus_widget->window;
-         event.in = FALSE;
+      xinc = MAX (xinc, geometry->width_inc);
+      yinc = MAX (yinc, geometry->height_inc);
+    }
+  
+  /* clamp width and height to min and max values
+   */
+  width = CLAMP (width, min_width, max_width);
+  height = CLAMP (height, min_height, max_height);
+  
+  /* shrink to base + N * inc
+   */
+  width = base_width + FLOOR (width - base_width, xinc);
+  height = base_height + FLOOR (height - base_height, yinc);
+
+  /* constrain aspect ratio, according to:
+   *
+   *                width     
+   * min_aspect <= -------- <= max_aspect
+   *                height    
+   */
+  
+  if (flags & GDK_HINT_ASPECT &&
+      geometry->min_aspect > 0 &&
+      geometry->max_aspect > 0)
+    {
+      gint delta;
 
-         gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
+      if (geometry->min_aspect * height > width)
+       {
+         delta = FLOOR (height - width * geometry->min_aspect, yinc);
+         if (height - delta >= min_height)
+           height -= delta;
+         else
+           { 
+             delta = FLOOR (height * geometry->min_aspect - width, xinc);
+             if (width + delta <= max_width) 
+               width += delta;
+           }
        }
-
-      window->focus_widget = focus;
-
-      if (window->focus_widget)
+      
+      if (geometry->max_aspect * height < width)
        {
-         event.type = GDK_FOCUS_CHANGE;
-         event.window = window->focus_widget->window;
-         event.in = TRUE;
-
-         gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
+         delta = FLOOR (width - height * geometry->max_aspect, xinc);
+         if (width - delta >= min_width) 
+           width -= delta;
+         else
+           {
+             delta = FLOOR (width / geometry->max_aspect - height, yinc);
+             if (height + delta <= max_height)
+               height += delta;
+           }
        }
     }
+
+#undef FLOOR
+  
+  *new_width = width;
+  *new_height = height;
 }
 
+/* Compute the set of geometry hints and flags for a window
+ * based on the application set geometry, and requisiition
+ * of the window. gtk_widget_size_request() must have been
+ * called first.
+ */
 static void
-gtk_window_set_hints (GtkWidget      *widget,
-                     GtkRequisition *requisition)
+gtk_window_compute_hints (GtkWindow   *window,
+                         GdkGeometry *new_geometry,
+                         guint       *new_flags)
 {
-  GtkWindow *window;
+  GtkWidget *widget;
   GtkWidgetAuxInfo *aux_info;
-  gint flags;
   gint ux, uy;
+  gint extra_width = 0;
+  gint extra_height = 0;
+  GtkWindowGeometryInfo *geometry_info;
+  GtkRequisition requisition;
 
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_WINDOW (widget));
-  g_return_if_fail (requisition != NULL);
+  g_return_if_fail (GTK_IS_WINDOW (window));
 
-  if (GTK_WIDGET_REALIZED (widget))
+  widget = GTK_WIDGET (window);
+  
+  gtk_widget_get_child_requisition (widget, &requisition);
+  geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
+
+  g_return_if_fail (geometry_info != NULL);
+  
+  *new_flags = geometry_info->mask;
+  *new_geometry = geometry_info->geometry;
+  
+  if (geometry_info->widget)
     {
-      window = GTK_WINDOW (widget);
+      extra_width = widget->requisition.width - geometry_info->widget->requisition.width;
+      extra_height = widget->requisition.height - geometry_info->widget->requisition.height;
+    }
+  
+  ux = 0;
+  uy = 0;
+  
+  aux_info = gtk_object_get_data (GTK_OBJECT (widget), "gtk-aux-info");
+  if (aux_info && (aux_info->x != -1) && (aux_info->y != -1))
+    {
+      ux = aux_info->x;
+      uy = aux_info->y;
+      *new_flags |= GDK_HINT_POS;
+    }
+  
+  if (*new_flags & GDK_HINT_BASE_SIZE)
+    {
+      new_geometry->base_width += extra_width;
+      new_geometry->base_height += extra_height;
+    }
+  else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
+          (*new_flags & GDK_HINT_RESIZE_INC) &&
+          ((extra_width != 0) || (extra_height != 0)))
+    {
+      *new_flags |= GDK_HINT_BASE_SIZE;
+      
+      new_geometry->base_width = extra_width;
+      new_geometry->base_height = extra_height;
+    }
+  
+  if (*new_flags & GDK_HINT_MIN_SIZE)
+    {
+      new_geometry->min_width += extra_width;
+      new_geometry->min_height += extra_height;
+    }
+  else if (!window->allow_shrink)
+    {
+      *new_flags |= GDK_HINT_MIN_SIZE;
+      
+      new_geometry->min_width = requisition.width;
+      new_geometry->min_height = requisition.height;
+    }
+  
+  if (*new_flags & GDK_HINT_MAX_SIZE)
+    {
+      new_geometry->max_width += extra_width;
+      new_geometry->max_height += extra_height;
+    }
+  else if (!window->allow_grow)
+    {
+      *new_flags |= GDK_HINT_MAX_SIZE;
+      
+      new_geometry->max_width = requisition.width;
+      new_geometry->max_height = requisition.height;
+    }
+}
+
+/* Compute a new position for the window based on a new
+ * size. *x and *y will be set to the new coordinates, or to -1 if the
+ * window does not need to be moved
+ */
+static void 
+gtk_window_compute_reposition (GtkWindow  *window,
+                              gint        new_width,
+                              gint        new_height,
+                              gint       *x,
+                              gint       *y)
+{
+  GtkWidget *widget;
 
-      flags = 0;
-      ux = 0;
-      uy = 0;
+  widget = GTK_WIDGET (window);
 
-      aux_info = gtk_object_get_data (GTK_OBJECT (widget), "gtk-aux-info");
-      if (aux_info && (aux_info->x != -1) && (aux_info->y != -1))
+  *x = -1;
+  *y = -1;
+  
+  switch (window->position)
+    {
+    case GTK_WIN_POS_CENTER:
+    case GTK_WIN_POS_CENTER_ALWAYS:
+      if (window->use_uposition)
        {
-         ux = aux_info->x;
-         uy = aux_info->y;
-         flags |= GDK_HINT_POS;
+         gint screen_width = gdk_screen_width ();
+         gint screen_height = gdk_screen_height ();
+         
+         *x = (screen_width - new_width) / 2;
+         *y = (screen_height - new_height) / 2;
        }
-      if (!window->allow_shrink)
-       flags |= GDK_HINT_MIN_SIZE;
-      if (!window->allow_grow)
-       flags |= GDK_HINT_MAX_SIZE;
-
-      gdk_window_set_hints (widget->window, ux, uy,
-                           requisition->width, requisition->height,
-                           requisition->width, requisition->height,
-                           flags);
-
-      if (window->use_uposition && (flags & GDK_HINT_POS))
+      break;
+    case GTK_WIN_POS_MOUSE:
+      if (window->use_uposition)
        {
-         window->use_uposition = FALSE;
-         gdk_window_move (widget->window, ux, uy);
+         gint screen_width = gdk_screen_width ();
+         gint screen_height = gdk_screen_height ();
+         
+         gdk_window_get_pointer (NULL, x, y, NULL);
+         *x -= new_width / 2;
+         *y -= new_height / 2;
+         *x = CLAMP (*x, 0, screen_width - new_width);
+         *y = CLAMP (*y, 0, screen_height - new_height);
        }
+      break;
+    default:
+      if (window->use_uposition)
+       {
+         GtkWidgetAuxInfo *aux_info;
+         
+         aux_info = gtk_object_get_data (GTK_OBJECT (window), "gtk-aux-info");
+         if (aux_info &&
+             aux_info->x != -1 && aux_info->y != -1 &&
+             aux_info->x != -2 && aux_info->y != -2)
+           {
+             *x = aux_info->x;
+             *y = aux_info->y;
+           }
+       }
+      break;
+    }
+
+  if (*x != -1 && *y != -1)
+    {
+      GtkWidgetAuxInfo *aux_info;
+      
+      /* we handle necessary window positioning by hand here,
+       * so we can coalesce the window movement with possible
+       * resizes to get only one configure event.
+       * keep this in sync with gtk_widget_set_uposition()
+       * and gtk_window_reposition().
+       */
+      gtk_widget_set_uposition (widget, -1, -1); /* ensure we have aux_info */
+      
+      aux_info = gtk_object_get_data (GTK_OBJECT (widget), "gtk-aux-info");
+      aux_info->x = *x;
+      aux_info->y = *y;
+
+      window->use_uposition = FALSE;
     }
 }
 
-static gint
-gtk_window_check_accelerator (GtkWindow *window,
-                             gint       key,
-                             guint      mods)
+/***********************
+ * Redrawing functions *
+ ***********************/
+
+static void
+gtk_window_paint (GtkWidget     *widget,
+                 GdkRectangle *area)
 {
-  GtkAcceleratorTable *table;
-  GList *tmp;
+  gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL, 
+                     GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
+}
 
-  if ((key >= 0x20) && (key <= 0xFF))
-    {
-      tmp = window->accelerator_tables;
-      while (tmp)
-       {
-         table = tmp->data;
-         tmp = tmp->next;
+static gint
+gtk_window_expose (GtkWidget      *widget,
+                  GdkEventExpose *event)
+{
+  g_return_val_if_fail (widget != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
 
-         if (gtk_accelerator_table_check (table, key, mods))
-           return TRUE;
-       }
+  if (!GTK_WIDGET_APP_PAINTABLE (widget))
+    gtk_window_paint (widget, &event->area);
+  
+  if (GTK_WIDGET_CLASS (parent_class)->expose_event)
+    return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
 
-      if (gtk_accelerator_table_check (NULL, key, mods))
-       return TRUE;
-    }
+  return TRUE;
+}
 
-  return FALSE;
+static void
+gtk_window_draw (GtkWidget    *widget,
+                GdkRectangle *area)
+{
+  if (!GTK_WIDGET_APP_PAINTABLE (widget))
+    gtk_window_paint (widget, area);
+  
+  if (GTK_WIDGET_CLASS (parent_class)->draw)
+    (* GTK_WIDGET_CLASS (parent_class)->draw) (widget, area);
 }