diff --git a/gdk/x11/gdkscreen-x11.c b/gdk/x11/gdkscreen-x11.c
index 987bcfc..ce1fe77 100644
--- a/gdk/x11/gdkscreen-x11.c
+++ b/gdk/x11/gdkscreen-x11.c
@@ -241,9 +241,29 @@ gdk_screen_get_root_window (GdkScreen *screen)
 GdkColormap *
 gdk_screen_get_default_colormap (GdkScreen *screen)
 {
+  GdkScreenX11 *screen_x11;
+  GdkColormap *colormap;
+
   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
 
-  return GDK_SCREEN_X11 (screen)->default_colormap;
+  screen_x11 = GDK_SCREEN_X11 (screen);
+
+  if (!screen_x11->default_colormap)
+    {
+      if (!screen_x11->rgba_visual)
+        {
+          colormap = g_object_ref (gdk_screen_get_system_colormap (screen));
+        }
+      else
+        {
+          colormap = gdk_colormap_new (screen_x11->rgba_visual,
+                                       FALSE);
+        }
+
+      screen_x11->default_colormap = colormap;
+    }
+
+  return screen_x11->default_colormap;
 }
 
 /**
diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c
index 6e79ff8..72eb720 100644
--- a/gdk/x11/gdkwindow-x11.c
+++ b/gdk/x11/gdkwindow-x11.c
@@ -426,9 +426,6 @@ _gdk_windowing_window_init (GdkScreen * screen)
 
   g_assert (screen_x11->root_window == NULL);
 
-  gdk_screen_set_default_colormap (screen,
-				   gdk_screen_get_system_colormap (screen));
-
   screen_x11->root_window = g_object_new (GDK_TYPE_WINDOW, NULL);
 
   private = (GdkWindowObject *) screen_x11->root_window;
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 7114da8..7d0c5ef 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -396,7 +396,6 @@ gtk_private_h_sources =		\
 	gtktoolpaletteprivate.h	\
 	gtktreedatalist.h	\
 	gtktreeprivate.h	\
-	gtkwindow-decorate.h	\
 	$(gtk_clipboard_dnd_h_sources)
 
 # GTK+ C sources to build the library from
@@ -615,7 +614,6 @@ gtk_base_c_sources =            \
 	gtkvscrollbar.c		\
 	gtkvseparator.c		\
 	gtkwidget.c		\
-	gtkwindow-decorate.c    \
 	gtkwindow.c		\
 	$(gtk_clipboard_dnd_c_sources)
 
diff --git a/gtk/gtkplug.c b/gtk/gtkplug.c
index 4c31ea7..d499515 100644
--- a/gtk/gtkplug.c
+++ b/gtk/gtkplug.c
@@ -167,6 +167,7 @@ gtk_plug_class_init (GtkPlugClass *class)
 							GDK_TYPE_WINDOW,
 							GTK_PARAM_READABLE));
 
+
   /**
    * GtkPlug::embedded:
    * @plug: the object on which the signal was emitted
@@ -525,7 +526,9 @@ gtk_plug_new_for_display (GdkDisplay	  *display,
 {
   GtkPlug *plug;
 
-  plug = g_object_new (GTK_TYPE_PLUG, NULL);
+  plug = g_object_new (GTK_TYPE_PLUG,
+                       "disable-client-side-decorations", TRUE,
+                       NULL);
   gtk_plug_construct_for_display (plug, display, socket_id);
   return GTK_WIDGET (plug);
 }
diff --git a/gtk/gtkstyle.c b/gtk/gtkstyle.c
index c806aee..c4be5bb 100644
--- a/gtk/gtkstyle.c
+++ b/gtk/gtkstyle.c
@@ -26,6 +26,7 @@
 
 #include "config.h"
 #include <math.h>
+#include <pixman.h>
 #include <stdlib.h>
 #include <string.h>
 #include <gobject/gvaluecollector.h>
@@ -3467,6 +3468,337 @@ option_menu_get_props (GtkWidget      *widget,
     *indicator_spacing = default_option_indicator_spacing;
 }
 
+/* gaussian blur kernel */
+pixman_fixed_t *
+create_blur_kernel (gint     radius,
+                    gint    *length)
+{
+  const gdouble   radiusf = fabs (radius) + 1.0f;
+  const gdouble   sigma = sqrt (-(radiusf * radiusf) / (2.0f * log (1.0f / 255.0f)));
+  const gdouble   scale2 = 2.0f * sigma * sigma;
+  const gdouble   scale1 = 1.0f / (G_PI * scale2);
+  const gint      size = 2 * radius + 1;
+  const gint      n_params = size * size;
+  pixman_fixed_t *params;
+  gdouble        *tmp;
+  gdouble         sum;
+  gint            x;
+  gint            y;
+  gint            i;
+
+  tmp = g_newa (double, n_params);
+
+  for (i = 0, sum = 0, x = -radius; x <= radius; ++x)
+    {
+      for (y = -radius; y <= radius; ++y, ++i)
+        {
+          const gdouble u = x * x;
+          const gdouble v = y * y;
+
+          tmp[i] = scale1 * exp (-(u + v) / scale2);
+
+          sum += tmp[i];
+        }
+    }
+
+  params = g_new (pixman_fixed_t, n_params + 2);
+
+  params[0] = pixman_int_to_fixed (size);
+  params[1] = pixman_int_to_fixed (size);
+
+  for (i = 0; i < n_params; ++i)
+    params[2 + i] = pixman_double_to_fixed (tmp[i] / sum);
+
+  if (length)
+    *length = n_params + 2;
+
+  return params;
+}
+
+static void
+blur_image_surface (cairo_surface_t *surface,
+                    gint             radius)
+{
+  cairo_format_t  format;
+  pixman_fixed_t *params = NULL;
+  gint            n_params;
+  pixman_image_t *src;
+  gint            w;
+  gint            h;
+  gint            s;
+  gpointer        p;
+
+  if (radius == 0 ||
+      cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS ||
+      cairo_surface_get_type (surface) != CAIRO_SURFACE_TYPE_IMAGE)
+    {
+      return;
+    }
+
+  format = cairo_image_surface_get_format (surface);
+  if (format != CAIRO_FORMAT_A8    &&
+      format != CAIRO_FORMAT_RGB24 &&
+      format != CAIRO_FORMAT_ARGB32)
+    {
+      return;
+    }
+
+  cairo_surface_flush (surface);
+
+  w = cairo_image_surface_get_width (surface);
+  h = cairo_image_surface_get_height (surface);
+  s = cairo_image_surface_get_stride (surface);
+
+  p = cairo_image_surface_get_data (surface);
+  src = pixman_image_create_bits (PIXMAN_a8r8g8b8, w, h, p, s);
+
+  params = create_blur_kernel (radius, &n_params);
+  pixman_image_set_filter (src,
+                           PIXMAN_FILTER_CONVOLUTION,
+                           params,
+                           n_params);
+  g_free (params);
+
+  pixman_image_composite (PIXMAN_OP_SRC,
+                          src,
+                          NULL,
+                          src,
+                          0, 0,
+                          0, 0,
+                          0, 0,
+                          w, h);
+
+  pixman_image_unref (src);
+
+  cairo_surface_mark_dirty (surface);
+}
+
+typedef struct _TileData
+{
+  guchar *data;
+  cairo_format_t format;
+  gint width;
+  gint height;
+  gint stride;
+} TileData;
+
+/* XXX - leak */
+static TileData *tile = NULL;
+
+static void
+paint_window_shadow (cairo_t *cr,
+                     gint     width,
+                     gint     height,
+                     gint     shadow_radius,
+                     gint     corner_radius)
+{
+  cairo_surface_t *tmp_surface = NULL;
+  cairo_surface_t *new_surface = NULL;
+  cairo_pattern_t *pattern     = NULL;
+  cairo_t         *cr_surf     = NULL;
+  cairo_matrix_t   matrix;
+
+  if (!tile)
+    {
+      guchar *data;
+
+      tmp_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+                                                4 * shadow_radius,
+                                                4 * shadow_radius);
+      if (cairo_surface_status (tmp_surface) != CAIRO_STATUS_SUCCESS)
+        return;
+
+      cr_surf = cairo_create (tmp_surface);
+      if (cairo_status (cr_surf) != CAIRO_STATUS_SUCCESS)
+        {
+          cairo_surface_destroy (tmp_surface);
+          return;
+        }
+
+      cairo_scale (cr_surf, 1.0f, 1.0f);
+      cairo_set_operator (cr_surf, CAIRO_OPERATOR_CLEAR);
+      cairo_paint (cr_surf);
+      cairo_set_operator (cr_surf, CAIRO_OPERATOR_OVER);
+      cairo_set_source_rgba (cr_surf, 0.0f, 0.0f, 0.0f, 0.75f);
+      cairo_arc (cr_surf,
+                 2 * shadow_radius,
+                 2 * shadow_radius,
+                 2.0f * corner_radius,
+                 0.0f,
+                 360.0f * (G_PI / 180.f));
+      cairo_fill (cr_surf);
+      cairo_destroy (cr_surf);
+
+      blur_image_surface (tmp_surface, shadow_radius);
+
+      tile = g_new0 (TileData, 1);
+      tile->format = cairo_image_surface_get_format (tmp_surface);
+      tile->width = cairo_image_surface_get_width (tmp_surface) / 2;
+      tile->height = cairo_image_surface_get_height (tmp_surface) / 2;
+      tile->stride = cairo_image_surface_get_stride (tmp_surface);
+
+      data = cairo_image_surface_get_data (tmp_surface);
+
+      tile->data = g_malloc (tile->height * tile->stride);
+      memcpy (tile->data, data, tile->height * tile->stride);
+    }
+
+  new_surface = cairo_image_surface_create_for_data (tile->data,
+                                                     tile->format,
+                                                     tile->width,
+                                                     tile->height,
+                                                     tile->stride);
+
+  pattern = cairo_pattern_create_for_surface (new_surface);
+  if (cairo_pattern_status (pattern) != CAIRO_STATUS_SUCCESS)
+    {
+      cairo_surface_destroy (tmp_surface);
+      cairo_surface_destroy (new_surface);
+      return;
+    }
+
+  /* top left */
+  cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
+  cairo_set_source (cr, pattern);
+  cairo_rectangle (cr,
+                   0.0f,
+                   0.0f,
+                   width - 2 * shadow_radius,
+                   2 * shadow_radius);
+  cairo_fill (cr);
+
+  /* bottom left */
+  cairo_matrix_init_scale (&matrix, 1.0f, -1.0f);
+  cairo_matrix_translate (&matrix, 0.0f, -height);
+  cairo_pattern_set_matrix (pattern, &matrix);
+  cairo_rectangle (cr,
+                   0.0f,
+                   2 * shadow_radius,
+                   2 * shadow_radius,
+                   height - 2 * shadow_radius);
+  cairo_fill (cr);
+
+  /* top right */
+  cairo_matrix_init_scale (&matrix, -1.0f, 1.0f);
+  cairo_matrix_translate (&matrix, -width, 0.0f);
+  cairo_pattern_set_matrix (pattern, &matrix);
+  cairo_rectangle (cr,
+                   width - 2 * shadow_radius,
+                   0.0f,
+                   2 * shadow_radius,
+                   height - 2 * shadow_radius);
+  cairo_fill (cr);
+
+  /* bottom right */
+  cairo_matrix_init_scale (&matrix, -1.0f, -1.0f);
+  cairo_matrix_translate (&matrix, -width, -height);
+  cairo_pattern_set_matrix (pattern, &matrix);
+  cairo_rectangle (cr,
+                   2 * shadow_radius,
+                   height - 2 * shadow_radius,
+                   width - 2 * shadow_radius,
+                   2 * shadow_radius);
+  cairo_fill (cr);
+
+
+  cairo_pattern_destroy (pattern);
+  cairo_surface_destroy (tmp_surface);
+  cairo_surface_destroy (new_surface);
+}
+
+static void
+paint_decorated_window (GtkStyle *style,
+                        GdkWindow *window,
+                        GtkStateType state_type,
+                        GtkShadowType shadow_type,
+                        const GdkRectangle *area,
+                        GtkWidget *widget,
+                        const gchar *detail,
+                        gint x,
+                        gint y,
+                        gint width,
+                        gint height)
+{
+  cairo_pattern_t *gradient;
+  cairo_t *cr;
+  const double hmargin = 2.5 + x;
+  const double vmargin = 2.5 + y;
+  const double radius = 5;
+  GdkColor *color;
+  GdkWindowState state;
+
+  if (width == -1)
+    width = widget->allocation.width - 2 * x;
+  if (height == -1)
+    height = widget->allocation.height - 2 * y;
+
+  state = gdk_window_get_state (window);
+
+  cr = gdk_cairo_create (window);
+  cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
+  cairo_paint (cr);
+
+  cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+
+  if (state & GDK_WINDOW_STATE_MAXIMIZED)
+    {
+      cairo_rectangle (cr,
+                       0, 0,
+                       width, height);
+    }
+  else
+    {
+      paint_window_shadow (cr,
+                           width,
+                           height,
+                           x / 2 + 2.5,
+                           radius);
+
+      cairo_move_to (cr, hmargin, vmargin + radius);
+
+      cairo_arc (cr, hmargin + radius, vmargin + radius,
+                 radius, M_PI, 3 * M_PI / 2);
+      cairo_line_to (cr, width - hmargin - radius, vmargin);
+      cairo_arc (cr, width - hmargin - radius, vmargin + radius,
+                 radius, 3 * M_PI / 2, 2 * M_PI);
+      cairo_line_to (cr, width - hmargin, height - vmargin - radius);
+      cairo_arc (cr, width - hmargin - radius, height - vmargin - radius,
+                 radius, 0, M_PI / 2);
+      cairo_line_to (cr, hmargin + radius, height - vmargin);
+      cairo_arc (cr, hmargin + radius, height - vmargin - radius,
+                 radius, M_PI / 2, M_PI);
+      cairo_close_path (cr);
+    }
+
+  cairo_close_path (cr);
+
+  gradient = cairo_pattern_create_linear (width / 2 - 1, vmargin,
+                                          width / 2 + 1, height);
+  if (GTK_IS_WINDOW (widget) &&
+      gtk_window_has_toplevel_focus (GTK_WINDOW (widget)) &&
+      gtk_window_is_active (GTK_WINDOW (widget)))
+    color = &style->bg[GTK_STATE_SELECTED];
+  else
+    color = &style->bg[GTK_STATE_NORMAL];
+  cairo_pattern_add_color_stop_rgba (gradient, 0,
+				     color->red / 65535.,
+				     color->green / 65535.,
+				     color->blue / 65535., 0.9);
+  cairo_pattern_add_color_stop_rgba (gradient, 0.8,
+				     color->red / 65535.,
+				     color->green / 65535.,
+				     color->blue / 65535., 1.0);
+  cairo_set_source (cr, gradient);
+  cairo_fill_preserve (cr);
+
+  gdk_cairo_set_source_color (cr, &style->fg[state_type]);
+  cairo_set_line_width (cr, 1);
+  cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
+  cairo_stroke (cr);
+
+  cairo_destroy (cr);
+}
+
 static void 
 gtk_default_draw_box (GtkStyle      *style,
 		      GdkWindow     *window,
@@ -3565,8 +3897,16 @@ gtk_default_draw_box (GtkStyle      *style,
       return;
     }
 
-  gtk_paint_shadow (style, window, state_type, shadow_type, area, widget, detail,
-                    x, y, width, height);
+  if (strcmp (detail, "decoration") == 0)
+    {
+      paint_decorated_window (style, window, state_type, shadow_type,
+                              area, widget, detail, x, y, width, height);
+    }
+  else
+    {
+      gtk_paint_shadow (style, window, state_type, shadow_type,
+                        area, widget, detail, x, y, width, height);
+    }
 
   if (detail && strcmp (detail, "optionmenu") == 0)
     {
diff --git a/gtk/gtkwindow-decorate.c b/gtk/gtkwindow-decorate.c
deleted file mode 100644
index 5ff0612..0000000
--- a/gtk/gtkwindow-decorate.c
+++ /dev/null
@@ -1,836 +0,0 @@
-/* GTK - The GIMP Toolkit
- * Copyright (C) 2001 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/* 
- * Authors: Alexander Larsson <alexl@redhat.com>
- */
-
-#include "config.h"
-#include "gtkprivate.h"
-#include "gtkwindow.h"
-#include "gtkmain.h"
-#include "gtkwindow-decorate.h"
-#include "gtkintl.h"
-#include "gtkalias.h"
-
-
-#ifdef DECORATE_WINDOWS
-
-typedef enum
-{
-  GTK_WINDOW_REGION_TITLE,
-  GTK_WINDOW_REGION_MAXIMIZE,
-  GTK_WINDOW_REGION_CLOSE,
-  GTK_WINDOW_REGION_BR_RESIZE
-} GtkWindowRegionType;
-
-typedef struct _GtkWindowRegion GtkWindowRegion;
-typedef struct _GtkWindowDecoration GtkWindowDecoration;
-
-struct _GtkWindowRegion
-{
-  GdkRectangle rect;
-  GtkWindowRegionType type;
-};
-
-typedef enum
-{
-  RESIZE_TOP_LEFT,
-  RESIZE_TOP,
-  RESIZE_TOP_RIGHT,
-  RESIZE_RIGHT,
-  RESIZE_BOTTOM_RIGHT,
-  RESIZE_BOTTOM,
-  RESIZE_BOTTOM_LEFT,
-  RESIZE_LEFT,
-  RESIZE_NONE,
-} GtkWindowResizeType;
-
-struct _GtkWindowDecoration
-{
-  gint n_regions;
-  GtkWindowRegion *regions;
-
-  gint last_x, last_y;
-  gint last_w, last_h;
-  
-  PangoLayout *title_layout;
-
-  GtkWindowResizeType resize;
-  
-  guint moving : 1;
-  guint closing : 1;
-  guint maximizing : 1;
-  guint maximized : 1;
-  guint maximizable : 1;
-  guint decorated : 1;
-  guint real_inner_move : 1;
-  guint focused : 1;
-};
-
-#define DECORATION_BORDER_TOP 15
-#define DECORATION_BORDER_LEFT 3
-#define DECORATION_BORDER_RIGHT 3
-#define DECORATION_BORDER_BOTTOM 3
-#define DECORATION_BORDER_TOT_X (DECORATION_BORDER_LEFT + DECORATION_BORDER_RIGHT)
-#define DECORATION_BORDER_TOT_Y (DECORATION_BORDER_TOP + DECORATION_BORDER_BOTTOM)
-#define DECORATION_BUTTON_SIZE 9
-#define DECORATION_BUTTON_Y_OFFSET 2
-#define DECORATION_TITLE_FONT "Sans 9"
-
-static void gtk_decorated_window_recalculate_regions      (GtkWindow      *window);
-static GtkWindowRegionType gtk_decorated_window_region_type    (GtkWindow      *window,
-						 gint            x,
-						 gint            y);
-static gint gtk_decorated_window_frame_event    (GtkWindow *window,
-						 GdkEvent *event);
-static gint gtk_decorated_window_button_press   (GtkWidget      *widget,
-						 GdkEventButton *event);
-static gint gtk_decorated_window_button_release (GtkWidget      *widget,
-						 GdkEventButton *event);
-static gint gtk_decorated_window_motion_notify  (GtkWidget      *widget,
-						 GdkEventMotion *event);
-static gint gtk_decorated_window_window_state   (GtkWidget           *widget,
-						 GdkEventWindowState *event);
-static void gtk_decorated_window_paint          (GtkWidget      *widget,
-						 GdkRectangle   *area);
-static gint gtk_decorated_window_focus_change   (GtkWidget         *widget,
-						 GdkEventFocus     *event);
-static void gtk_decorated_window_realize        (GtkWindow   *window);
-static void gtk_decorated_window_unrealize      (GtkWindow   *window);
-
-static void
-gtk_decoration_free (GtkWindowDecoration *deco)
-{
-  g_free (deco->regions);
-  deco->regions = NULL;
-  deco->n_regions = 0;
-
-  g_free (deco);
-}
-
-void
-gtk_decorated_window_init (GtkWindow   *window)
-{
-  GtkWindowDecoration *deco;
-
-  deco = g_new (GtkWindowDecoration, 1);
-
-  deco->n_regions = 0;
-  deco->regions = NULL;
-  deco->title_layout = NULL;
-  deco->resize = RESIZE_NONE;
-  deco->moving = FALSE;
-  deco->decorated = TRUE;
-  deco->closing = FALSE;
-  deco->maximizing = FALSE;
-  deco->maximized = FALSE;
-  deco->maximizable = FALSE;
-  deco->real_inner_move = FALSE;
- 
-  g_object_set_data_full (G_OBJECT (window), I_("gtk-window-decoration"), deco,
-			  (GDestroyNotify) gtk_decoration_free);
-  
-  gtk_window_set_has_frame (window, TRUE);
-
-  g_signal_connect (window,
-		    "frame-event",
-		    G_CALLBACK (gtk_decorated_window_frame_event),
-		    window);
-  g_signal_connect (window,
-		    "focus-in-event",
-		    G_CALLBACK (gtk_decorated_window_focus_change),
-		    window);
-  g_signal_connect (window,
-		    "focus-out-event",
-		    G_CALLBACK (gtk_decorated_window_focus_change),
-		    window);
-  g_signal_connect (window,
-		    "realize",
-		    G_CALLBACK (gtk_decorated_window_realize),
-		    window);
-  g_signal_connect (window,
-		    "unrealize",
-		    G_CALLBACK (gtk_decorated_window_unrealize),
-		    window);
-}
-
-static inline GtkWindowDecoration *
-get_decoration (GtkWindow *window)
-{
-  return (GtkWindowDecoration *)g_object_get_data (G_OBJECT (window), "gtk-window-decoration");
-}
-
-void
-gtk_decorated_window_set_title (GtkWindow   *window,
-				const gchar *title)
-{
-  GtkWindowDecoration *deco = get_decoration (window);
-  
-  if (deco->title_layout)
-    pango_layout_set_text (deco->title_layout, title, -1);
-}
-
-void 
-gtk_decorated_window_calculate_frame_size (GtkWindow *window)
-{
-  GdkWMDecoration decorations;
-  GtkWindowDecoration *deco = get_decoration (window);
-  
-  if (gdk_window_get_decorations (GTK_WIDGET (window)->window,
-				  &decorations))
-    {
-      if ((decorations & GDK_DECOR_BORDER) &&
-	  (decorations & GDK_DECOR_TITLE))
-	{
-	  deco->decorated = TRUE;
-	  if ((decorations & GDK_DECOR_MAXIMIZE) &&
-	      (gtk_window_get_type_hint (window) == GDK_WINDOW_TYPE_HINT_NORMAL))
-	    deco->maximizable = TRUE;
-	}
-      else
-	deco->decorated = FALSE;
-    }
-  else
-    {
-      deco->decorated = (window->type != GTK_WINDOW_POPUP);
-      deco->maximizable = (gtk_window_get_type_hint (window) == GDK_WINDOW_TYPE_HINT_NORMAL);
-    }
-
-  if (deco->decorated)
-    gtk_window_set_frame_dimensions (window,
-				     DECORATION_BORDER_LEFT,
-				     DECORATION_BORDER_TOP,
-				     DECORATION_BORDER_RIGHT,
-				     DECORATION_BORDER_BOTTOM);
-  else
-    gtk_window_set_frame_dimensions (window, 0, 0, 0, 0);
-
-  gtk_decorated_window_recalculate_regions (window);
-}
-
-static gboolean
-gtk_decorated_window_inner_change (GdkWindow *win,
-				   gint x, gint y,
-				   gint width, gint height,
-				   gpointer user_data)
-{
-  GtkWindow *window = (GtkWindow *)user_data;
-  GtkWidget *widget = GTK_WIDGET (window);
-  GtkWindowDecoration *deco = get_decoration (window);
-
-  if (deco->real_inner_move)
-    {
-      deco->real_inner_move = FALSE;
-      return FALSE;
-    }
-
-  deco->real_inner_move = TRUE;
-  gdk_window_move_resize (widget->window,
-			  window->frame_left, window->frame_top,
-			  width, height);
-
-  gdk_window_move_resize (window->frame,
-			  x - window->frame_left, y - window->frame_top,
-			  width + window->frame_left + window->frame_right,
-			  height + window->frame_top + window->frame_bottom);
-  return TRUE;
-}
-
-static void
-gtk_decorated_window_inner_get_pos (GdkWindow *win,
-				    gint *x, gint *y,
-				    gpointer user_data)
-{
-  GtkWindow *window = (GtkWindow *)user_data;
-
-  gdk_window_get_position (window->frame, x, y);
-  
-  *x += window->frame_left;
-  *y += window->frame_top;
-}
-
-static void
-gtk_decorated_window_realize (GtkWindow   *window)
-{
-  GtkWindowDecoration *deco = get_decoration (window);
-  GtkWidget *widget = GTK_WIDGET (window);
-  PangoFontDescription *font_desc;
-
-  deco->title_layout = gtk_widget_create_pango_layout (widget,
-						       (window->title)?window->title:"");
-
-  font_desc = pango_font_description_from_string(DECORATION_TITLE_FONT);
-  pango_layout_set_font_description (deco->title_layout, font_desc);
-  pango_font_description_free (font_desc);
-
-#if 0
-  /* What is this code exactly doing? I remember we were using the
-     decorated windows with the DirectFB port and it did just work,
-     and there was definitely no code in linux-fb involved. */
-  gdk_fb_window_set_child_handler (window->frame,
-				   gtk_decorated_window_inner_change,
-				   gtk_decorated_window_inner_get_pos,
-				   window);
-
-  /* This is a huge hack to make frames have the same shape as
-     the window they wrap */
-  gdk_window_shape_combine_mask (window->frame, GDK_FB_USE_CHILD_SHAPE, 0, 0);
-#endif
-}
-
-
-static void
-gtk_decorated_window_unrealize (GtkWindow   *window)
-{
-  GtkWindowDecoration *deco = get_decoration (window);
-
-  if (deco->title_layout)
-    {
-      g_object_unref (deco->title_layout);
-      deco->title_layout = NULL;
-    }
-}
-
-static gint
-gtk_decorated_window_frame_event (GtkWindow *window, GdkEvent *event)
-{
-  GtkWindowDecoration *deco = get_decoration (window);
-  GtkWidget *widget = GTK_WIDGET (window);
-  GdkEventExpose *expose_event;
-
-  switch (event->type)
-    {
-    case GDK_EXPOSE:
-      expose_event = (GdkEventExpose *)event;
-      if (deco->decorated)
-	gtk_decorated_window_paint (widget, &expose_event->area);
-      return TRUE;
-      break;
-    case GDK_CONFIGURE:
-      gtk_decorated_window_recalculate_regions (window);
-      break;
-    case GDK_MOTION_NOTIFY:
-      return gtk_decorated_window_motion_notify (widget, (GdkEventMotion *)event);
-      break;
-    case GDK_BUTTON_PRESS:
-      return gtk_decorated_window_button_press (widget, (GdkEventButton *)event);
-      break;
-    case GDK_BUTTON_RELEASE:
-      return gtk_decorated_window_button_release (widget, (GdkEventButton *)event);
-    case GDK_WINDOW_STATE:
-      return gtk_decorated_window_window_state (widget, (GdkEventWindowState *)event);
-    default:
-      break;
-    }
-  return FALSE;
-}
-
-static gint
-gtk_decorated_window_focus_change (GtkWidget         *widget,
-				   GdkEventFocus     *event)
-{
-  GtkWindow *window = GTK_WINDOW(widget);
-  GtkWindowDecoration *deco = get_decoration (window);
-  deco->focused = event->in;
-  gdk_window_invalidate_rect (window->frame, NULL, FALSE);
-  return FALSE;
-}
-
-static gint
-gtk_decorated_window_motion_notify (GtkWidget       *widget,
-				    GdkEventMotion  *event)
-{
-  GtkWindow *window;
-  GtkWindowDecoration *deco;
-  GdkModifierType mask;
-  GdkWindow *win;
-  gint x, y;
-  gint win_x, win_y, win_w, win_h;
-  
-  window = GTK_WINDOW (widget);
-  deco = get_decoration (window);
-  
-  if (!deco->decorated)
-    return TRUE;
-  
-  win = widget->window;
-  gdk_window_get_pointer (window->frame, &x, &y, &mask);
-  
-  gdk_window_get_position (window->frame, &win_x, &win_y);
-  win_x += DECORATION_BORDER_LEFT;
-  win_y += DECORATION_BORDER_TOP;
-  
-  gdk_window_get_geometry (win, NULL, NULL, &win_w, &win_h, NULL);
-
-  if (deco->moving)
-    {
-      int dx, dy;
-      dx = x - deco->last_x;
-      dy = y - deco->last_y;
-
-      _gtk_window_reposition (window, win_x + dx, win_y + dy);
-    }
-
-  if (deco->resize != RESIZE_NONE)
-    {
-      int w, h;
-      
-      w = win_w;
-      h = win_h;
-      
-      switch(deco->resize) {
-      case RESIZE_BOTTOM_RIGHT:
-	w = x - DECORATION_BORDER_TOT_X;
-	h = y - DECORATION_BORDER_TOT_Y;
-	break;
-      case RESIZE_RIGHT:
-	w = x - DECORATION_BORDER_TOT_X;
-	break;
-      case RESIZE_BOTTOM:
-	h = y - DECORATION_BORDER_TOT_Y;
-	break;
-      case RESIZE_TOP_LEFT:
-      case RESIZE_TOP:
-      case RESIZE_TOP_RIGHT:
-      case RESIZE_BOTTOM_LEFT:
-      case RESIZE_LEFT:
-      default:
-	g_warning ("Resize mode %d not handled yet.\n", deco->resize);
-	break;
-      }
-      
-      if ((w > 0) && (h > 0))
-	{
-	  _gtk_window_constrain_size (window, w,h, &w, &h);
-	  
-	  if ((w != win_w) || (h != win_h))
-	    gdk_window_resize (widget->window, w, h);
-	}
-    }
-
-  return TRUE;
-}
-
-static GtkWindowRegionType
-gtk_decorated_window_region_type (GtkWindow *window, gint x, gint y)
-{
-  GtkWindowDecoration *deco = get_decoration (window);
-  int i;
-
-  for (i=0;i<deco->n_regions;i++)
-    {
-      if ((x > deco->regions[i].rect.x) &&
-	  (x - deco->regions[i].rect.x < deco->regions[i].rect.width) &&
-	  (y > deco->regions[i].rect.y) &&
-	  (y - deco->regions[i].rect.y < deco->regions[i].rect.height))
-	return deco->regions[i].type;
-    }
-  return -1;
-}
-
-static gint
-gtk_decorated_window_button_press (GtkWidget       *widget,
-				   GdkEventButton  *event)
-{
-  GtkWindow *window;
-  GtkWindowRegionType type;
-  GtkWindowDecoration *deco;
-  gint x, y; 
-
-  window = GTK_WINDOW (widget);
-  deco = get_decoration (window);
-
-  if (!deco->decorated)
-    return TRUE;
-
-  x = event->x;
-  y = event->y;
-  
-  type = gtk_decorated_window_region_type (window, x, y);
-
-  switch (type)
-    {
-    case GTK_WINDOW_REGION_TITLE:
-      if (!deco->maximized && event->state & GDK_BUTTON1_MASK)
-	{
-	  deco->last_x = x;
-	  deco->last_y = y;
-	  deco->moving = TRUE;
-	}
-      break;
-    case GTK_WINDOW_REGION_MAXIMIZE:
-      if (event->state & GDK_BUTTON1_MASK)
-	deco->maximizing = TRUE;
-      break;
-    case GTK_WINDOW_REGION_CLOSE:
-      if (event->state & GDK_BUTTON1_MASK)
-	deco->closing = TRUE;
-      break;
-    case GTK_WINDOW_REGION_BR_RESIZE:
-      if (!deco->maximized)
-	{
-	  if (event->state & GDK_BUTTON1_MASK)
-	    deco->resize = RESIZE_BOTTOM_RIGHT;
-	  deco->last_x = x;
-	  deco->last_y = y;
-	}
-      break;
-    default:
-      break;
-    }
-  
-  return TRUE;
-}
-
-static gint
-gtk_decorated_window_button_release (GtkWidget	    *widget,
-				     GdkEventButton *event)
-{
-  GtkWindow *window;
-  GtkWindowRegionType type;
-  GtkWindowDecoration *deco;
-      
-  window = GTK_WINDOW (widget);
-  deco = get_decoration (window);
-
-  if (deco->closing)
-    {
-      type = gtk_decorated_window_region_type (window, event->x, event->y);
-      if (type == GTK_WINDOW_REGION_CLOSE)
-	{
-	  GdkEvent *event = gdk_event_new (GDK_DELETE);
-
-	  event->any.type = GDK_DELETE;
-	  event->any.window = g_object_ref (widget->window);
-	  event->any.send_event = TRUE;
-
-	  gtk_main_do_event (event);
-	  gdk_event_free (event);
-	}
-    }
-  else if (deco->maximizing)
-    {
-      type = gtk_decorated_window_region_type (window, event->x, event->y);
-      if (type == GTK_WINDOW_REGION_MAXIMIZE)
-        {
-	  if (deco->maximized)
-	    gtk_window_unmaximize (window);
-	  else
-	    gtk_window_maximize (window);
-	}
-    }
-  
-  deco->closing = FALSE;
-  deco->maximizing = FALSE;
-  deco->moving = FALSE;
-  deco->resize = RESIZE_NONE;
-  return TRUE;
-}
-
-static gint
-gtk_decorated_window_window_state (GtkWidget	       *widget,
-				   GdkEventWindowState *event)
-{
-  GtkWindow *window;
-  GtkWindowDecoration *deco;
-  GdkWindowObject *priv;
-      
-  window = GTK_WINDOW (widget);
-  deco = get_decoration (window);
-  priv = GDK_WINDOW_OBJECT (window->frame);
-
-  if (event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED)
-    {
-      if (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED)
-	{
-	  int w, h;
-	  gdk_window_get_geometry (widget->window, NULL, NULL,
-				   &deco->last_w, &deco->last_h, NULL);
-	  gdk_window_get_origin (widget->window, &deco->last_x, &deco->last_y);
-	  w = gdk_screen_get_width(gdk_screen_get_default()) - DECORATION_BORDER_TOT_X;
-	  h = gdk_screen_get_height(gdk_screen_get_default()) - DECORATION_BORDER_TOT_Y;
-	  _gtk_window_constrain_size (window, w, h, &w, &h);
-	  if (w != deco->last_w || h != deco->last_h)
-	    {
-	      _gtk_window_reposition (window, DECORATION_BORDER_LEFT, DECORATION_BORDER_TOP);
-	      gdk_window_resize (widget->window, w, h);
-	      deco->maximized = TRUE;
-	    }
-	}
-      else
-	{
-	  _gtk_window_reposition (window, deco->last_x, deco->last_y);
-	  _gtk_window_constrain_size (window, deco->last_w, deco->last_h,
-				      &deco->last_w, &deco->last_h);
-	  gdk_window_resize (widget->window, deco->last_w, deco->last_h);
-	  deco->maximized = FALSE;
-	}
-    }
-  return TRUE;
-}
-
-static void
-gtk_decorated_window_paint (GtkWidget    *widget,
-			    GdkRectangle *area)
-{
-  GtkWindow *window = GTK_WINDOW (widget);
-  GtkWindowDecoration *deco = get_decoration (window);
-  gint x1, y1, x2, y2;
-  GtkStateType border_state;
-
-  if (deco->decorated)
-    {
-      GdkWindow *frame;
-      gint width, height;
-
-      frame = window->frame;
-      gdk_drawable_get_size (frame, &width, &height);
-
-      /* Top */
-      gtk_paint_flat_box (widget->style, frame, GTK_STATE_NORMAL,
-			  GTK_SHADOW_NONE, area, widget, "base",
-			  0, 0,
-			  width, DECORATION_BORDER_TOP);
-      /* Bottom */
-      gtk_paint_flat_box (widget->style, frame, GTK_STATE_NORMAL,
-			  GTK_SHADOW_NONE, area, widget, "base",
-			  0, height - DECORATION_BORDER_BOTTOM,
-			  width, DECORATION_BORDER_BOTTOM);
-      /* Left */
-      gtk_paint_flat_box (widget->style, frame, GTK_STATE_NORMAL,
-			  GTK_SHADOW_NONE, area, widget, "base",
-			  0, DECORATION_BORDER_TOP,
-			  DECORATION_BORDER_LEFT, height - DECORATION_BORDER_TOT_Y);
-      /* Right */
-      gtk_paint_flat_box (widget->style, frame, GTK_STATE_NORMAL,
-			  GTK_SHADOW_NONE, area, widget, "base",
-			  width - DECORATION_BORDER_RIGHT, DECORATION_BORDER_TOP,
-			  DECORATION_BORDER_RIGHT, height - DECORATION_BORDER_TOT_Y);
-      
-      /* Border: */
-      if (deco->focused)
-	border_state = GTK_STATE_SELECTED;
-      else 
-	border_state = GTK_STATE_PRELIGHT;
-
-      gtk_paint_box (widget->style, frame, border_state, 
-		     GTK_SHADOW_OUT, area, widget, "base",
-		     0, 0, width, height);
-      
-      gtk_paint_box (widget->style, frame, border_state, 
-		     GTK_SHADOW_IN, area, widget, "base",
-		     DECORATION_BORDER_LEFT - 2, DECORATION_BORDER_TOP - 2,
-		     width - (DECORATION_BORDER_LEFT + DECORATION_BORDER_RIGHT) + 3,
-		     height - (DECORATION_BORDER_TOP + DECORATION_BORDER_BOTTOM) + 3);
-
-      if (deco->maximizable)
-	{
-	  /* Maximize button: */
-
-	  x1 = width - (DECORATION_BORDER_LEFT * 2) - (DECORATION_BUTTON_SIZE * 2);
-	  y1 = DECORATION_BUTTON_Y_OFFSET;
-	  x2 = x1 + DECORATION_BUTTON_SIZE;
-	  y2 = y1 + DECORATION_BUTTON_SIZE;
-
-	  if (area)
-	    gdk_gc_set_clip_rectangle (widget->style->bg_gc[widget->state], area);
-
-	  gdk_draw_rectangle (frame, widget->style->bg_gc[widget->state], TRUE,
-			      x1, y1, x2 - x1, y2 - y1);
-
-	  gdk_draw_line (frame, widget->style->black_gc, x1 + 1, y1 + 1, x2 - 2, y1 + 1);
-
-	  gdk_draw_rectangle (frame, widget->style->black_gc, FALSE,
-			      x1 + 1, y1 + 2,
-			      DECORATION_BUTTON_SIZE - 3, DECORATION_BUTTON_SIZE - 4);
-
-	  if (area)
-	    gdk_gc_set_clip_rectangle (widget->style->black_gc, NULL);
-	}
-      
-      /* Close button: */
-      
-      x1 = width - DECORATION_BORDER_LEFT - DECORATION_BUTTON_SIZE;
-      y1 = DECORATION_BUTTON_Y_OFFSET;
-      x2 = width - DECORATION_BORDER_LEFT;
-      y2 = DECORATION_BUTTON_Y_OFFSET + DECORATION_BUTTON_SIZE;
-
-      if (area)
-	gdk_gc_set_clip_rectangle (widget->style->bg_gc[widget->state], area);
-
-      gdk_draw_rectangle (frame, widget->style->bg_gc[widget->state], TRUE,
-			  x1, y1, x2 - x1, y2 - y1);
-
-      if (area)
-	gdk_gc_set_clip_rectangle (widget->style->bg_gc[widget->state], NULL);
-      
-      if (area)
-	gdk_gc_set_clip_rectangle (widget->style->black_gc, area);
-
-      gdk_draw_line (frame, widget->style->black_gc, x1, y1, x2-1, y2-1);
-
-      gdk_draw_line (frame, widget->style->black_gc, x1, y2-1, x2-1, y1);
-
-      if (area)
-	gdk_gc_set_clip_rectangle (widget->style->black_gc, NULL);
-      
-      
-
-      /* Title */
-      if (deco->title_layout)
-	{
-	  if (area)
-	    gdk_gc_set_clip_rectangle (widget->style->fg_gc [border_state], area);
-
-	  gdk_draw_layout (frame,
-			   widget->style->fg_gc [border_state],
-			   DECORATION_BORDER_LEFT, 1,
-			   deco->title_layout);
-	  if (area)
-	    gdk_gc_set_clip_rectangle (widget->style->fg_gc [border_state], NULL);
-	}
-      
-    }
-}
-
-
-static void
-gtk_decorated_window_recalculate_regions (GtkWindow *window)
-{
-  gint n_regions;
-  gint width, height;
-  GtkWindowRegion *region;
-  GtkWindowDecoration *deco = get_decoration (window);
-      
-  n_regions = 0;
-
-  if (!deco->decorated)
-    return;
-  
-  n_regions += 2; /* close, Title */
-  if (deco->maximizable)
-    n_regions += 1;
-  if (window->allow_shrink || window->allow_grow)
-    n_regions += 2;
-
-  if (deco->n_regions != n_regions)
-    {
-      g_free (deco->regions);
-      deco->regions = g_new (GtkWindowRegion, n_regions);
-      deco->n_regions = n_regions;
-    }
-
-  width = GTK_WIDGET (window)->allocation.width + DECORATION_BORDER_TOT_X;
-  height = GTK_WIDGET (window)->allocation.height + DECORATION_BORDER_TOT_Y;
-
-  region = deco->regions;
-
-  /* Maximize button */
-  if (deco->maximizable)
-    {
-      region->rect.x = width - (DECORATION_BORDER_LEFT * 2) - (DECORATION_BUTTON_SIZE * 2);
-      region->rect.y = DECORATION_BUTTON_Y_OFFSET;
-      region->rect.width = DECORATION_BUTTON_SIZE;
-      region->rect.height = DECORATION_BUTTON_SIZE;
-      region->type = GTK_WINDOW_REGION_MAXIMIZE;
-      region++;
-    }
-
-  /* Close button */
-  region->rect.x = width - DECORATION_BORDER_LEFT - DECORATION_BUTTON_SIZE;
-  region->rect.y = DECORATION_BUTTON_Y_OFFSET;
-  region->rect.width = DECORATION_BUTTON_SIZE;
-  region->rect.height = DECORATION_BUTTON_SIZE;
-  region->type = GTK_WINDOW_REGION_CLOSE;
-  region++;
-    
-  /* title bar */
-  region->rect.x = 0;
-  region->rect.y = 0;
-  region->rect.width = width;
-  region->rect.height = DECORATION_BORDER_TOP;
-  region->type = GTK_WINDOW_REGION_TITLE;
-  region++;
-  
-  if (window->allow_shrink || window->allow_grow)
-    {
-      region->rect.x = width - (DECORATION_BORDER_RIGHT + 10);
-      region->rect.y = height - DECORATION_BORDER_BOTTOM;
-      region->rect.width = DECORATION_BORDER_RIGHT + 10;
-      region->rect.height = DECORATION_BORDER_BOTTOM;
-      region->type = GTK_WINDOW_REGION_BR_RESIZE;
-      region++;
-
-      region->rect.x = width - DECORATION_BORDER_RIGHT;
-      region->rect.y = height - (DECORATION_BORDER_BOTTOM + 10);
-      region->rect.width = DECORATION_BORDER_RIGHT;
-      region->rect.height = DECORATION_BORDER_BOTTOM + 10;
-      region->type = GTK_WINDOW_REGION_BR_RESIZE;
-      region++;
-    }
-}
-
-void
-gtk_decorated_window_move_resize_window (GtkWindow   *window,
-					 gint         x,
-					 gint         y,
-					 gint         width,
-					 gint         height)
-{
-  GtkWidget *widget = GTK_WIDGET (window);
-  GtkWindowDecoration *deco = get_decoration (window);
-  
-  deco->real_inner_move = TRUE;
-  gdk_window_move_resize (widget->window,
-			  x, y, width, height);
-}
-#else
-
-void
-gtk_decorated_window_init (GtkWindow  *window)
-{
-}
-
-void 
-gtk_decorated_window_calculate_frame_size (GtkWindow *window)
-{
-}
-
-void
-gtk_decorated_window_set_title (GtkWindow   *window,
-				const gchar *title)
-{
-}
-
-void
-gtk_decorated_window_move_resize_window (GtkWindow   *window,
-					 gint         x,
-					 gint         y,
-					 gint         width,
-					 gint         height)
-{
-  gdk_window_move_resize (GTK_WIDGET (window)->window,
-			  x, y, width, height);
-}
-#endif
-
-
-#define __GTK_WINDOW_DECORATE_C__
-#include "gtkaliasdef.c"
diff --git a/gtk/gtkwindow-decorate.h b/gtk/gtkwindow-decorate.h
deleted file mode 100644
index 9f182f4..0000000
--- a/gtk/gtkwindow-decorate.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* GTK - The GIMP Toolkit
- * Copyright (C) 2001 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/* 
- * Authors: Alexander Larsson <alexl@redhat.com>
- */
-
-#ifndef __GTK_WINDOW_DECORATE_H__
-#define __GTK_WINDOW_DECORATE_H__
-
-G_BEGIN_DECLS
-
-void gtk_decorated_window_init                 (GtkWindow   *window);
-void gtk_decorated_window_calculate_frame_size (GtkWindow   *window);
-void gtk_decorated_window_set_title            (GtkWindow   *window,
-						const gchar *title);
-void gtk_decorated_window_move_resize_window   (GtkWindow   *window,
-						gint         x,
-						gint         y,
-						gint         width,
-						gint         height);
-
-G_END_DECLS
-
-#endif /* __GTK_WINDOW_DECORATE_H__ */
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 98747b2..894f9f7 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -25,6 +25,7 @@
  */
 
 #include "config.h"
+#include <math.h>
 #include <string.h>
 #include <stdlib.h>
 #include <errno.h>
@@ -36,17 +37,23 @@
 
 #include "gtkprivate.h"
 #include "gtkrc.h"
+#include "gtkbutton.h"
+#include "gtkeventbox.h"
 #include "gtkwindow.h"
-#include "gtkwindow-decorate.h"
+#include "gtklabel.h"
 #include "gtkbindings.h"
+#include "gtkhbox.h"
 #include "gtkkeyhash.h"
 #include "gtkmain.h"
 #include "gtkmnemonichash.h"
 #include "gtkiconfactory.h"
 #include "gtkicontheme.h"
+#include "gtkimagemenuitem.h"
 #include "gtkmarshalers.h"
 #include "gtkplug.h"
 #include "gtkbuildable.h"
+#include "gtkstock.h"
+#include "gtkseparatormenuitem.h"
 #include "gtkalias.h"
 
 #ifdef GDK_WINDOWING_X11
@@ -67,6 +74,7 @@ enum {
 
   /* Construct */
   PROP_TYPE,
+  PROP_DISABLE_CLIENT_SIDE_DECORATIONS,
 
   /* Normal Props */
   PROP_TITLE,
@@ -100,16 +108,34 @@ enum {
   
   /* Writeonly properties */
   PROP_STARTUP_ID,
-  
+
   LAST_ARG
 };
 
+/* Must be kept in sync with GdkWindowEdge ! */
+typedef enum
+{
+  GTK_WINDOW_REGION_EDGE_NW,
+  GTK_WINDOW_REGION_EDGE_N,
+  GTK_WINDOW_REGION_EDGE_NE,
+  GTK_WINDOW_REGION_EDGE_W,
+  GTK_WINDOW_REGION_EDGE_E,
+  GTK_WINDOW_REGION_EDGE_SW,
+  GTK_WINDOW_REGION_EDGE_S,
+  GTK_WINDOW_REGION_EDGE_SE,
+  GTK_WINDOW_REGION_INNER,
+  GTK_WINDOW_REGION_TITLE,
+  GTK_WINDOW_REGION_EDGE,
+  GTK_WINDOW_REGION_SHADOW
+} GtkWindowRegion;
+
 typedef struct
 {
   GList     *icon_list;
   GdkPixmap *icon_pixmap;
   GdkPixmap *icon_mask;
   gchar     *icon_name;
+  GdkPixbuf *icon_pixbuf;
   guint      realized : 1;
   guint      using_default_icon : 1;
   guint      using_parent_icon : 1;
@@ -169,7 +195,7 @@ typedef struct _GtkWindowPrivate GtkWindowPrivate;
 struct _GtkWindowPrivate
 {
   GtkMnemonicHash *mnemonic_hash;
-  
+
   guint above_initially : 1;
   guint below_initially : 1;
   guint fullscreen_initially : 1;
@@ -185,11 +211,28 @@ struct _GtkWindowPrivate
   guint opacity_set : 1;
   guint builder_visible : 1;
 
+  GdkWMDecoration client_side_decorations;
+  GdkWMDecoration old_decorations;
+  gboolean        disable_client_side_decorations;
+
   GdkWindowTypeHint type_hint;
 
   gdouble opacity;
 
   gchar *startup_id;
+
+  GtkWidget *title_label;
+  GtkWidget *icon_event_box;
+  GtkWidget *title_icon;
+  GtkWidget *min_button;
+  GtkWidget *max_button;
+  GtkWidget *close_button;
+  GtkWidget *button_box;
+  gint cursor_region;
+
+  GtkWidget *popup_menu;
+
+  GdkCursor *default_cursor;
 };
 
 static void gtk_window_dispose            (GObject           *object);
@@ -205,22 +248,22 @@ static void gtk_window_size_request       (GtkWidget         *widget,
 					   GtkRequisition    *requisition);
 static void gtk_window_size_allocate      (GtkWidget         *widget,
 					   GtkAllocation     *allocation);
-static gint gtk_window_event              (GtkWidget *widget,
-					   GdkEvent *event);
 static gboolean gtk_window_map_event      (GtkWidget         *widget,
                                            GdkEventAny       *event);
-static gboolean gtk_window_frame_event    (GtkWindow *window,
-					   GdkEvent *event);
 static gint gtk_window_configure_event    (GtkWidget         *widget,
 					   GdkEventConfigure *event);
+static gint gtk_window_state_event        (GtkWidget           *widget,
+					   GdkEventWindowState *event);
 static gint gtk_window_key_press_event    (GtkWidget         *widget,
 					   GdkEventKey       *event);
 static gint gtk_window_key_release_event  (GtkWidget         *widget,
 					   GdkEventKey       *event);
+static gboolean gtk_window_button_press_event (GtkWidget      *widget,
+                                               GdkEventButton *event);
 static gint gtk_window_enter_notify_event (GtkWidget         *widget,
 					   GdkEventCrossing  *event);
-static gint gtk_window_leave_notify_event (GtkWidget         *widget,
-					   GdkEventCrossing  *event);
+static gboolean gtk_window_motion_notify_event (GtkWidget    *widget,
+                                                GdkEventMotion *event);
 static gint gtk_window_focus_in_event     (GtkWidget         *widget,
 					   GdkEventFocus     *event);
 static gint gtk_window_focus_out_event    (GtkWidget         *widget,
@@ -228,8 +271,10 @@ static gint gtk_window_focus_out_event    (GtkWidget         *widget,
 static gint gtk_window_client_event	  (GtkWidget	     *widget,
 					   GdkEventClient    *event);
 static void gtk_window_check_resize       (GtkContainer      *container);
-static gint gtk_window_focus              (GtkWidget        *widget,
-				           GtkDirectionType  direction);
+static gint gtk_window_focus              (GtkWidget         *widget,
+				           GtkDirectionType   direction);
+static void gtk_window_style_set          (GtkWidget         *widget,
+                                           GtkStyle          *prev_style);
 static void gtk_window_real_set_focus     (GtkWindow         *window,
 					   GtkWidget         *focus);
 
@@ -297,6 +342,18 @@ static GtkKeyHash *gtk_window_get_key_hash        (GtkWindow   *window);
 static void        gtk_window_free_key_hash       (GtkWindow   *window);
 static void	   gtk_window_on_composited_changed (GdkScreen *screen,
 						     GtkWindow *window);
+static void        gtk_window_set_label_widget (GtkWindow *window,
+                                                GtkWidget *label);
+
+static gboolean    is_client_side_decorated    (GtkWindow      *window);
+static gint        get_decoration_frame_width  (GtkWindow      *window);
+static gboolean    gtk_window_popup_menu       (GtkWidget      *widget);
+static void        gtk_window_do_popup         (GtkWindow      *window,
+                                                GdkEventButton *event);
+
+static void        window_cursor_changed       (GdkWindow  *window,
+                                                GParamSpec *pspec,
+                                                GtkWidget  *widget);
 
 static GSList      *toplevel_list = NULL;
 static guint        window_signals[LAST_SIGNAL] = { 0 };
@@ -343,6 +400,13 @@ static void gtk_window_buildable_custom_finished (GtkBuildable  *buildable,
 						      const gchar   *tagname,
 						      gpointer       user_data);
 
+/* GtkContainer */
+static void gtk_window_forall        (GtkContainer   *container,
+                                      gboolean        include_internals,
+                                      GtkCallback     callback,
+                                      gpointer        callback_data);
+static void gtk_window_remove        (GtkContainer *container,
+                                      GtkWidget    *child);
 
 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
@@ -448,22 +512,26 @@ gtk_window_class_init (GtkWindowClass *klass)
   widget_class->size_request = gtk_window_size_request;
   widget_class->size_allocate = gtk_window_size_allocate;
   widget_class->configure_event = gtk_window_configure_event;
+  widget_class->window_state_event = gtk_window_state_event;
   widget_class->key_press_event = gtk_window_key_press_event;
   widget_class->key_release_event = gtk_window_key_release_event;
   widget_class->enter_notify_event = gtk_window_enter_notify_event;
-  widget_class->leave_notify_event = gtk_window_leave_notify_event;
+  widget_class->motion_notify_event = gtk_window_motion_notify_event;
   widget_class->focus_in_event = gtk_window_focus_in_event;
   widget_class->focus_out_event = gtk_window_focus_out_event;
   widget_class->client_event = gtk_window_client_event;
   widget_class->focus = gtk_window_focus;
-  
+  widget_class->button_press_event = gtk_window_button_press_event;
+  widget_class->style_set = gtk_window_style_set;
+  widget_class->popup_menu = gtk_window_popup_menu;
+
   widget_class->expose_event = gtk_window_expose;
-   
+
   container_class->check_resize = gtk_window_check_resize;
+  container_class->forall = gtk_window_forall;
+  container_class->remove = gtk_window_remove;
 
   klass->set_focus = gtk_window_real_set_focus;
-  klass->frame_event = gtk_window_frame_event;
-
   klass->activate_default = gtk_window_real_activate_default;
   klass->activate_focus = gtk_window_real_activate_focus;
   klass->move_focus = gtk_window_move_focus;
@@ -778,6 +846,95 @@ gtk_window_class_init (GtkWindowClass *klass)
 							1.0,
 							GTK_PARAM_READWRITE));
 
+  /**
+   * GtkWindow:disable-client-side-decorations:
+   *
+   * Disable the use of client-side window decorations for this window.
+   * This is intended to be used by subclasses of GtkWindow that need to
+   * always disable client-side window decorations, for example GtkPlug.
+   * Normally client-side decorations should be controlled through
+   * GtkWindow's 'client-side-decorated' style property.
+   *
+   * Since: 2.18
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_DISABLE_CLIENT_SIDE_DECORATIONS,
+                                   g_param_spec_boolean ("disable-client-side-decorations",
+                                                         P_("Disable client-side decorations"),
+                                                         P_("Disable client-side window decorations"),
+                                                         FALSE,
+                                                         GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+  /* Style properties */
+
+  /**
+   * GtkWindow:client-side-decorated:
+   *
+   * Specifies that the window should draw its own decorations ratherthan
+   * relying upon a window manager to do so.
+   *
+   * Since: 2.18
+   */
+  gtk_widget_class_install_style_property (widget_class,
+                                           g_param_spec_boolean ("client-side-decorated",
+                                                                 P_("Client-side window decorations"),
+                                                                 P_("Whether to decorate windows without the WM"),
+                                                                 TRUE,
+                                                                 GTK_PARAM_READWRITE));
+
+  gtk_widget_class_install_style_property (widget_class,
+                                           g_param_spec_int ("decoration-border-width",
+                                                             P_("Decoration border width"),
+                                                             P_("Decoration border width"),
+                                                             0, G_MAXINT,
+                                                             6, GTK_PARAM_READWRITE));
+
+  gtk_widget_class_install_style_property (widget_class,
+                                           g_param_spec_int ("decoration-resize-handle",
+                                                             P_("Decoration resize handle size"),
+                                                             P_("Decoration resize handle size"),
+                                                             0, G_MAXINT,
+                                                             20, GTK_PARAM_READWRITE));
+
+  /**
+   * GtkWindow:decoration-extents:
+   *
+   * Specifies the size of the client-side window extents, which can be
+   * used for client-side window drop-shadows or window glow.
+   */
+  gtk_widget_class_install_style_property (widget_class,
+                                           g_param_spec_int ("extents-left",
+                                                             P_("Left extents"),
+                                                             P_("Left extents area"),
+                                                             0, G_MAXINT,
+                                                             40,
+                                                             GTK_PARAM_READWRITE));
+
+  gtk_widget_class_install_style_property (widget_class,
+                                           g_param_spec_int ("extents-top",
+                                                             P_("Top extents"),
+                                                             P_("Top extents area"),
+                                                             0, G_MAXINT,
+                                                             40,
+                                                             GTK_PARAM_READWRITE));
+
+  gtk_widget_class_install_style_property (widget_class,
+                                           g_param_spec_int ("extents-right",
+                                                             P_("Right extents"),
+                                                             P_("Right extents area"),
+                                                             0, G_MAXINT,
+                                                             40,
+                                                             GTK_PARAM_READWRITE));
+
+  gtk_widget_class_install_style_property (widget_class,
+                                           g_param_spec_int ("extents-bottom",
+                                                             P_("Bottom extents"),
+                                                             P_("Bottom extents area"),
+                                                             0, G_MAXINT,
+                                                             40,
+                                                             GTK_PARAM_READWRITE));
+
+
   window_signals[SET_FOCUS] =
     g_signal_new (I_("set-focus"),
                   G_TYPE_FROM_CLASS (gobject_class),
@@ -885,8 +1042,8 @@ gtk_window_class_init (GtkWindowClass *klass)
 static void
 gtk_window_init (GtkWindow *window)
 {
-  GdkColormap *colormap;
   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
+  GtkWidget *label;
   
   GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
   GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
@@ -913,10 +1070,10 @@ gtk_window_init (GtkWindow *window)
   window->modal = FALSE;
   window->frame = NULL;
   window->has_frame = FALSE;
-  window->frame_left = 0;
-  window->frame_right = 0;
-  window->frame_top = 0;
-  window->frame_bottom = 0;
+  window->frame_left = 6;
+  window->frame_right = 6;
+  window->frame_top = 6;
+  window->frame_bottom = 6;
   window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
   window->gravity = GDK_GRAVITY_NORTH_WEST;
   window->decorated = TRUE;
@@ -929,17 +1086,19 @@ gtk_window_init (GtkWindow *window)
   priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
   priv->opacity = 1.0;
   priv->startup_id = NULL;
+  gtk_window_set_client_side_decorations (window, GDK_DECOR_BORDER | GDK_DECOR_TITLE | GDK_DECOR_MAXIMIZE);
+  priv->old_decorations = 0;
+  priv->disable_client_side_decorations = FALSE;
+  priv->cursor_region = -1;
+
+  label = gtk_label_new ("");
+  gtk_widget_show (label);
+  gtk_window_set_label_widget (window, label);
 
-  colormap = _gtk_widget_peek_colormap ();
-  if (colormap)
-    gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
-  
   g_object_ref_sink (window);
   window->has_user_ref_count = TRUE;
   toplevel_list = g_slist_prepend (toplevel_list, window);
 
-  gtk_decorated_window_init (window);
-
   g_signal_connect (window->screen, "composited-changed",
 		    G_CALLBACK (gtk_window_on_composited_changed), window);
 }
@@ -950,15 +1109,17 @@ gtk_window_set_property (GObject      *object,
 			 const GValue *value,
 			 GParamSpec   *pspec)
 {
-  GtkWindow  *window;
-  
-  window = GTK_WINDOW (object);
+  GtkWindow  *window = GTK_WINDOW (object);
+  GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
 
   switch (prop_id)
     {
     case PROP_TYPE:
       window->type = g_value_get_enum (value);
       break;
+    case PROP_DISABLE_CLIENT_SIDE_DECORATIONS:
+      priv->disable_client_side_decorations = g_value_get_boolean (value);
+      break;
     case PROP_TITLE:
       gtk_window_set_title (window, g_value_get_string (value));
       break;
@@ -1074,6 +1235,9 @@ gtk_window_get_property (GObject      *object,
     case PROP_TYPE:
       g_value_set_enum (value, window->type);
       break;
+    case PROP_DISABLE_CLIENT_SIDE_DECORATIONS:
+      g_value_set_boolean (value, priv->disable_client_side_decorations);
+      break;
     case PROP_ROLE:
       g_value_set_string (value, window->wm_role);
       break;
@@ -1347,6 +1511,229 @@ gtk_window_new (GtkWindowType type)
   return GTK_WIDGET (window);
 }
 
+static void
+min_button_clicked (GtkWidget *widget, gpointer data)
+{
+  GtkWindow *window = (GtkWindow *)data;
+
+  gtk_window_iconify (window);
+}
+
+static void
+max_button_clicked (GtkWidget *widget, gpointer data)
+{
+  GtkWindow *window = (GtkWindow *)data;
+  GdkWindowState state = gdk_window_get_state (widget->window);
+
+  if (state & GDK_WINDOW_STATE_MAXIMIZED)
+    {
+      gtk_window_unmaximize (window);
+    }
+  else
+    {
+      gtk_window_maximize (window);
+    }
+}
+
+static void
+close_button_clicked (GtkWidget *widget, gpointer data)
+{
+  GdkEvent *event = gdk_event_new (GDK_DELETE);
+
+  event->any.type = GDK_DELETE;
+  event->any.window = g_object_ref (widget->window);
+  event->any.send_event = TRUE;
+
+  gtk_main_do_event (event);
+  gdk_event_free (event);
+}
+
+static void
+update_window_buttons (GtkWindow *window)
+{
+  GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
+
+  if (is_client_side_decorated (window))
+    {
+      if (priv->button_box)
+        gtk_widget_show (priv->button_box);
+      // XXX: should this be using GdkWMFunction instead?
+      if (priv->min_button)
+        {
+          if (priv->client_side_decorations & GDK_DECOR_MINIMIZE)
+            gtk_widget_show_all (priv->min_button);
+          else
+            gtk_widget_hide (priv->min_button);
+        }
+
+      if (priv->max_button)
+        {
+          if (priv->client_side_decorations & GDK_DECOR_MAXIMIZE)
+            gtk_widget_show_all (priv->max_button);
+          else
+            gtk_widget_hide (priv->max_button);
+        }
+
+      // close?
+
+      if (priv->icon_event_box)
+        gtk_widget_show (priv->icon_event_box);
+      if (priv->title_icon)
+        gtk_widget_show (priv->title_icon);
+      if (priv->title_label)
+        gtk_widget_show (priv->title_label);
+    }
+  else
+    {
+      if (priv->button_box)
+        gtk_widget_hide (priv->button_box);
+      if (priv->icon_event_box)
+        gtk_widget_hide (priv->icon_event_box);
+      if (priv->title_icon)
+        gtk_widget_hide (priv->title_icon);
+      if (priv->title_label)
+        gtk_widget_hide (priv->title_label);
+    }
+}
+
+static void
+gtk_window_style_set (GtkWidget *widget,
+                      GtkStyle  *prev_style)
+{
+  GtkWindow *window = GTK_WINDOW (widget);
+
+  GTK_WIDGET_CLASS (gtk_window_parent_class)->style_set (widget, prev_style);
+
+  update_window_buttons (window);
+  gtk_widget_queue_resize (widget);
+  if (widget->window)
+    {
+      if (window->decorated && !is_client_side_decorated (window))
+        gdk_window_set_decorations (widget->window, GDK_DECOR_ALL);
+      else
+        gdk_window_set_decorations (widget->window, 0);
+    }
+}
+
+static void
+update_max_button (GtkWindow *window,
+                   gboolean   maximized)
+{
+  GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
+  GtkWidget *button;
+  GtkWidget *image;
+
+  button = priv->max_button;
+  image = gtk_bin_get_child (GTK_BIN (button));
+
+  if (maximized)
+    {
+      gtk_image_set_from_stock (GTK_IMAGE (image), GTK_STOCK_ZOOM_100, GTK_ICON_SIZE_MENU);
+      gtk_widget_set_tooltip_text (button, _("Restore Window"));
+    }
+  else
+    {
+      gtk_image_set_from_stock (GTK_IMAGE (image), GTK_STOCK_ZOOM_IN, GTK_ICON_SIZE_MENU);
+      gtk_widget_set_tooltip_text (button, _("Maximize Window"));
+    }
+}
+
+static void
+ensure_title_box (GtkWindow *window)
+{
+  GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
+
+  if (is_client_side_decorated (window) && !priv->button_box)
+    {
+      GtkWidget *hbox;
+      GtkWidget *button;
+      GtkWidget *image;
+
+      hbox = gtk_hbox_new (FALSE, 0);
+      gtk_widget_set_parent (hbox, GTK_WIDGET (window));
+
+      button = gtk_button_new ();
+      gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
+      gtk_widget_set_name (button, "gtk-window-decorated-minimize-button");
+      image = gtk_image_new_from_stock (GTK_STOCK_ZOOM_OUT, GTK_ICON_SIZE_MENU);
+      gtk_widget_set_tooltip_text (button, _("Minimize Window"));
+      GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_FOCUS);
+      gtk_container_add (GTK_CONTAINER (button), image);
+      gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
+      priv->min_button = button;
+      g_signal_connect (G_OBJECT (button), "clicked",
+                        G_CALLBACK (min_button_clicked), window);
+
+      button = gtk_button_new ();
+      gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
+      gtk_widget_set_name (button, "gtk-window-decorated-maximize-button");
+      image = gtk_image_new_from_stock (GTK_STOCK_ZOOM_IN, GTK_ICON_SIZE_MENU);
+      gtk_widget_set_tooltip_text (button, _("Maximize Window"));
+      GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_FOCUS);
+      gtk_container_add (GTK_CONTAINER (button), image);
+      gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
+      priv->max_button = button;
+      g_signal_connect (G_OBJECT (button), "clicked",
+                        G_CALLBACK (max_button_clicked), window);
+
+      button = gtk_button_new ();
+      gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
+      gtk_widget_set_name (button, "gtk-window-decorated-close-button");
+      image = gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
+      gtk_widget_set_tooltip_text (button, _("Close Window"));
+      GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_FOCUS);
+      gtk_container_add (GTK_CONTAINER (button), image);
+      gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
+      priv->close_button = button;
+      g_signal_connect (G_OBJECT (button), "clicked",
+                        G_CALLBACK (close_button_clicked), window);
+
+      priv->button_box = hbox;
+
+      gtk_widget_show_all (priv->button_box);
+
+      update_window_buttons (window);
+    }
+}
+
+static void
+gtk_window_set_label_widget (GtkWindow *window,
+                             GtkWidget *label)
+{
+  GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
+
+  g_return_if_fail (GTK_IS_WINDOW (window));
+  g_return_if_fail (label == NULL || GTK_IS_WIDGET (label));
+  g_return_if_fail (label == NULL || label->parent == NULL);
+
+  if (priv->title_label == label)
+    return;
+
+  ensure_title_box (window);
+
+  if (priv->title_label)
+    {
+      gtk_widget_unparent (priv->title_label);
+    }
+
+  priv->title_label = label;
+
+  gtk_widget_set_parent (priv->title_label, GTK_WIDGET (window));
+  gtk_label_set_ellipsize (GTK_LABEL (priv->title_label), PANGO_ELLIPSIZE_END);
+
+  if (label)
+    {
+      priv->title_label = label;
+    }
+
+  gtk_widget_show (priv->title_label);
+
+  if (GTK_WIDGET_VISIBLE (window))
+    {
+      gtk_widget_queue_resize (GTK_WIDGET (window));
+    }
+}
+
 /**
  * gtk_window_set_title:
  * @window: a #GtkWindow
@@ -1367,18 +1754,37 @@ gtk_window_set_title (GtkWindow   *window,
 		      const gchar *title)
 {
   char *new_title;
-  
+  GtkWindowPrivate *priv;
+
   g_return_if_fail (GTK_IS_WINDOW (window));
 
+  priv = GTK_WINDOW_GET_PRIVATE (window);
+
   new_title = g_strdup (title);
   g_free (window->title);
   window->title = new_title;
 
+  if (!priv->title_label)
+    {
+      GtkWidget *child = gtk_label_new (title);
+
+      gtk_widget_set_name (child, "gtk-window-decorated-title-label");
+      gtk_widget_show (child);
+      gtk_window_set_label_widget (window, child);
+    }
+  else
+    {
+      gtk_label_set_text (GTK_LABEL (priv->title_label), title);
+    }
+
+  if (GTK_WIDGET_VISIBLE (priv->title_label) && GTK_WIDGET_VISIBLE (GTK_WIDGET (window)))
+    gtk_widget_queue_resize (GTK_WIDGET (window));
+
   if (GTK_WIDGET_REALIZED (window))
     {
       gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
 
-      gtk_decorated_window_set_title (window, title);
+      gtk_label_set_text (GTK_LABEL (priv->title_label), title);
     }
 
   g_object_notify (G_OBJECT (window), "title");
@@ -2871,29 +3277,36 @@ gtk_window_set_geometry_hints (GtkWindow       *window,
  *
  * On Windows, this function always works, since there's no window manager
  * policy involved.
- * 
+ *
  **/
 void
 gtk_window_set_decorated (GtkWindow *window,
                           gboolean   setting)
 {
+  GtkWindowPrivate *priv;
+
   g_return_if_fail (GTK_IS_WINDOW (window));
 
+  priv = GTK_WINDOW_GET_PRIVATE (window);
   setting = setting != FALSE;
 
   if (setting == window->decorated)
     return;
 
   window->decorated = setting;
-  
+
   if (GTK_WIDGET (window)->window)
     {
-      if (window->decorated)
-        gdk_window_set_decorations (GTK_WIDGET (window)->window,
-                                    GDK_DECOR_ALL);
+      if (window->decorated && !is_client_side_decorated (window))
+        {
+          gdk_window_set_decorations (GTK_WIDGET (window)->window,
+                                      GDK_DECOR_ALL);
+        }
       else
-        gdk_window_set_decorations (GTK_WIDGET (window)->window,
-                                    0);
+        {
+          gdk_window_set_decorations (GTK_WIDGET (window)->window,
+                                      0);
+        }
     }
 
   g_object_notify (G_OBJECT (window), "decorated");
@@ -2916,6 +3329,43 @@ gtk_window_get_decorated (GtkWindow *window)
   return window->decorated;
 }
 
+void
+gtk_window_set_client_side_decorations (GtkWindow       *window,
+                                        GdkWMDecoration  setting)
+{
+  GtkWindowPrivate *priv;
+
+  g_return_if_fail (GTK_IS_WINDOW (window));
+
+  priv = GTK_WINDOW_GET_PRIVATE (window);
+
+  if (setting == priv->client_side_decorations)
+    return;
+
+  priv->client_side_decorations = setting;
+
+  if (GTK_WIDGET (window)->window)
+    {
+      if (priv->client_side_decorations)
+        {
+          gdk_window_get_decorations (GTK_WIDGET (window)->window,
+                                      &priv->old_decorations);
+          gdk_window_set_decorations (GTK_WIDGET (window)->window, 0);
+        }
+      else
+        {
+          if (priv->old_decorations)
+            {
+              gdk_window_set_decorations (GTK_WIDGET (window)->window,
+                                          priv->old_decorations);
+              priv->old_decorations = 0;
+            }
+        }
+    }
+
+  update_window_buttons (window);
+}
+
 /**
  * gtk_window_set_deletable:
  * @window: a #GtkWindow
@@ -2950,7 +3400,7 @@ gtk_window_set_deletable (GtkWindow *window,
     return;
 
   priv->deletable = setting;
-  
+
   if (GTK_WIDGET (window)->window)
     {
       if (priv->deletable)
@@ -3024,6 +3474,7 @@ typedef struct {
   guint serial;
   GdkPixmap *pixmap;
   GdkPixmap *mask;
+  GdkPixbuf *pixbuf;
 } ScreenIconInfo;
 
 static ScreenIconInfo *
@@ -3064,7 +3515,8 @@ get_pixmap_and_mask (GdkWindow		*window,
                      gboolean            is_default_list,
                      GList              *icon_list,
                      GdkPixmap         **pmap_return,
-                     GdkBitmap         **mask_return)
+                     GdkBitmap         **mask_return,
+                     GdkPixbuf         **pixbuf_return)
 {
   GdkScreen *screen = gdk_drawable_get_screen (window);
   ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
@@ -3074,6 +3526,7 @@ get_pixmap_and_mask (GdkWindow		*window,
   
   *pmap_return = NULL;
   *mask_return = NULL;
+  *pixbuf_return = NULL;
   
   if (is_default_list &&
       default_icon_info->pixmap != NULL)
@@ -3084,9 +3537,12 @@ get_pixmap_and_mask (GdkWindow		*window,
         g_object_ref (default_icon_info->pixmap);
       if (default_icon_info->mask)
         g_object_ref (default_icon_info->mask);
+      if (default_icon_info->pixbuf)
+        g_object_ref (default_icon_info->pixbuf);
 
       *pmap_return = default_icon_info->pixmap;
       *mask_return = default_icon_info->mask;
+      *pixbuf_return = default_icon_info->pixbuf;
     }
   else if (parent_info && parent_info->icon_pixmap)
     {
@@ -3094,9 +3550,12 @@ get_pixmap_and_mask (GdkWindow		*window,
         g_object_ref (parent_info->icon_pixmap);
       if (parent_info->icon_mask)
         g_object_ref (parent_info->icon_mask);
-      
+      if (parent_info->icon_pixbuf)
+        g_object_ref (parent_info->icon_pixbuf);
+
       *pmap_return = parent_info->icon_pixmap;
       *mask_return = parent_info->icon_mask;
+      *pixbuf_return = parent_info->icon_pixbuf;
     }
   else
     {
@@ -3139,27 +3598,38 @@ get_pixmap_and_mask (GdkWindow		*window,
         }
 
       if (best_icon)
-        gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
-							gdk_screen_get_system_colormap (screen),
-							pmap_return,
-							mask_return,
-							128);
+        {
+          // XXX - should probably scale based on the height of the label?
+          best_icon = gdk_pixbuf_scale_simple (best_icon, 24, 24, GDK_INTERP_HYPER);
+
+          *pixbuf_return = best_icon;
+
+          gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
+                                                          gdk_screen_get_system_colormap (screen),
+                                                          pmap_return,
+                                                          mask_return,
+                                                          128);
+        }
 
       /* Save pmap/mask for others to use if appropriate */
       if (parent_info)
         {
           parent_info->icon_pixmap = *pmap_return;
           parent_info->icon_mask = *mask_return;
+          parent_info->icon_pixbuf = *pixbuf_return;
 
           if (parent_info->icon_pixmap)
             g_object_ref (parent_info->icon_pixmap);
           if (parent_info->icon_mask)
             g_object_ref (parent_info->icon_mask);
+          if (parent_info->icon_pixbuf)
+            g_object_ref (parent_info->icon_pixbuf);
         }
       else if (is_default_list)
         {
           default_icon_info->pixmap = *pmap_return;
           default_icon_info->mask = *mask_return;
+          default_icon_info->pixbuf = *pixbuf_return;
 
           if (default_icon_info->pixmap)
 	    g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
@@ -3167,6 +3637,9 @@ get_pixmap_and_mask (GdkWindow		*window,
           if (default_icon_info->mask) 
 	    g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
 				       (gpointer*)&default_icon_info->mask);
+          if (default_icon_info->pixbuf)
+            g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixbuf),
+                                       (gpointer*)&default_icon_info->pixbuf);
         }
     }
 }
@@ -3209,6 +3682,60 @@ icon_list_from_theme (GtkWidget    *widget,
   return list;
 }
 
+static gboolean
+icon_button_press (GtkWidget      *widget,
+                   GdkEventButton *event,
+                   gpointer        user_data)
+{
+  GtkWindow *window = (GtkWindow *)user_data;
+
+  gtk_window_do_popup (window, event);
+
+  return TRUE;
+}
+
+static void
+ensure_title_icon (GtkWindow *window)
+{
+  GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
+
+  ensure_title_box (window);
+
+  if (!priv->icon_event_box)
+    {
+      priv->icon_event_box = gtk_event_box_new ();
+      gtk_event_box_set_visible_window (GTK_EVENT_BOX (priv->icon_event_box), FALSE);
+
+      priv->title_icon = gtk_image_new ();
+
+      gtk_container_add (GTK_CONTAINER (priv->icon_event_box),
+                         priv->title_icon);
+
+      g_signal_connect (G_OBJECT (priv->icon_event_box),
+                        "button-press-event",
+                        G_CALLBACK (icon_button_press),
+                        window);
+    }
+
+  gtk_widget_set_parent (priv->icon_event_box, GTK_WIDGET (window));
+
+  gtk_widget_show_all (priv->icon_event_box);
+
+  if (GTK_WIDGET_VISIBLE (window))
+    {
+      gtk_widget_queue_resize (GTK_WIDGET (window));
+    }
+}
+
+static void
+set_title_icon (GtkWindow *window, GdkPixbuf *pixbuf)
+{
+  GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
+
+  ensure_title_icon (window);
+
+  gtk_image_set_from_pixbuf (GTK_IMAGE (priv->title_icon), pixbuf);
+}
 
 static void
 gtk_window_realize_icon (GtkWindow *window)
@@ -3280,8 +3807,9 @@ gtk_window_realize_icon (GtkWindow *window)
                        info->using_default_icon,
                        icon_list,
                        &info->icon_pixmap,
-                       &info->icon_mask);
-  
+                       &info->icon_mask,
+                       &info->icon_pixbuf);
+
   /* This is a slight ICCCM violation since it's a color pixmap not
    * a bitmap, but everyone does it.
    */
@@ -3290,6 +3818,10 @@ gtk_window_realize_icon (GtkWindow *window)
                        info->icon_pixmap,
                        info->icon_mask);
 
+  /* This is not an ICCCM violation. ;-)
+   */
+  set_title_icon (window, info->icon_pixbuf);
+
   info->realized = TRUE;
   
   if (info->using_themed_icon) 
@@ -3338,7 +3870,6 @@ gtk_window_unrealize_icon (GtkWindow *window)
    */
 
   info->realized = FALSE;
-
 }
 
 /**
@@ -4127,13 +4658,18 @@ gtk_window_move (GtkWindow *window,
 {
   GtkWindowGeometryInfo *info;
   GtkWidget *widget;
+  GtkWindowPrivate *priv;
+  gint frame_width = 0;
   
   g_return_if_fail (GTK_IS_WINDOW (window));
 
   widget = GTK_WIDGET (window);
+  priv = GTK_WINDOW_GET_PRIVATE (window);
+
+  info = gtk_window_get_geometry_info (window, TRUE);
+
+  frame_width = get_decoration_frame_width (window);
 
-  info = gtk_window_get_geometry_info (window, TRUE);  
-  
   if (GTK_WIDGET_MAPPED (window))
     {
       /* we have now sent a request with this position
@@ -4168,8 +4704,8 @@ gtk_window_move (GtkWindow *window,
       /* FIXME are we handling gravity properly for framed windows? */
       if (window->frame)
         gdk_window_move (window->frame,
-                         x - window->frame_left,
-                         y - window->frame_top);
+                         x - frame_width,
+                         y - frame_width);
       else
         gdk_window_move (GTK_WIDGET (window)->window,
                          x, y);
@@ -4489,11 +5025,6 @@ gtk_window_show (GtkWidget *widget)
 	  was_realized = TRUE;
 	}
 
-      /* Must be done after the windows are realized,
-       * so that the decorations can be read
-       */
-      gtk_decorated_window_calculate_frame_size (window);
-
       /* We only send configure request if we didn't just finish
        * creating the window; if we just created the window
        * then we created it with widget->allocation anyhow.
@@ -4545,6 +5076,27 @@ gtk_window_map (GtkWidget *widget)
       !GTK_WIDGET_MAPPED (window->bin.child))
     gtk_widget_map (window->bin.child);
 
+  if (priv->title_label &&
+      GTK_WIDGET_VISIBLE (priv->title_label) &&
+      !GTK_WIDGET_MAPPED (priv->title_label))
+    {
+      gtk_widget_map (priv->title_label);
+    }
+
+  if (priv->icon_event_box &&
+      GTK_WIDGET_VISIBLE (priv->icon_event_box) &&
+      !GTK_WIDGET_MAPPED (priv->icon_event_box))
+    {
+      gtk_widget_map (priv->icon_event_box);
+    }
+
+  if (priv->button_box &&
+      GTK_WIDGET_VISIBLE (priv->button_box) &&
+      !GTK_WIDGET_MAPPED (priv->button_box))
+    {
+      gtk_widget_map (priv->button_box);
+    }
+
   if (window->frame)
     toplevel = window->frame;
   else
@@ -4591,9 +5143,6 @@ gtk_window_map (GtkWidget *widget)
 
   gdk_window_show (widget->window);
 
-  if (window->frame)
-    gdk_window_show (window->frame);
-
   if (!disable_startup_notification)
     {
       /* Do we have a custom startup-notification id? */
@@ -4670,6 +5219,56 @@ gtk_window_unmap (GtkWidget *widget)
   priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
 }
 
+static gint
+get_decoration_frame_width (GtkWindow *window)
+{
+  gint frame_width = 0;
+  GdkWindowState state;
+  GtkWidget *widget;
+
+  widget = GTK_WIDGET (window);
+
+  if (widget->window)
+    {
+      GtkWindowPrivate *priv;
+
+      state = gdk_window_get_state (widget->window);
+      priv = GTK_WINDOW_GET_PRIVATE (window);
+
+      if (!(state & GDK_WINDOW_STATE_MAXIMIZED) &&
+          is_client_side_decorated (window) &&
+          priv->client_side_decorations & GDK_DECOR_BORDER)
+        {
+          gtk_widget_style_get (widget,
+                                "decoration-border-width", &frame_width,
+                                NULL);
+        }
+    }
+
+  return frame_width;
+}
+
+static gboolean
+is_client_side_decorated (GtkWindow *window)
+{
+  GtkWindowPrivate *priv;
+  gboolean client_side_decorated;
+
+  if (!window->decorated)
+    return FALSE;
+
+  priv = GTK_WINDOW_GET_PRIVATE (window);
+
+  if (priv->disable_client_side_decorations)
+    return FALSE;
+
+  gtk_widget_style_get (GTK_WIDGET (window),
+                        "client-side-decorated", &client_side_decorated,
+                        NULL);
+
+  return client_side_decorated;
+}
+
 static void
 gtk_window_realize (GtkWidget *widget)
 {
@@ -4678,10 +5277,14 @@ gtk_window_realize (GtkWidget *widget)
   GdkWindowAttr attributes;
   gint attributes_mask;
   GtkWindowPrivate *priv;
+  gint label_height = 0;
+  gboolean client_decorated;
   
   window = GTK_WINDOW (widget);
   priv = GTK_WINDOW_GET_PRIVATE (window);
 
+  client_decorated = is_client_side_decorated (window);
+
   /* ensure widget tree is properly size allocated */
   if (widget->allocation.x == -1 &&
       widget->allocation.y == -1 &&
@@ -4719,7 +5322,7 @@ gtk_window_realize (GtkWidget *widget)
       g_warning (G_STRLOC": Unknown window type %d!", window->type);
       break;
     }
-   
+
   attributes.title = window->title;
   attributes.wmclass_name = window->wmclass_name;
   attributes.wmclass_class = window->wmclass_class;
@@ -4727,50 +5330,9 @@ gtk_window_realize (GtkWidget *widget)
   attributes.visual = gtk_widget_get_visual (widget);
   attributes.colormap = gtk_widget_get_colormap (widget);
 
-  if (window->has_frame)
-    {
-      attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
-      attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
-      attributes.event_mask = (GDK_EXPOSURE_MASK |
-			       GDK_KEY_PRESS_MASK |
-			       GDK_ENTER_NOTIFY_MASK |
-			       GDK_LEAVE_NOTIFY_MASK |
-			       GDK_FOCUS_CHANGE_MASK |
-			       GDK_STRUCTURE_MASK |
-			       GDK_BUTTON_MOTION_MASK |
-			       GDK_POINTER_MOTION_HINT_MASK |
-			       GDK_BUTTON_PRESS_MASK |
-			       GDK_BUTTON_RELEASE_MASK);
-      
-      attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
-      
-      window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
-				      &attributes, attributes_mask);
-						 
-      if (priv->opacity_set)
-	gdk_window_set_opacity (window->frame, priv->opacity);
+  attributes_mask = 0;
+  parent_window = gtk_widget_get_root_window (widget);
 
-      gdk_window_set_user_data (window->frame, widget);
-      
-      attributes.window_type = GDK_WINDOW_CHILD;
-      attributes.x = window->frame_left;
-      attributes.y = window->frame_top;
-    
-      attributes_mask = GDK_WA_X | GDK_WA_Y;
-
-      parent_window = window->frame;
-
-      g_signal_connect (window,
-			"event",
-			G_CALLBACK (gtk_window_event),
-			NULL);
-    }
-  else
-    {
-      attributes_mask = 0;
-      parent_window = gtk_widget_get_root_window (widget);
-    }
-  
   attributes.width = widget->allocation.width;
   attributes.height = widget->allocation.height;
   attributes.event_mask = gtk_widget_get_events (widget);
@@ -4781,6 +5343,24 @@ gtk_window_realize (GtkWidget *widget)
 			    GDK_LEAVE_NOTIFY_MASK |
 			    GDK_FOCUS_CHANGE_MASK |
 			    GDK_STRUCTURE_MASK);
+  if (client_decorated && window->type != GTK_WINDOW_POPUP)
+    {
+      attributes.event_mask |= GDK_BUTTON_PRESS_MASK;
+      attributes.event_mask |= GDK_POINTER_MOTION_MASK;
+
+      if (priv->title_label && GTK_WIDGET_VISIBLE (priv->title_label))
+        {
+          GtkRequisition label_requisition;
+
+          gtk_widget_get_child_requisition (priv->title_label, &label_requisition);
+          label_height = label_requisition.height;
+        }
+      else
+        {
+          label_height = 0;
+        }
+    }
+
   attributes.type_hint = priv->type_hint;
 
   attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP | GDK_WA_TYPE_HINT;
@@ -4811,9 +5391,11 @@ gtk_window_realize (GtkWidget *widget)
 
   if (window->wm_role)
     gdk_window_set_role (widget->window, window->wm_role);
-  
-  if (!window->decorated)
-    gdk_window_set_decorations (widget->window, 0);
+
+  if (!window->decorated || client_decorated)
+    {
+      gdk_window_set_decorations (widget->window, 0);
+    }
 
   if (!priv->deletable)
     gdk_window_set_functions (widget->window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
@@ -4850,6 +5432,12 @@ gtk_window_realize (GtkWidget *widget)
         gdk_window_set_startup_id (widget->window, priv->startup_id);
     }
 
+  /* get the default cursor */
+  priv->default_cursor = gdk_window_get_cursor (widget->window);
+  g_signal_connect (G_OBJECT (widget->window), "notify::cursor",
+                    G_CALLBACK (window_cursor_changed),
+                    widget);
+
   /* Icons */
   gtk_window_realize_icon (window);
 }
@@ -4858,9 +5446,11 @@ static void
 gtk_window_unrealize (GtkWidget *widget)
 {
   GtkWindow *window;
+  GtkWindowPrivate *priv;
   GtkWindowGeometryInfo *info;
 
   window = GTK_WINDOW (widget);
+  priv = GTK_WINDOW_GET_PRIVATE (window);
 
   /* On unrealize, we reset the size of the window such
    * that we will re-apply the default sizing stuff
@@ -4881,6 +5471,12 @@ gtk_window_unrealize (GtkWidget *widget)
       /* be sure we reset geom hints on re-realize */
       info->last.flags = 0;
     }
+
+  if (priv->popup_menu)
+    {
+      gtk_widget_destroy (priv->popup_menu);
+      priv->popup_menu = NULL;
+    }
   
   if (window->frame)
     {
@@ -4901,22 +5497,116 @@ gtk_window_size_request (GtkWidget      *widget,
 {
   GtkWindow *window;
   GtkBin *bin;
+  GtkRequisition child_requisition;
+  GtkWindowPrivate *priv;
 
   window = GTK_WINDOW (widget);
+  priv = GTK_WINDOW_GET_PRIVATE (window);
   bin = GTK_BIN (window);
-  
+
   requisition->width = GTK_CONTAINER (window)->border_width * 2;
   requisition->height = GTK_CONTAINER (window)->border_width * 2;
 
+  if (is_client_side_decorated (window))
+    {
+      gint frame_width = 0;
+      gint extents_left = 0, extents_right = 0, extents_top = 0, extents_bottom = 0;
+      GdkWindowState state;
+
+      if (widget->window != NULL)
+        state = gdk_window_get_state (widget->window);
+
+      if (widget->window && !(state & GDK_WINDOW_STATE_MAXIMIZED))
+        {
+          gtk_widget_style_get (widget,
+                                "extents-left",   &extents_left,
+                                "extents-top",    &extents_top,
+                                "extents-right",  &extents_right,
+                                "extents-bottom", &extents_bottom,
+                                NULL);
+        }
+
+      if (priv->client_side_decorations & GDK_DECOR_BORDER)
+        {
+          gtk_widget_style_get (widget,
+                                "decoration-border-width", &frame_width,
+                                NULL);
+        }
+
+      if (window->type != GTK_WINDOW_POPUP)
+        {
+          GtkRequisition box_requisition;
+          GtkRequisition icon_requisition;
+          gint child_height = 0;
+
+          if (priv->title_label && GTK_WIDGET_VISIBLE (priv->title_label))
+            {
+              gtk_widget_size_request (priv->title_label, &child_requisition);
+              child_height = child_requisition.height;
+            }
+
+          if (priv->icon_event_box && GTK_WIDGET_VISIBLE (priv->icon_event_box))
+            {
+              gtk_widget_size_request (priv->icon_event_box, &icon_requisition);
+              child_height = MAX (child_height, icon_requisition.height);
+            }
+
+          if (priv->button_box && GTK_WIDGET_VISIBLE (priv->button_box))
+            {
+              gtk_widget_size_request (priv->button_box, &box_requisition);
+
+              child_height = MAX (child_height, box_requisition.height);
+            }
+
+          // There should probably be some kind of padding property for
+          // "between the title/buttons and the bin.child".
+          requisition->width += frame_width * 2;
+          requisition->height += frame_width * 2 + child_height;
+        }
+
+      requisition->width += extents_left + extents_right;
+      requisition->height += extents_top + extents_bottom;
+    }
+
   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
     {
-      GtkRequisition child_requisition;
-      
       gtk_widget_size_request (bin->child, &child_requisition);
 
-      requisition->width += child_requisition.width;
-      requisition->height += child_requisition.height;
+      requisition->width += MAX (0, child_requisition.width);
+      requisition->height += MAX (0, child_requisition.height);
+    }
+}
+
+static gint
+get_available_size_for_label (GtkWindow *window)
+{
+  GtkWidget *widget;
+  GtkWindowPrivate *priv;
+  gint border_width = 0;
+  gint available_size;
+
+  if (!is_client_side_decorated (window))
+    return 0;
+
+  widget = GTK_WIDGET (window);
+  priv = GTK_WINDOW_GET_PRIVATE (window);
+
+  available_size = widget->allocation.width;
+  border_width = get_decoration_frame_width (window);
+
+  available_size -= border_width * 2;
+
+  if (priv->icon_event_box && GTK_WIDGET_VISIBLE (priv->icon_event_box))
+    {
+      available_size -= priv->icon_event_box->allocation.width;
     }
+
+  if (priv->button_box && GTK_WIDGET_VISIBLE (priv->button_box))
+    {
+      available_size -= priv->button_box->allocation.width;
+    }
+
+  return available_size;
 }
 
 static void
@@ -4924,88 +5614,141 @@ gtk_window_size_allocate (GtkWidget     *widget,
 			  GtkAllocation *allocation)
 {
   GtkWindow *window;
+  GtkContainer *container;
   GtkAllocation child_allocation;
+  GtkWindowPrivate *priv;
+  GtkRequisition deco_requisition;
+  GtkAllocation deco_allocation;
+  GtkRequisition box_requisition;
+  GtkAllocation box_allocation;
+  gint frame_width = 0;
+  gint title_width = 0;
+  gint left_width = 0;
+  GdkRectangle rect;
+  gboolean client_decorated;
+  gint extents_left = 0;
+  gint extents_top = 0;
+  gint extents_right = 0;
+  gint extents_bottom = 0;
+  GdkWindowState state;
 
   window = GTK_WINDOW (widget);
+  container = GTK_CONTAINER (widget);
   widget->allocation = *allocation;
+  priv = GTK_WINDOW_GET_PRIVATE (window);
 
-  if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
+  client_decorated = is_client_side_decorated (window);
+  if (widget->window)
+    state = gdk_window_get_state (widget->window);
+
+  deco_allocation.width = deco_allocation.height = 0;
+
+  if (client_decorated)
     {
-      child_allocation.x = GTK_CONTAINER (window)->border_width;
-      child_allocation.y = GTK_CONTAINER (window)->border_width;
-      child_allocation.width =
-	MAX (1, (gint)allocation->width - child_allocation.x * 2);
-      child_allocation.height =
-	MAX (1, (gint)allocation->height - child_allocation.y * 2);
+      if (widget->window && !(state & GDK_WINDOW_STATE_MAXIMIZED))
+        {
+          gtk_widget_style_get (widget,
+                                "extents-left",   &extents_left,
+                                "extents-top",    &extents_top,
+                                "extents-right",  &extents_right,
+                                "extents-bottom", &extents_bottom,
+                                NULL);
+        }
 
-      gtk_widget_size_allocate (window->bin.child, &child_allocation);
+      if (priv->client_side_decorations & GDK_DECOR_BORDER)
+        {
+          frame_width = get_decoration_frame_width (window);
+        }
     }
 
-  if (GTK_WIDGET_REALIZED (widget) && window->frame)
+  if (client_decorated && priv->icon_event_box && GTK_WIDGET_VISIBLE (priv->icon_event_box))
     {
-      gdk_window_resize (window->frame,
-			 allocation->width + window->frame_left + window->frame_right,
-			 allocation->height + window->frame_top + window->frame_bottom);
-    }
-}
+      gtk_widget_get_child_requisition (priv->icon_event_box, &deco_requisition);
 
-static gint
-gtk_window_event (GtkWidget *widget, GdkEvent *event)
-{
-  GtkWindow *window;
-  gboolean return_val;
+      if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+        deco_allocation.x = allocation->width - frame_width - deco_requisition.width - extents_left;
+      else
+        deco_allocation.x = frame_width + extents_left;
+      deco_allocation.y = frame_width + extents_top;
+      deco_allocation.width = deco_requisition.width;
+      deco_allocation.height = deco_requisition.height;
 
-  window = GTK_WINDOW (widget);
+      if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
+        left_width = deco_allocation.width;
+
+      gtk_widget_size_allocate (priv->icon_event_box, &deco_allocation);
+    }
 
-  if (window->frame && (event->any.window == window->frame))
+  if (client_decorated && priv->button_box && GTK_WIDGET_VISIBLE (priv->button_box))
     {
-      if ((event->type != GDK_KEY_PRESS) &&
-	  (event->type != GDK_KEY_RELEASE) &&
-	  (event->type != GDK_FOCUS_CHANGE))
-	{
-	  g_signal_stop_emission_by_name (widget, "event");
-	  return_val = FALSE;
-	  g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
-	  return TRUE;
-	}
+      gtk_widget_get_child_requisition (priv->button_box, &box_requisition);
+
+      if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+        box_allocation.x = frame_width + extents_left;
       else
-	{
-	  g_object_unref (event->any.window);
-	  event->any.window = g_object_ref (widget->window);
-	}
+        box_allocation.x = allocation->width - frame_width - box_requisition.width - extents_right;
+      box_allocation.y = frame_width + extents_top;
+      box_allocation.width = box_requisition.width;
+      box_allocation.height = box_requisition.height;
+
+      if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+        left_width = box_allocation.width;
+
+      gtk_widget_size_allocate (priv->button_box, &box_allocation);
     }
 
-  return FALSE;
-}
+  if (client_decorated && priv->title_label && GTK_WIDGET_VISIBLE (priv->title_label))
+    {
+      gtk_widget_get_child_requisition (priv->title_label, &deco_requisition);
 
-static gboolean
-gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
-{
-  GdkEventConfigure *configure_event;
-  GdkRectangle rect;
+      deco_allocation.x = 2 * frame_width + left_width + extents_left;
+      deco_allocation.y = frame_width + extents_top;
+      deco_allocation.width = MAX (deco_requisition.width, get_available_size_for_label (window));
+      deco_allocation.height = deco_requisition.height;
+
+      title_width = deco_allocation.width;
+
+      gtk_widget_size_allocate (priv->title_label, &deco_allocation);
+    }
 
-  switch (event->type)
+  if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
+    {
+      if (client_decorated && window->type != GTK_WINDOW_POPUP)
+        {
+          child_allocation.x = container->border_width + frame_width + extents_left;
+          child_allocation.y = container->border_width + extents_top
+            + MAX (deco_allocation.height, box_allocation.height)
+            + frame_width; // XXX - padding style property?
+          child_allocation.width = MAX (1, ((gint)allocation->width - container->border_width * 2
+                                            - extents_left - extents_right
+                                            - (frame_width * 2)));
+          child_allocation.height = MAX (1, ((gint)allocation->height - container->border_width * 2
+                                             - extents_top - extents_bottom
+                                             - (frame_width * 2)
+                                             // XXX - padding style property?
+                                             - MAX (deco_allocation.height, box_allocation.height)));
+        }
+      else
+        {
+          child_allocation.x = GTK_CONTAINER (window)->border_width + extents_left;
+          child_allocation.y = GTK_CONTAINER (window)->border_width + extents_top;
+          child_allocation.width = MAX (1,
+              (gint)allocation->width - child_allocation.x * 2 - extents_left - extents_right);
+          child_allocation.height = MAX (1,
+              (gint)allocation->height - child_allocation.y * 2 - extents_top - extents_bottom);
+        }
+
+      gtk_widget_size_allocate (window->bin.child, &child_allocation);
+    }
+
+  if (widget->window != NULL)
     {
-    case GDK_CONFIGURE:
-      configure_event = (GdkEventConfigure *)event;
-      
-      /* Invalidate the decorations */
       rect.x = 0;
       rect.y = 0;
-      rect.width = configure_event->width;
-      rect.height = configure_event->height;
-      
-      gdk_window_invalidate_rect (window->frame, &rect, FALSE);
-
-      /* Pass on the (modified) configure event */
-      configure_event->width -= window->frame_left + window->frame_right;
-      configure_event->height -= window->frame_top + window->frame_bottom;
-      return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
-      break;
-    default:
-      break;
+      rect.width = allocation->width;
+      rect.height = allocation->height;
+      gdk_window_invalidate_rect (widget->window, &rect, TRUE);
     }
-  return FALSE;
 }
 
 static gint
@@ -5063,12 +5806,27 @@ gtk_window_configure_event (GtkWidget         *widget,
   
   widget->allocation.width = event->width;
   widget->allocation.height = event->height;
-  
+
   _gtk_container_queue_resize (GTK_CONTAINER (widget));
   
   return TRUE;
 }
 
+static gboolean
+gtk_window_state_event (GtkWidget           *widget,
+                        GdkEventWindowState *event)
+{
+  GtkWindow *window = GTK_WINDOW (widget);
+
+  if (is_client_side_decorated (window))
+    {
+      if (event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED)
+        update_max_button (window, event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED);
+    }
+
+  return FALSE;
+}
+
 /* the accel_key and accel_mods fields of the key have to be setup
  * upon calling this function. it'll then return whether that key
  * is at all used as accelerator, and if so will OR in the
@@ -5159,6 +5917,196 @@ gtk_window_propagate_key_event (GtkWindow        *window,
 }
 
 static gint
+get_title_height (GtkWindow *window)
+{
+  GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
+  gint title;
+
+  title = 0;
+  if (priv->title_icon && GTK_WIDGET_VISIBLE (priv->title_icon))
+    title = MAX (title, priv->title_icon->allocation.height);
+  if (priv->title_label && GTK_WIDGET_VISIBLE (priv->title_label))
+    title = MAX (title, priv->title_label->allocation.height);
+  if (priv->button_box && GTK_WIDGET_VISIBLE (priv->button_box))
+    title = MAX (title, priv->button_box->allocation.height);
+
+  return title;
+}
+
+static GtkWindowRegion
+get_region_type (GtkWindow *window, gint x, gint y)
+{
+  GtkWidget *widget = GTK_WIDGET (window);
+  gint title_height = get_title_height (window);
+  gint frame_width = 0;
+  gint resize_handle = 0;
+  gint extents_left, extents_right, extents_top, extents_bottom;
+
+  frame_width = get_decoration_frame_width (window);
+
+  gtk_widget_style_get (widget,
+                        "decoration-resize-handle", &resize_handle,
+                        "extents-left",             &extents_left,
+                        "extents-right",            &extents_right,
+                        "extents-top",              &extents_top,
+                        "extents-bottom",           &extents_bottom,
+                        NULL);
+
+  if (x < extents_left || x > widget->allocation.width - extents_right ||
+      y < extents_top || y > widget->allocation.height - extents_bottom)
+    return GTK_WINDOW_REGION_SHADOW;
+
+  if (x > extents_left && x < frame_width + extents_left)
+    {
+      if (y < frame_width + extents_top + MAX (title_height, resize_handle))
+        return GTK_WINDOW_REGION_EDGE_NW;
+      else if (y > widget->allocation.height - frame_width - resize_handle - extents_bottom)
+        return GTK_WINDOW_REGION_EDGE_SW;
+      else
+        return GTK_WINDOW_REGION_EDGE_W;
+    }
+  else if (x > widget->allocation.width - extents_right - frame_width &&
+           x < widget->allocation.width - extents_right)
+    {
+      if (y < frame_width + extents_top + MAX (title_height, resize_handle))
+        return GTK_WINDOW_REGION_EDGE_NE;
+      else if (y > widget->allocation.height - frame_width - resize_handle - extents_bottom)
+        return GTK_WINDOW_REGION_EDGE_SE;
+      else
+        return GTK_WINDOW_REGION_EDGE_E;
+    }
+  else if (y > extents_top && y < frame_width + extents_top)
+    {
+      if (x < frame_width + resize_handle && x > extents_left)
+        return GTK_WINDOW_REGION_EDGE_NW;
+      else if (x > widget->allocation.width - frame_width - resize_handle &&
+               x < widget->allocation.width - extents_right)
+        return GTK_WINDOW_REGION_EDGE_NE;
+      else
+        return GTK_WINDOW_REGION_EDGE_N;
+    }
+  else if (y > widget->allocation.height - extents_bottom - frame_width &&
+           y < widget->allocation.height - extents_bottom)
+    {
+      if (x < frame_width + resize_handle && x > extents_left)
+        return GTK_WINDOW_REGION_EDGE_SW;
+      else if (x > widget->allocation.width - frame_width - resize_handle &&
+               x < widget->allocation.width - extents_right)
+        return GTK_WINDOW_REGION_EDGE_SE;
+      else
+        return GTK_WINDOW_REGION_EDGE_S;
+    }
+  else
+    {
+      if (y < frame_width + title_height)
+        return GTK_WINDOW_REGION_TITLE;
+      else
+        return GTK_WINDOW_REGION_INNER;
+    }
+}
+
+static GtkWindowRegion
+get_active_region_type (GtkWindow *window, gint x, gint y)
+{
+  GtkWidget *widget = GTK_WIDGET (window);
+  GtkWindowRegion region;
+  gboolean resize_h, resize_v;
+  gint frame_width = 0;
+  gint state;
+
+  region = get_region_type (window, x, y);
+
+  frame_width = get_decoration_frame_width (window);
+
+  state = gdk_window_get_state (widget->window);
+  if (!window->allow_grow || (state & GDK_WINDOW_STATE_MAXIMIZED))
+    {
+      resize_h = resize_v = FALSE;
+    }
+  else
+    {
+      resize_h = resize_v = TRUE;
+      if (window->geometry_info)
+        {
+          GdkGeometry *geometry = &window->geometry_info->geometry;
+          GdkWindowHints flags = window->geometry_info->mask;
+
+          if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
+            {
+              resize_h = geometry->min_width != geometry->max_width;
+              resize_v = geometry->min_height != geometry->max_height;
+            }
+        }
+    }
+
+  switch (region)
+    {
+    case GTK_WINDOW_REGION_EDGE_N:
+    case GTK_WINDOW_REGION_EDGE_S:
+      if (resize_v)
+        return region;
+      else
+        return GTK_WINDOW_REGION_EDGE;
+      break;
+
+    case GTK_WINDOW_REGION_EDGE_W:
+    case GTK_WINDOW_REGION_EDGE_E:
+      if (resize_h)
+        return region;
+      else
+        return GTK_WINDOW_REGION_EDGE;
+      break;
+
+    case GTK_WINDOW_REGION_EDGE_NW:
+      if (resize_h && resize_v)
+        return region;
+      else if (resize_h && x < frame_width)
+        return GTK_WINDOW_REGION_EDGE_W;
+      else if (resize_v && y < frame_width)
+        return GTK_WINDOW_REGION_EDGE_N;
+      else
+        return GTK_WINDOW_REGION_EDGE;
+      break;
+
+    case GTK_WINDOW_REGION_EDGE_NE:
+      if (resize_h && resize_v)
+        return region;
+      else if (resize_h && x > widget->allocation.width - frame_width)
+        return GTK_WINDOW_REGION_EDGE_E;
+      else if (resize_v && y < frame_width)
+        return GTK_WINDOW_REGION_EDGE_N;
+      else
+        return GTK_WINDOW_REGION_EDGE;
+      break;
+
+    case GTK_WINDOW_REGION_EDGE_SW:
+      if (resize_h && resize_v)
+        return region;
+      else if (resize_h && x < frame_width)
+        return GTK_WINDOW_REGION_EDGE_W;
+      else if (resize_v && y > widget->allocation.height - frame_width)
+        return GTK_WINDOW_REGION_EDGE_N;
+      else
+        return GTK_WINDOW_REGION_EDGE;
+      break;
+
+    case GTK_WINDOW_REGION_EDGE_SE:
+      if (resize_h && resize_v)
+        return region;
+      else if (resize_h && x > widget->allocation.width - frame_width)
+        return GTK_WINDOW_REGION_EDGE_E;
+      else if (resize_v && y > widget->allocation.height - frame_width)
+        return GTK_WINDOW_REGION_EDGE_S;
+      else
+        return GTK_WINDOW_REGION_EDGE;
+      break;
+
+    default:
+      return region;
+    }
+}
+
+static gint
 gtk_window_key_press_event (GtkWidget   *widget,
 			    GdkEventKey *event)
 {
@@ -5198,6 +6146,66 @@ gtk_window_key_release_event (GtkWidget   *widget,
   return handled;
 }
 
+static gboolean
+gtk_window_button_press_event (GtkWidget      *widget,
+                               GdkEventButton *event)
+{
+  GtkWindow *window = GTK_WINDOW (widget);
+  gint x = event->x;
+  gint y = event->y;
+
+  if (is_client_side_decorated (window))
+    {
+      GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
+      GtkWindowRegion region = get_active_region_type (window, x, y);
+
+      if (event->type == GDK_BUTTON_PRESS)
+        {
+          if (event->button == 1)
+            {
+              switch (region)
+                {
+                case GTK_WINDOW_REGION_TITLE:
+                case GTK_WINDOW_REGION_INNER:
+                case GTK_WINDOW_REGION_EDGE:
+                  gtk_window_begin_move_drag (window,
+                                              event->button,
+                                              event->x_root,
+                                              event->y_root,
+                                              event->time);
+                  break;
+
+                default:
+                  gtk_window_begin_resize_drag (window,
+                                                (GdkWindowEdge)region,
+                                                event->button,
+                                                event->x_root,
+                                                event->y_root,
+                                                event->time);
+                  break;
+                }
+
+              return TRUE;
+            }
+          else if (event->button == 3)
+            {
+              gtk_window_do_popup (window, event);
+
+              return TRUE;
+            }
+        }
+      else if (event->type == GDK_2BUTTON_PRESS)
+        {
+          if (region == GTK_WINDOW_REGION_TITLE)
+            {
+              gtk_button_clicked (GTK_BUTTON (priv->max_button));
+            }
+        }
+    }
+
+  return FALSE;
+}
+
 static void
 gtk_window_real_activate_default (GtkWindow *window)
 {
@@ -5220,17 +6228,154 @@ gtk_window_move_focus (GtkWindow       *window,
     gtk_window_set_focus (window, NULL);
 }
 
+static void
+get_resize_info (GtkWindow *window,
+                 gboolean  *horizontal,
+                 gboolean  *vertical)
+{
+  GdkGeometry *geometry;
+
+  if (window->geometry_info)
+    {
+      geometry = &window->geometry_info->geometry;
+      *horizontal = geometry->min_width != geometry->max_width;
+      *vertical = geometry->min_height != geometry->max_height;
+    }
+  else
+    {
+      *horizontal = *vertical = TRUE;
+    }
+}
+
+static void
+window_cursor_changed (GdkWindow  *window,
+                       GParamSpec *pspec,
+                       GtkWidget  *widget)
+{
+  GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (widget);
+
+  priv->default_cursor = gdk_window_get_cursor (window);
+}
+
+static void
+update_cursor_at_position (GtkWidget *widget, gint x, gint y)
+{
+  GtkWindow *window = GTK_WINDOW (widget);
+  GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
+  GtkWindowRegion region;
+  GdkCursorType cursor_type;
+  GdkCursor *cursor;
+  GdkWindowState state;
+  gboolean use_default = FALSE;
+
+  region = get_active_region_type (window, x, y);
+
+  if (region == priv->cursor_region)
+    return;
+
+  state = gdk_window_get_state (widget->window);
+
+  if ((state & GDK_WINDOW_STATE_MAXIMIZED) || !window->allow_grow)
+    {
+      use_default = TRUE;
+    }
+  else
+    {
+      switch (region)
+        {
+        case GTK_WINDOW_REGION_EDGE_NW:
+          cursor_type = GDK_TOP_LEFT_CORNER;
+          break;
+
+        case GTK_WINDOW_REGION_EDGE_N:
+          cursor_type = GDK_TOP_SIDE;
+          break;
+
+        case GTK_WINDOW_REGION_EDGE_NE:
+          cursor_type = GDK_TOP_RIGHT_CORNER;
+          break;
+
+        case GTK_WINDOW_REGION_EDGE_W:
+          cursor_type = GDK_LEFT_SIDE;
+          break;
+
+        case GTK_WINDOW_REGION_EDGE_E:
+          cursor_type = GDK_RIGHT_SIDE;
+          break;
+
+        case GTK_WINDOW_REGION_EDGE_SW:
+          cursor_type = GDK_BOTTOM_LEFT_CORNER;
+          break;
+
+        case GTK_WINDOW_REGION_EDGE_S:
+          cursor_type = GDK_BOTTOM_SIDE;
+          break;
+
+        case GTK_WINDOW_REGION_EDGE_SE:
+          cursor_type = GDK_BOTTOM_RIGHT_CORNER;
+          break;
+
+        default:
+          use_default = TRUE;
+          break;
+        }
+    }
+
+  g_signal_handlers_disconnect_by_func (G_OBJECT (widget->window),
+                                        G_CALLBACK (window_cursor_changed),
+                                        widget);
+
+  if (use_default)
+    {
+      gdk_window_set_cursor (widget->window, priv->default_cursor);
+    }
+  else
+    {
+      cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), cursor_type);
+      gdk_window_set_cursor (widget->window, cursor);
+    }
+
+  g_signal_connect (G_OBJECT (widget->window), "notify::cursor",
+                    G_CALLBACK (window_cursor_changed),
+                    widget);
+}
+
 static gint
 gtk_window_enter_notify_event (GtkWidget        *widget,
 			       GdkEventCrossing *event)
 {
+  gint x, y;
+  GdkModifierType mask;
+  gint winx, winy, winh, winw;
+
+  gdk_window_get_geometry (widget->window, &winx, &winy, &winh, &winw, NULL);
+  gdk_window_get_pointer (widget->window, &x, &y, &mask);
+
+  if (gdk_window_get_pointer (widget->window, &x, &y, NULL) == widget->window)
+    {
+      update_cursor_at_position (widget, x, y);
+    }
+  else
+    {
+      GdkCursor *cursor = gdk_cursor_new (GDK_ARROW);
+      gdk_window_set_cursor (widget->window, cursor);
+    }
+
   return FALSE;
 }
 
-static gint
-gtk_window_leave_notify_event (GtkWidget        *widget,
-			       GdkEventCrossing *event)
+static gboolean
+gtk_window_motion_notify_event (GtkWidget       *widget,
+                                GdkEventMotion  *event)
 {
+  gint x, y;
+  gint winx, winy, winh, winw;
+
+  gdk_window_get_geometry (widget->window, &winx, &winy, &winh, &winw, NULL);
+  gdk_window_get_pointer (widget->window, &x, &y, NULL);
+
+  update_cursor_at_position (widget, x, y);
+
   return FALSE;
 }
 
@@ -5261,6 +6406,13 @@ do_focus_change (GtkWidget *widget,
   gdk_event_free (fevent);
 }
 
+static void
+gtk_window_queue_draw_border (GtkWidget *widget)
+{
+  /* FIXME only invalidate the frame area */
+  gtk_widget_queue_draw (widget);
+}
+
 static gint
 gtk_window_focus_in_event (GtkWidget     *widget,
 			   GdkEventFocus *event)
@@ -5276,6 +6428,8 @@ gtk_window_focus_in_event (GtkWidget     *widget,
     {
       _gtk_window_set_has_toplevel_focus (window, TRUE);
       _gtk_window_set_is_active (window, TRUE);
+      if (is_client_side_decorated (window))
+        gtk_window_queue_draw_border (widget);
     }
       
   return FALSE;
@@ -5289,6 +6443,8 @@ gtk_window_focus_out_event (GtkWidget     *widget,
 
   _gtk_window_set_has_toplevel_focus (window, FALSE);
   _gtk_window_set_is_active (window, FALSE);
+  if (is_client_side_decorated (window))
+    gtk_window_queue_draw_border (widget);
 
   return FALSE;
 }
@@ -5358,6 +6514,59 @@ gtk_window_check_resize (GtkContainer *container)
     gtk_window_move_resize (window);
 }
 
+static void
+gtk_window_forall (GtkContainer   *container,
+                   gboolean        include_internals,
+                   GtkCallback     callback,
+                   gpointer        callback_data)
+{
+  GtkBin *bin = GTK_BIN (container);
+  GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (container);
+
+  if (bin->child)
+    (* callback) (bin->child, callback_data);
+
+  if (priv->icon_event_box)
+    (* callback) (priv->icon_event_box, callback_data);
+
+  if (priv->title_label)
+    (* callback) (priv->title_label, callback_data);
+
+  if (priv->button_box)
+    (* callback) (priv->button_box, callback_data);
+}
+
+static void
+gtk_window_remove (GtkContainer *container,
+                   GtkWidget    *child)
+{
+  GtkWindow *window = GTK_WINDOW (container);
+  GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
+
+  if (priv->icon_event_box && priv->icon_event_box == child)
+    {
+      gtk_widget_unparent (priv->icon_event_box);
+      gtk_widget_destroy (priv->icon_event_box);
+      priv->icon_event_box = NULL;
+    }
+  else if (priv->title_label && priv->title_label == child)
+    {
+      gtk_widget_unparent (priv->title_label);
+      gtk_widget_destroy (priv->title_label);
+      priv->title_label = NULL;
+    }
+  else if (priv->button_box && priv->button_box == child)
+    {
+      gtk_widget_unparent (priv->button_box);
+      gtk_widget_destroy (priv->button_box);
+      priv->button_box = NULL;
+    }
+  else
+    {
+      GTK_CONTAINER_CLASS (gtk_window_parent_class)->remove (container, child);
+    }
+}
+
 static gboolean
 gtk_window_focus (GtkWidget        *widget,
 		  GtkDirectionType  direction)
@@ -5552,6 +6761,117 @@ _gtk_window_unset_focus_and_default (GtkWindow *window,
   g_object_unref (window);
 }
 
+static void
+popup_menu_detach (GtkWidget *widget,
+                   GtkMenu   *menu)
+{
+  GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (widget);
+
+  priv->popup_menu = NULL;
+}
+
+static void
+popup_position_func (GtkMenu   *menu,
+                     gint      *x,
+                     gint      *y,
+                     gboolean  *push_in,
+                     gpointer   user_data)
+{
+}
+
+static void
+minimize_window_clicked (GtkMenuItem *menuitem,
+                         gpointer     user_data)
+{
+  GtkWindow *window = (GtkWindow *)user_data;
+
+  gtk_window_iconify (window);
+}
+
+static void
+maximize_window_clicked (GtkMenuItem *menuitem,
+                         gpointer     user_data)
+{
+  GtkWindow *window = (GtkWindow *)user_data;
+  GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
+
+  gtk_button_clicked (GTK_BUTTON (priv->max_button));
+}
+
+static void
+close_window_clicked (GtkMenuItem *menuitem,
+                      gpointer     user_data)
+{
+  GtkWindow *window = (GtkWindow *)user_data;
+
+  close_button_clicked (GTK_WIDGET (window), NULL);
+}
+
+static void
+gtk_window_do_popup (GtkWindow      *window,
+                     GdkEventButton *event)
+{
+  GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
+  GdkWindowState state = gdk_window_get_state (GTK_WIDGET (window)->window);
+  GtkWidget *menuitem;
+
+  if (priv->popup_menu)
+    gtk_widget_destroy (priv->popup_menu);
+
+  priv->popup_menu = gtk_menu_new ();
+  gtk_menu_attach_to_widget (GTK_MENU (priv->popup_menu),
+                             GTK_WIDGET (window),
+                             popup_menu_detach);
+
+  menuitem = gtk_menu_item_new_with_label ("Minimize");
+  gtk_widget_show (menuitem);
+  g_signal_connect (G_OBJECT (menuitem),
+                    "activate",
+                    G_CALLBACK (minimize_window_clicked), window);
+  gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), menuitem);
+
+  menuitem = gtk_menu_item_new_with_label (state & GDK_WINDOW_STATE_MAXIMIZED ? "Unmaximize" : "Maximize");
+  g_signal_connect (G_OBJECT (menuitem),
+                    "activate",
+                    G_CALLBACK (maximize_window_clicked), window);
+  gtk_widget_show (menuitem);
+  gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), menuitem);
+
+  menuitem = gtk_separator_menu_item_new ();
+  gtk_widget_show (menuitem);
+  gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), menuitem);
+
+  menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_CLOSE, NULL);
+  gtk_widget_show (menuitem);
+  g_signal_connect (G_OBJECT (menuitem),
+                    "activate",
+                    G_CALLBACK (close_window_clicked), window);
+  gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), menuitem);
+
+  if (event)
+    {
+      gtk_menu_popup (GTK_MENU (priv->popup_menu),
+                      NULL, NULL,
+                      NULL, NULL,
+                      event->button, event->time);
+    }
+  else
+    {
+      gtk_menu_popup (GTK_MENU (priv->popup_menu),
+                      NULL, NULL,
+                      popup_position_func, window,
+                      0, gtk_get_current_event_time ());
+    }
+}
+
+static gboolean
+gtk_window_popup_menu (GtkWidget *widget)
+{
+  gtk_window_do_popup (GTK_WINDOW (widget), NULL);
+
+  return TRUE;
+}
+
 /*********************************
  * Functions related to resizing *
  *********************************/
@@ -5983,6 +7303,7 @@ gtk_window_move_resize (GtkWindow *window)
    *   the position request to be centered.
    */
   GtkWidget *widget;
+  GtkWindowPrivate *priv;
   GtkContainer *container;
   GtkWindowGeometryInfo *info;
   GdkGeometry new_geometry;
@@ -5992,14 +7313,18 @@ gtk_window_move_resize (GtkWindow *window)
   gboolean configure_request_pos_changed;
   gboolean hints_changed; /* do we need to send these again */
   GtkWindowLastGeometryInfo saved_last_info;
-  
+  gint frame_width = 0;
+
   widget = GTK_WIDGET (window);
   container = GTK_CONTAINER (widget);
   info = gtk_window_get_geometry_info (window, TRUE);
+  priv = GTK_WINDOW_GET_PRIVATE (window);
   
   configure_request_size_changed = FALSE;
   configure_request_pos_changed = FALSE;
-  
+
+  frame_width = get_decoration_frame_width (window);
+
   gtk_window_compute_configure_request (window, &new_request,
                                         &new_geometry, &new_flags);  
   
@@ -6242,6 +7567,8 @@ gtk_window_move_resize (GtkWindow *window)
 	    widget->allocation.height != new_request.height))
 
     {
+      gint frame_width = get_decoration_frame_width (window);
+
       /* We are in one of the following situations:
        * A. configure_request_size_changed
        *    our requisition has changed and we need a different window size,
@@ -6263,10 +7590,10 @@ gtk_window_move_resize (GtkWindow *window)
 	  if (window->frame)
 	    {
 	      gdk_window_move_resize (window->frame,
-				      new_request.x - window->frame_left,
-                                      new_request.y - window->frame_top,
-				      new_request.width + window->frame_left + window->frame_right,
-				      new_request.height + window->frame_top + window->frame_bottom);
+				      new_request.x - frame_width,
+                                      new_request.y - frame_width,
+				      new_request.width + frame_width * 2,
+				      new_request.height + frame_width * 2);
 	      gdk_window_resize (widget->window,
                                  new_request.width, new_request.height);
 	    }
@@ -6279,8 +7606,8 @@ gtk_window_move_resize (GtkWindow *window)
 	{
 	  if (window->frame)
 	    gdk_window_resize (window->frame,
-			       new_request.width + window->frame_left + window->frame_right,
-			       new_request.height + window->frame_top + window->frame_bottom);
+			       new_request.width + frame_width * 2,
+			       new_request.height + frame_width * 2);
 	  gdk_window_resize (widget->window,
 			     new_request.width, new_request.height);
 	}
@@ -6339,8 +7666,8 @@ gtk_window_move_resize (GtkWindow *window)
 	  if (window->frame)
 	    {
 	      gdk_window_move (window->frame,
-			       new_request.x - window->frame_left,
-			       new_request.y - window->frame_top);
+			       new_request.x - frame_width,
+			       new_request.y - frame_width);
 	    }
 	  else
 	    gdk_window_move (widget->window,
@@ -6567,12 +7894,58 @@ gtk_window_compute_hints (GtkWindow   *window,
  * Redrawing functions *
  ***********************/
 
+// This is just temporary, because it looks cool :)
 static void
 gtk_window_paint (GtkWidget     *widget,
 		  GdkRectangle *area)
 {
-  gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL, 
-		      GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
+  if (is_client_side_decorated (GTK_WINDOW (widget)))
+    {
+      gint frame_width, title_height;
+      gint extents_left, extents_top, extents_right, extents_bottom;
+
+      frame_width = title_height = extents_left = extents_right = extents_top = extents_bottom = 0;
+
+      if (is_client_side_decorated (GTK_WINDOW (widget)))
+        {
+          frame_width = get_decoration_frame_width (GTK_WINDOW (widget));
+          title_height = get_title_height (GTK_WINDOW (widget));
+
+          gtk_widget_style_get (widget,
+                                "decoration-border-width", &frame_width,
+                                "extents-left",            &extents_left,
+                                "extents-top",             &extents_top,
+                                "extents-right",           &extents_right,
+                                "extents-bottom",          &extents_bottom,
+                                NULL);
+        }
+
+      gtk_paint_box (widget->style,
+                     widget->window,
+                     GTK_STATE_NORMAL,
+		     GTK_SHADOW_OUT,
+                     area, widget,
+                     "decoration",
+                     extents_left,
+                     extents_top,
+                     -1,
+                     -1);
+
+      gtk_paint_flat_box (widget->style,
+                          widget->window,
+                          GTK_STATE_NORMAL,
+                          GTK_SHADOW_NONE,
+                          area,
+                          widget,
+                          "base",
+                          frame_width + extents_left,
+                          frame_width + title_height + extents_top,
+                          widget->allocation.width - 2 * frame_width - extents_left - extents_right,
+                          widget->allocation.height - 2 * frame_width - title_height - extents_top - extents_bottom);
+    }
+  else
+    gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
+                        GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
 }
 
 static gint
@@ -6581,7 +7954,7 @@ gtk_window_expose (GtkWidget      *widget,
 {
   if (!GTK_WIDGET_APP_PAINTABLE (widget))
     gtk_window_paint (widget, &event->area);
-  
+
   if (GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event)
     return GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event (widget, event);
 
@@ -6676,16 +8049,7 @@ gtk_window_set_frame_dimensions (GtkWindow *window,
   window->frame_right = right;
   window->frame_bottom = bottom;
 
-  if (GTK_WIDGET_REALIZED (widget) && window->frame)
-    {
-      gint width = widget->allocation.width + left + right;
-      gint height = widget->allocation.height + top + bottom;
-      gdk_window_resize (window->frame, width, height);
-      gtk_decorated_window_move_resize_window (window,
-					       left, top,
-					       widget->allocation.width,
-					       widget->allocation.height);
-    }
+  gtk_widget_queue_resize (GTK_WIDGET (window));
 }
 
 /**
diff --git a/gtk/gtkwindow.h b/gtk/gtkwindow.h
index dc59dfe..347d731 100644
--- a/gtk/gtkwindow.h
+++ b/gtk/gtkwindow.h
@@ -136,7 +136,7 @@ struct _GtkWindowClass
                                         GtkDirectionType direction);
   
   void	   (*keys_changed)	       (GtkWindow	*window);
-  
+
   /* Padding for future expansion */
   void (*_gtk_reserved1) (void);
   void (*_gtk_reserved2) (void);
@@ -271,6 +271,9 @@ void       gtk_window_get_frame_dimensions     (GtkWindow *window,
 void       gtk_window_set_decorated            (GtkWindow *window,
                                                 gboolean   setting);
 gboolean   gtk_window_get_decorated            (GtkWindow *window);
+void       gtk_window_set_client_side_decorations (GtkWindow       *window,
+                                                   GdkWMDecoration  decoration);
+void       gtk_window_disable_client_side_decorations (GtkWindow *window);
 void       gtk_window_set_deletable            (GtkWindow *window,
                                                 gboolean   setting);
 gboolean   gtk_window_get_deletable            (GtkWindow *window);
