[metacity] Build with gtk+-3.0 Most changes are copied from mutter 3.4.0. So thanks to mutter developers! They



commit a2013ae87a9c4a97e293964a0f3848d9425a65be
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Tue Jun 3 18:46:31 2014 +0300

    Build with gtk+-3.0
    Most changes are copied from mutter 3.4.0. So thanks to mutter
    developers! They done all hard work.
    This patch also removes unused functions.

 configure.ac                     |    9 +-
 src/core/errors.c                |  228 +---------
 src/core/iconcache.c             |   10 +-
 src/include/ui.h                 |   15 +-
 src/libmetacity-private.pc.in    |    2 +-
 src/tools/metacity-mag.c         |    9 +-
 src/tools/metacity-window-demo.c |   11 +-
 src/ui/draw-workspace.c          |   51 +--
 src/ui/draw-workspace.h          |    2 +-
 src/ui/fixedtip.c                |   20 +-
 src/ui/frames.c                  |  478 +++++++------------
 src/ui/frames.h                  |    4 +-
 src/ui/gradient.c                |  130 +++---
 src/ui/gradient.h                |   10 +-
 src/ui/menu.c                    |    2 +-
 src/ui/metaaccellabel.c          |  204 +++++----
 src/ui/preview-widget.c          |  228 +++------
 src/ui/preview-widget.h          |    4 -
 src/ui/tabpopup.c                |  144 +++----
 src/ui/testgradient.c            |  179 ++++----
 src/ui/theme-viewer.c            |   50 +-
 src/ui/theme.c                   |  970 ++++++++++----------------------------
 src/ui/theme.h                   |   94 +---
 src/ui/ui.c                      |  244 ++++------
 24 files changed, 1020 insertions(+), 2078 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 2099255..5b480b3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -108,13 +108,10 @@ if test "x$GCC" = "xyes"; then
 fi
 changequote([,])dnl
 
-dnl This used to purport to allow compilation against gtk3, but it doesn't actually
-dnl work; see https://bugzilla.gnome.org/show_bug.cgi?id=650513
-with_gtk=2.0
-GTK_API_VERSION=2.0
-GTK_MIN_VERSION=2.24.0
+GTK_API_VERSION=3.0
+GTK_MIN_VERSION=3.8.0
 GIO_MIN_VERSION=2.25.10
-CANBERRA_GTK=libcanberra-gtk
+CANBERRA_GTK=libcanberra-gtk3
 
 METACITY_PC_MODULES="gtk+-$GTK_API_VERSION >= $GTK_MIN_VERSION gio-2.0 >= $GIO_MIN_VERSION pango >= 1.2.0 
gsettings-desktop-schemas >= 3.3.0"
 AC_SUBST(GTK_API_VERSION)
diff --git a/src/core/errors.c b/src/core/errors.c
index 137fd6e..692d8fc 100644
--- a/src/core/errors.c
+++ b/src/core/errors.c
@@ -27,260 +27,40 @@
 #include <stdlib.h>
 #include <gdk/gdk.h>
 
-static int x_error_handler    (Display     *display,
-                               XErrorEvent *error);
-static int x_io_error_handler (Display     *display);
-
 void
 meta_errors_init (void)
 {
-  XSetErrorHandler (x_error_handler);
-  XSetIOErrorHandler (x_io_error_handler);
 }
 
-typedef struct ForeignDisplay ForeignDisplay;
-
-struct ForeignDisplay
-{
-    Display *dpy;
-    ErrorHandler handler;
-    gpointer data;
-    ForeignDisplay *next;
-};
-
-static ForeignDisplay *foreign_displays;
-
 void
 meta_errors_register_foreign_display (Display      *foreign_dpy,
                                      ErrorHandler  handler,
                                      gpointer      data)
 {
-    ForeignDisplay *info = g_new0 (ForeignDisplay, 1);
-    info->dpy = foreign_dpy;
-    info->handler = handler;
-    info->data = data;
-    info->next = foreign_displays;
-    foreign_displays = info;
-}
-
-static void
-meta_error_trap_push_internal (MetaDisplay *display,
-                               gboolean     need_sync)
-{
-  /* GDK resets the error handler on each push */
-  int (* old_error_handler) (Display     *,
-                             XErrorEvent *);
-
-  if (need_sync)
-    {
-      XSync (display->xdisplay, False);
-    }
-  
-  gdk_error_trap_push ();
-
-  /* old_error_handler will just be equal to x_error_handler
-   * for nested traps
-   */
-  old_error_handler = XSetErrorHandler (x_error_handler);
-  
-  /* Replace GDK handler, but save it so we can chain up */
-  if (display->error_trap_handler == NULL)
-    {
-      g_assert (display->error_traps == 0);
-      display->error_trap_handler = old_error_handler;
-      g_assert (display->error_trap_handler != x_error_handler);
-    }
-
-  display->error_traps += 1;
-
-  meta_topic (META_DEBUG_ERRORS, "%d traps remain\n", display->error_traps);
-}
-
-static int
-meta_error_trap_pop_internal  (MetaDisplay *display,
-                               gboolean     need_sync)
-{
-  int result;
-
-  g_assert (display->error_traps > 0);
-
-  if (need_sync)
-    {
-      XSync (display->xdisplay, False);
-    }
-
-  result = gdk_error_trap_pop ();
-
-  display->error_traps -= 1;
-  
-  if (display->error_traps == 0)
-    {
-      /* check that GDK put our handler back; this
-       * assumes that there are no pending GDK traps from GDK itself
-       */
-      
-      int (* restored_error_handler) (Display     *,
-                                      XErrorEvent *);
-
-      restored_error_handler = XSetErrorHandler (x_error_handler);
-
-      /* remove this */
-      display->error_trap_handler = NULL;
-    }
-
-  meta_topic (META_DEBUG_ERRORS, "%d traps\n", display->error_traps);
-  
-  return result;
 }
 
 void
 meta_error_trap_push (MetaDisplay *display)
 {
-  meta_error_trap_push_internal (display, FALSE);
+  gdk_error_trap_push ();
 }
 
 void
 meta_error_trap_pop (MetaDisplay *display,
                      gboolean     last_request_was_roundtrip)
 {
-  gboolean need_sync;
-
-  /* we only have to sync when popping the outermost trap */
-  need_sync = (display->error_traps == 1 && !last_request_was_roundtrip);
-
-  if (need_sync)
-    meta_topic (META_DEBUG_SYNC, "Syncing on error_trap_pop, traps = %d, roundtrip = %d\n",
-                display->error_traps, last_request_was_roundtrip);
-
-  display->error_trap_synced_at_last_pop = need_sync || last_request_was_roundtrip;
-  
-  meta_error_trap_pop_internal (display, need_sync);
+  gdk_error_trap_pop_ignored ();
 }
 
 void
 meta_error_trap_push_with_return (MetaDisplay *display)
 {
-  gboolean need_sync;
-
-  /* We don't sync on push_with_return if there are no traps
-   * currently, because we assume that any errors were either covered
-   * by a previous pop, or were fatal.
-   *
-   * More generally, we don't sync if we were synchronized last time
-   * we popped. This is known to be the case if there are no traps,
-   * but we also keep a flag so we know whether it's the case otherwise.
-   */
-
-  if (!display->error_trap_synced_at_last_pop)
-    need_sync = TRUE;
-  else
-    need_sync = FALSE;
-
-  if (need_sync)
-    meta_topic (META_DEBUG_SYNC, "Syncing on error_trap_push_with_return, traps = %d\n",
-                display->error_traps);
-  
-  meta_error_trap_push_internal (display, FALSE);
+  gdk_error_trap_push ();
 }
 
 int
 meta_error_trap_pop_with_return  (MetaDisplay *display,
                                   gboolean     last_request_was_roundtrip)
 {
-  if (!last_request_was_roundtrip)
-    meta_topic (META_DEBUG_SYNC, "Syncing on error_trap_pop_with_return, traps = %d, roundtrip = %d\n",
-                display->error_traps, last_request_was_roundtrip);
-
-  display->error_trap_synced_at_last_pop = TRUE;
-  
-  return meta_error_trap_pop_internal (display,
-                                       !last_request_was_roundtrip);
-}
-
-static int
-x_error_handler (Display     *xdisplay,
-                 XErrorEvent *error)
-{
-  int retval;
-  gchar buf[64];
-  MetaDisplay *display;
-  ForeignDisplay *foreign;
-
-  for (foreign = foreign_displays; foreign != NULL; foreign = foreign->next)
-  {
-      if (foreign->dpy == xdisplay)
-      {
-         foreign->handler (xdisplay, error, foreign->data);
-
-         return 0;
-      }
-  }
-  
-  XGetErrorText (xdisplay, error->error_code, buf, 63);  
-
-  display = meta_display_for_x_display (xdisplay);
-
-  /* Display can be NULL here because the compositing manager
-   * has its own Display, but Xlib only has one global error handler
-   */
-  if (display->error_traps > 0)
-    {
-      /* we're in an error trap, chain to the trap handler
-       * saved from GDK
-       */
-      meta_verbose ("X error: %s serial %ld error_code %d request_code %d minor_code %d)\n",
-                    buf,
-                    error->serial, 
-                    error->error_code, 
-                    error->request_code,
-                    error->minor_code);
-
-      g_assert (display->error_trap_handler != NULL);
-      g_assert (display->error_trap_handler != x_error_handler);
-      
-      retval = (* display->error_trap_handler) (xdisplay, error);
-    }
-  else
-    {
-      meta_bug ("Unexpected X error: %s serial %ld error_code %d request_code %d minor_code %d)\n",
-                buf,
-                error->serial, 
-                error->error_code, 
-                error->request_code,
-                error->minor_code);
-
-      retval = 1; /* compiler warning */
-    }
-
-  return retval;
-}
-
-static int
-x_io_error_handler (Display *xdisplay)
-{
-  MetaDisplay *display;
-
-  display = meta_display_for_x_display (xdisplay);
-
-  if (display == NULL)
-    meta_bug ("IO error received for unknown display?\n");
-  
-  if (errno == EPIPE)
-    {
-      meta_warning (_("Lost connection to the display '%s';\n"
-                      "most likely the X server was shut down or you killed/destroyed\n"
-                      "the window manager.\n"),
-                    display->name);
-    }
-  else
-    {
-      meta_warning (_("Fatal IO error %d (%s) on display '%s'.\n"),
-                    errno, g_strerror (errno),
-                    display->name);
-    }
-
-  /* Xlib would force an exit anyhow */
-  exit (1);
-  
-  return 0;
+  return gdk_error_trap_pop ();
 }
diff --git a/src/core/iconcache.c b/src/core/iconcache.c
index 055164e..70af354 100644
--- a/src/core/iconcache.c
+++ b/src/core/iconcache.c
@@ -392,17 +392,15 @@ try_pixmap_and_mask (MetaDisplay *display,
 
   get_pixmap_geometry (display, src_pixmap, &w, &h, NULL);
 
-  unscaled = meta_gdk_pixbuf_get_from_pixmap (NULL,
-                                              src_pixmap,
-                                              0, 0, 0, 0,
+  unscaled = meta_gdk_pixbuf_get_from_pixmap (src_pixmap,
+                                              0, 0,
                                               w, h);
 
   if (unscaled && src_mask != None)
     {
       get_pixmap_geometry (display, src_mask, &w, &h, NULL);
-      mask = meta_gdk_pixbuf_get_from_pixmap (NULL,
-                                              src_mask,
-                                              0, 0, 0, 0,
+      mask = meta_gdk_pixbuf_get_from_pixmap (src_mask,
+                                              0, 0,
                                               w, h);
     }
 
diff --git a/src/include/ui.h b/src/include/ui.h
index 36bb634..e2bb9ed 100644
--- a/src/include/ui.h
+++ b/src/include/ui.h
@@ -130,22 +130,9 @@ void            meta_ui_window_menu_popup (MetaWindowMenu     *menu,
 void            meta_ui_window_menu_free  (MetaWindowMenu     *menu);
 
 
-/* FIXME these lack a display arg */
-GdkPixbuf* meta_gdk_pixbuf_get_from_window (GdkPixbuf   *dest,
-                                            Window       xwindow,
+GdkPixbuf* meta_gdk_pixbuf_get_from_pixmap (Pixmap       xpixmap,
                                             int          src_x,
                                             int          src_y,
-                                            int          dest_x,
-                                            int          dest_y,
-                                            int          width,
-                                            int          height);
-
-GdkPixbuf* meta_gdk_pixbuf_get_from_pixmap (GdkPixbuf   *dest,
-                                            Pixmap       xpixmap,
-                                            int          src_x,
-                                            int          src_y,
-                                            int          dest_x,
-                                            int          dest_y,
                                             int          width,
                                             int          height);
 
diff --git a/src/libmetacity-private.pc.in b/src/libmetacity-private.pc.in
index 3f034b6..6ab5842 100644
--- a/src/libmetacity-private.pc.in
+++ b/src/libmetacity-private.pc.in
@@ -6,7 +6,7 @@ libgnome_serverdir= libexecdir@
 
 Name: libmetacity-private
 Description: Metacity internals shared 
-Requires: gtk+-2.0
+Requires: gtk+-3.0
 Version: @VERSION@
 Libs: -L${libdir} -lmetacity-private
 Cflags: -I${includedir}/metacity-1
diff --git a/src/tools/metacity-mag.c b/src/tools/metacity-mag.c
index 654e6a2..1fe6394 100644
--- a/src/tools/metacity-mag.c
+++ b/src/tools/metacity-mag.c
@@ -50,10 +50,9 @@ get_pixbuf (void)
            last_grab_width, last_grab_height);
 #endif
   
-  screenshot = gdk_pixbuf_get_from_drawable (NULL, gdk_get_default_root_window (),
-                                             NULL,
-                                             last_grab_x, last_grab_y, 0, 0,
-                                             last_grab_width, last_grab_height);
+  screenshot = gdk_pixbuf_get_from_window (gdk_get_default_root_window (),
+                                           last_grab_x, last_grab_y,
+                                           last_grab_width, last_grab_height);
 
   if (screenshot == NULL)
     {
@@ -189,7 +188,7 @@ key_press (GtkWidget   *invisible,
            GdkEventKey *event,
            gpointer     data)
 {  
-  if (event->keyval == GDK_Escape)
+  if (event->keyval == GDK_KEY_Escape)
     {
       shutdown_grab ();
 
diff --git a/src/tools/metacity-window-demo.c b/src/tools/metacity-window-demo.c
index 522b05d..25d3748 100644
--- a/src/tools/metacity-window-demo.c
+++ b/src/tools/metacity-window-demo.c
@@ -680,7 +680,7 @@ desktop_cb (GtkAction *action,
 {
   GtkWidget *window;
   GtkWidget *label;
-  GdkColor desktop_color;
+  GdkRGBA    desktop_color;
   
   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
   set_gtk_window_type (GTK_WINDOW (window), "_NET_WM_WINDOW_TYPE_DESKTOP");
@@ -689,11 +689,12 @@ desktop_cb (GtkAction *action,
                                gdk_screen_width (), gdk_screen_height ());
   gtk_window_move (GTK_WINDOW (window), 0, 0);
   
-  desktop_color.red = 0x5144;
-  desktop_color.green = 0x75D6;
-  desktop_color.blue = 0xA699;
+  desktop_color.red = 0.32;
+  desktop_color.green = 0.46;
+  desktop_color.blue = 0.65;
+  desktop_color.alpha = 1.0;
 
-  gtk_widget_modify_bg (window, GTK_STATE_NORMAL, &desktop_color);
+  gtk_widget_override_background_color (window, 0, &desktop_color);
   
   label = focus_label (window);
   
diff --git a/src/ui/draw-workspace.c b/src/ui/draw-workspace.c
index d36694b..6f96747 100644
--- a/src/ui/draw-workspace.c
+++ b/src/ui/draw-workspace.c
@@ -24,7 +24,7 @@
  */
 
 #include "draw-workspace.h"
-
+#include "theme.h"
 
 static void
 get_window_rect (const WnckWindowDisplayInfo *win,
@@ -65,33 +65,30 @@ get_window_rect (const WnckWindowDisplayInfo *win,
 
 static void
 draw_window (GtkWidget                   *widget,
-             GdkDrawable                 *drawable,
+             cairo_t                     *cr,
              const WnckWindowDisplayInfo *win,
              const GdkRectangle          *winrect,
              GtkStateType                state)
 {
-  cairo_t *cr;
   GdkPixbuf *icon;
   int icon_x, icon_y, icon_w, icon_h;
   gboolean is_active;
-  GdkColor *color;
-  GtkStyle *style;
+  GdkRGBA color;
+  GtkStyleContext *style;
 
   is_active = win->is_active;
-  
-  cr = gdk_cairo_create (drawable);
+
+  cairo_save (cr);
+
   cairo_rectangle (cr, winrect->x, winrect->y, winrect->width, winrect->height);
   cairo_clip (cr);
 
-  style = gtk_widget_get_style (widget);
+  style = gtk_widget_get_style_context (widget);
   if (is_active)
-    color = &style->light[state];
+    meta_gtk_style_get_light_color (style, state, &color);
   else
-    color = &style->bg[state];
-  cairo_set_source_rgb (cr,
-                        color->red / 65535.,
-                        color->green / 65535.,
-                        color->blue / 65535.);
+    gtk_style_context_get_background_color (style, state, &color);
+  gdk_cairo_set_source_rgba (cr, &color);
 
   cairo_rectangle (cr,
                    winrect->x + 1, winrect->y + 1,
@@ -142,27 +139,20 @@ draw_window (GtkWidget                   *widget,
       cairo_restore (cr);
     }
           
-  if (is_active)
-    color = &style->fg[state];
-  else
-    color = &style->fg[state];
-
-  cairo_set_source_rgb (cr,
-                        color->red / 65535.,
-                        color->green / 65535.,
-                        color->blue / 65535.);
+  gtk_style_context_get_color (style, state, &color);
+  gdk_cairo_set_source_rgba (cr, &color);
   cairo_set_line_width (cr, 1.0);
   cairo_rectangle (cr,
                    winrect->x + 0.5, winrect->y + 0.5,
                    MAX (0, winrect->width - 1), MAX (0, winrect->height - 1));
   cairo_stroke (cr);
   
-  cairo_destroy (cr);
+  cairo_restore (cr);
 }
 
 void
 wnck_draw_workspace (GtkWidget                   *widget,
-                     GdkDrawable                 *drawable,
+                     cairo_t                     *cr,
                      int                          x,
                      int                          y,
                      int                          width,
@@ -177,7 +167,6 @@ wnck_draw_workspace (GtkWidget                   *widget,
   int i;
   GdkRectangle workspace_rect;
   GtkStateType state;
-  cairo_t *cr;
 
   workspace_rect.x = x;
   workspace_rect.y = y;
@@ -191,8 +180,8 @@ wnck_draw_workspace (GtkWidget                   *widget,
   else
     state = GTK_STATE_NORMAL;
 
-  cr = gdk_cairo_create (drawable);
-  
+  cairo_save (cr);
+
   if (workspace_background)
     {
       gdk_cairo_set_source_pixbuf (cr, workspace_background, x, y);
@@ -205,8 +194,6 @@ wnck_draw_workspace (GtkWidget                   *widget,
       cairo_fill (cr);
     }
 
-  cairo_destroy (cr);
-  
   i = 0;
   while (i < n_windows)
     {
@@ -217,11 +204,13 @@ wnck_draw_workspace (GtkWidget                   *widget,
                        screen_height, &workspace_rect, &winrect);
       
       draw_window (widget,
-                   drawable,
+                   cr,
                    win,
                    &winrect,
                    state);
       
       ++i;
     }
+
+  cairo_restore (cr);
 }
diff --git a/src/ui/draw-workspace.h b/src/ui/draw-workspace.h
index efccde4..5c3a535 100644
--- a/src/ui/draw-workspace.h
+++ b/src/ui/draw-workspace.h
@@ -44,7 +44,7 @@ typedef struct
 } WnckWindowDisplayInfo;
 
 void wnck_draw_workspace (GtkWidget                   *widget,
-                          GdkDrawable                 *drawable,
+                          cairo_t                     *cr,
                           int                          x,
                           int                          y,
                           int                          width,
diff --git a/src/ui/fixedtip.c b/src/ui/fixedtip.c
index 91c2b09..2e94caa 100644
--- a/src/ui/fixedtip.c
+++ b/src/ui/fixedtip.c
@@ -49,12 +49,18 @@ static int screen_right_edge = 0;
 static int screen_bottom_edge = 0;
 
 static gint
-expose_handler (GtkTooltip *tooltips)
+draw_handler (GtkWidget *tooltips,
+              cairo_t   *cr,
+              gpointer   user_data)
 {
-  gtk_paint_flat_box (gtk_widget_get_style (tip), gtk_widget_get_window (tip),
-                      GTK_STATE_NORMAL, GTK_SHADOW_OUT, 
-                      NULL, tip, "tooltip",
-                      0, 0, -1, -1);
+  if (tooltips != NULL)
+    {
+      gtk_render_background (gtk_widget_get_style_context (tooltips),
+                             cr,
+                             0, 0,
+                             gtk_widget_get_allocated_width (tooltips),
+                             gtk_widget_get_allocated_height (tooltips));
+    }
 
   return FALSE;
 }
@@ -91,8 +97,8 @@ meta_fixed_tip_show (Display *xdisplay, int screen_number,
       gtk_widget_set_name (tip, "gtk-tooltips");
       gtk_container_set_border_width (GTK_CONTAINER (tip), 4);
 
-      g_signal_connect_swapped (tip, "expose_event",
-                                G_CALLBACK (expose_handler), NULL);
+      g_signal_connect_swapped (tip, "draw",
+                                G_CALLBACK (draw_handler), NULL);
 
       label = gtk_label_new (NULL);
       gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
diff --git a/src/ui/frames.c b/src/ui/frames.c
index eaa7652..7ea0ff2 100644
--- a/src/ui/frames.c
+++ b/src/ui/frames.c
@@ -33,20 +33,19 @@
 #include "prefs.h"
 #include "ui.h"
 
+#include <cairo-xlib.h>
+
 #ifdef HAVE_SHAPE
 #include <X11/extensions/shape.h>
 #endif
 
 #define DEFAULT_INNER_BUTTON_BORDER 3
 
-static void meta_frames_class_init (MetaFramesClass *klass);
-static void meta_frames_init       (MetaFrames      *frames);
-static void meta_frames_destroy    (GtkObject       *object);
-static void meta_frames_finalize   (GObject         *object);
-static void meta_frames_style_set  (GtkWidget       *widget,
-                                    GtkStyle        *prev_style);
-static void meta_frames_realize    (GtkWidget       *widget);
-static void meta_frames_unrealize  (GtkWidget       *widget);
+static void meta_frames_destroy       (GtkWidget *widget);
+static void meta_frames_finalize      (GObject   *object);
+static void meta_frames_style_updated (GtkWidget *widget);
+static void meta_frames_map           (GtkWidget *widget);
+static void meta_frames_unmap         (GtkWidget *widget);
 
 static void meta_frames_update_prelit_control (MetaFrames      *frames,
                                                MetaUIFrame     *frame,
@@ -59,8 +58,8 @@ static gboolean meta_frames_motion_notify_event   (GtkWidget           *widget,
                                                    GdkEventMotion      *event);
 static gboolean meta_frames_destroy_event         (GtkWidget           *widget,
                                                    GdkEventAny         *event);
-static gboolean meta_frames_expose_event          (GtkWidget           *widget,
-                                                   GdkEventExpose      *event);
+static gboolean meta_frames_draw                  (GtkWidget           *widget,
+                                                   cairo_t             *cr);
 static gboolean meta_frames_enter_notify_event    (GtkWidget           *widget,
                                                    GdkEventCrossing    *event);
 static gboolean meta_frames_leave_notify_event    (GtkWidget           *widget,
@@ -69,12 +68,9 @@ static gboolean meta_frames_leave_notify_event    (GtkWidget           *widget,
 static void meta_frames_attach_style (MetaFrames  *frames,
                                       MetaUIFrame *frame);
 
-static void meta_frames_paint_to_drawable (MetaFrames   *frames,
-                                           MetaUIFrame  *frame,
-                                           GdkDrawable  *drawable,
-                                           GdkRegion    *region,
-                                           int           x_offset,
-                                           int           y_offset);
+static void meta_frames_paint (MetaFrames  *frames,
+                               MetaUIFrame *frame,
+                               cairo_t     *cr);
 
 static void meta_frames_set_window_background (MetaFrames   *frames,
                                                MetaUIFrame  *frame);
@@ -104,8 +100,6 @@ static void invalidate_all_caches (MetaFrames *frames);
 static void invalidate_whole_window (MetaFrames *frames,
                                      MetaUIFrame *frame);
 
-static GtkWidgetClass *parent_class = NULL;
-
 G_DEFINE_TYPE (MetaFrames, meta_frames, GTK_TYPE_WINDOW);
 
 
@@ -117,7 +111,7 @@ meta_frames_constructor (GType                  gtype,
   GObject *object;
   GObjectClass *gobject_class;
 
-  gobject_class = G_OBJECT_CLASS (parent_class);
+  gobject_class = G_OBJECT_CLASS (meta_frames_parent_class);
   object = gobject_class->constructor (gtype, n_properties, properties);
 
   g_object_set (object,
@@ -131,25 +125,21 @@ static void
 meta_frames_class_init (MetaFramesClass *class)
 {
   GObjectClass   *gobject_class;
-  GtkObjectClass *object_class;
   GtkWidgetClass *widget_class;
 
   gobject_class = G_OBJECT_CLASS (class);
-  object_class = (GtkObjectClass*) class;
   widget_class = (GtkWidgetClass*) class;
 
-  parent_class = g_type_class_peek_parent (class);
-
   gobject_class->constructor = meta_frames_constructor;
   gobject_class->finalize = meta_frames_finalize;
-  object_class->destroy = meta_frames_destroy;
 
-  widget_class->style_set = meta_frames_style_set;
+  widget_class->destroy = meta_frames_destroy;
+  widget_class->style_updated = meta_frames_style_updated;
 
-  widget_class->realize = meta_frames_realize;
-  widget_class->unrealize = meta_frames_unrealize;
-  
-  widget_class->expose_event = meta_frames_expose_event;
+  widget_class->map = meta_frames_map;
+  widget_class->unmap = meta_frames_unmap;
+
+  widget_class->draw = meta_frames_draw;
   widget_class->destroy_event = meta_frames_destroy_event;  
   widget_class->button_press_event = meta_frames_button_press_event;
   widget_class->button_release_event = meta_frames_button_release_event;
@@ -225,13 +215,13 @@ listify_func (gpointer key, gpointer value, gpointer data)
 }
 
 static void
-meta_frames_destroy (GtkObject *object)
+meta_frames_destroy (GtkWidget *widget)
 {
   GSList *winlist;
   GSList *tmp;
   MetaFrames *frames;
   
-  frames = META_FRAMES (object);
+  frames = META_FRAMES (widget);
 
   clear_tip (frames);
   
@@ -249,7 +239,7 @@ meta_frames_destroy (GtkObject *object)
     }
   g_slist_free (winlist);
 
-  GTK_OBJECT_CLASS (parent_class)->destroy (object);
+  GTK_WIDGET_CLASS (meta_frames_parent_class)->destroy (widget);
 }
 
 static void
@@ -271,13 +261,13 @@ meta_frames_finalize (GObject *object)
   g_hash_table_destroy (frames->frames);
   g_hash_table_destroy (frames->cache);
 
-  G_OBJECT_CLASS (parent_class)->finalize (object);
+  G_OBJECT_CLASS (meta_frames_parent_class)->finalize (object);
 }
 
 typedef struct
 {
-  MetaRectangle rect;
-  GdkPixmap *pixmap;
+  cairo_rectangle_int_t rect;
+  cairo_surface_t *pixmap;
 } CachedFramePiece;
 
 typedef struct
@@ -429,8 +419,7 @@ reattach_style_func (gpointer key, gpointer value, gpointer data)
 }
 
 static void
-meta_frames_style_set  (GtkWidget *widget,
-                        GtkStyle  *prev_style)
+meta_frames_style_updated (GtkWidget *widget)
 {
   MetaFrames *frames;
 
@@ -441,7 +430,7 @@ meta_frames_style_set  (GtkWidget *widget,
   g_hash_table_foreach (frames->frames,
                         reattach_style_func, frames);
 
-  GTK_WIDGET_CLASS (parent_class)->style_set (widget, prev_style);
+  GTK_WIDGET_CLASS (meta_frames_parent_class)->style_updated (widget);
 }
 
 static void
@@ -583,12 +572,9 @@ meta_frames_attach_style (MetaFrames  *frames,
                           MetaUIFrame *frame)
 {
   if (frame->style != NULL)
-    gtk_style_detach (frame->style);
+    g_object_unref (frame->style);
 
-  /* Weirdly, gtk_style_attach() steals a reference count from the style passed in */
-  g_object_ref (gtk_widget_get_style (GTK_WIDGET (frames)));
-  frame->style = gtk_style_attach (gtk_widget_get_style (GTK_WIDGET (frames)),
-                                   frame->window);
+  frame->style = g_object_ref (gtk_widget_get_style_context (GTK_WIDGET (frames)));
 }
 
 void
@@ -659,7 +645,7 @@ meta_frames_unmanage_window (MetaFrames *frames,
       
       g_hash_table_remove (frames->frames, &frame->xwindow);
 
-      gtk_style_detach (frame->style);
+      g_object_unref (frame->style);
 
       gdk_window_destroy (frame->window);
 
@@ -676,17 +662,15 @@ meta_frames_unmanage_window (MetaFrames *frames,
 }
 
 static void
-meta_frames_realize (GtkWidget *widget)
+meta_frames_map (GtkWidget *widget)
 {
-  if (GTK_WIDGET_CLASS (parent_class)->realize)
-    GTK_WIDGET_CLASS (parent_class)->realize (widget);
+  gtk_widget_set_mapped (widget, TRUE);
 }
 
 static void
-meta_frames_unrealize (GtkWidget *widget)
+meta_frames_unmap (GtkWidget *widget)
 {
-  if (GTK_WIDGET_CLASS (parent_class)->unrealize)
-    GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
+  gtk_widget_set_mapped (widget, FALSE);
 }
 
 static MetaUIFrame*
@@ -1019,10 +1003,10 @@ meta_frames_move_resize_frame (MetaFrames *frames,
                                int         height)
 {
   MetaUIFrame *frame = meta_frames_lookup_window (frames, xwindow);
-  int old_x, old_y, old_width, old_height;
-  
-  gdk_drawable_get_size (frame->window, &old_width, &old_height);
-  gdk_window_get_position (frame->window, &old_x, &old_y);
+  int old_width, old_height;
+
+  old_width = gdk_window_get_width (frame->window);
+  old_height = gdk_window_get_height (frame->window);
 
   gdk_window_move_resize (frame->window, x, y, width, height);
 
@@ -1925,8 +1909,9 @@ meta_frames_motion_notify_event     (GtkWidget           *widget,
       {
         MetaFrameControl control;
         int x, y;
-        
-        gdk_window_get_pointer (frame->window, &x, &y, NULL);
+
+        gdk_window_get_device_position (frame->window, event->device,
+                                        &x, &y, NULL);
 
         /* Control is set to none unless it matches
          * the current grab
@@ -1966,8 +1951,9 @@ meta_frames_motion_notify_event     (GtkWidget           *widget,
       {
         MetaFrameControl control;
         int x, y;
-        
-        gdk_window_get_pointer (frame->window, &x, &y, NULL);
+
+        gdk_window_get_device_position (frame->window, event->device,
+                                        &x, &y, NULL);
 
         control = get_control (frames, frame, x, y);
 
@@ -2001,54 +1987,6 @@ meta_frames_destroy_event           (GtkWidget           *widget,
   return TRUE;
 }
 
-#if !GTK_CHECK_VERSION(2,21,6)
-/* Copied from GDK */
-static cairo_surface_t *
-_gdk_drawable_ref_cairo_surface (GdkDrawable *drawable)
-{
-  g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
-
-  return GDK_DRAWABLE_GET_CLASS (drawable)->ref_cairo_surface (drawable);
-}
-
-static cairo_pattern_t *
-gdk_window_get_background_pattern (GdkWindow *window)
-{
-  GdkWindowObject *private = (GdkWindowObject *) window;
-  cairo_pattern_t *pattern;
-
-  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
-
-  if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG)
-    pattern = NULL;
-  else if (private->bg_pixmap != GDK_NO_BG &&
-           private->bg_pixmap != NULL)
-    {
-      static cairo_user_data_key_t key;
-      cairo_surface_t *surface;
-
-      surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
-      pattern = cairo_pattern_create_for_surface (surface);
-      cairo_surface_destroy (surface);
-
-      cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
-      cairo_pattern_set_user_data (pattern,
-                                   &key,
-                                   g_object_ref (private->bg_pixmap),
-                                   g_object_unref);
-    }
-  else
-    {
-      pattern =
-        cairo_pattern_create_rgb (private->bg_color.red   / 65535.,
-                                  private->bg_color.green / 65535.,
-                                  private->bg_color.blue / 65535.);
-    }
-
-  return pattern;
-}
-#endif
-
 static void
 setup_bg_cr (cairo_t *cr, GdkWindow *window, int x_offset, int y_offset)
 {
@@ -2071,56 +2009,38 @@ setup_bg_cr (cairo_t *cr, GdkWindow *window, int x_offset, int y_offset)
     }
 }
 
-static void
-clear_backing (GdkPixmap *pixmap,
-               GdkWindow *window,
-               int xoffset, int yoffset)
-{
-  int width, height;
-  cairo_t *cr = gdk_cairo_create (pixmap);
-
-  setup_bg_cr (cr, window, xoffset, yoffset);
-
-  gdk_drawable_get_size (GDK_DRAWABLE (pixmap), &width, &height);
-  cairo_rectangle (cr, 0, 0, width, height);
-  cairo_fill (cr);
-
-  cairo_destroy (cr);
-}
-
 /* Returns a pixmap with a piece of the windows frame painted on it.
 */
 
-static GdkPixmap *
-generate_pixmap (MetaFrames *frames,
-                 MetaUIFrame *frame,
-                 MetaRectangle rect)
+static cairo_surface_t *
+generate_pixmap (MetaFrames            *frames,
+                 MetaUIFrame           *frame,
+                 cairo_rectangle_int_t *rect)
 {
-  GdkRectangle rectangle;
-  GdkRegion *region;
-  GdkPixmap *result;
+  cairo_surface_t *result;
+  cairo_t *cr;
 
-  rectangle.x = rect.x;
-  rectangle.y = rect.y;
-  rectangle.width = MAX (rect.width, 1);
-  rectangle.height = MAX (rect.height, 1);
-  
-  result = gdk_pixmap_new (frame->window,
-                           rectangle.width, rectangle.height, -1);
-  
-  clear_backing (result, frame->window, rectangle.x, rectangle.y);
+  /* do not create a pixmap for nonexisting areas */
+  if (rect->width <= 0 || rect->height <= 0)
+    return NULL;
+
+  result = gdk_window_create_similar_surface (frame->window,
+                                              CAIRO_CONTENT_COLOR,
+                                              rect->width, rect->height);
 
-  region = gdk_region_rectangle (&rectangle);
+  cr = cairo_create (result);
+  cairo_translate (cr, -rect->x, -rect->y);
 
-  meta_frames_paint_to_drawable (frames, frame, result, region,
-                                 -rectangle.x, -rectangle.y);
+  setup_bg_cr (cr, frame->window, 0, 0);
+  cairo_paint (cr);
 
-  gdk_region_destroy (region);
+  meta_frames_paint (frames, frame, cr);
+
+  cairo_destroy (cr);
 
   return result;
 }
 
-
 static void
 populate_cache (MetaFrames *frames,
                 MetaUIFrame *frame)
@@ -2185,7 +2105,7 @@ populate_cache (MetaFrames *frames,
     {
       CachedFramePiece *piece = &pixels->piece[i];
       if (!piece->pixmap)
-        piece->pixmap = generate_pixmap (frames, frame, piece->rect);
+        piece->pixmap = generate_pixmap (frames, frame, &piece->rect);
     }
   
   if (frames->invalidate_cache_timeout_id)
@@ -2199,11 +2119,11 @@ populate_cache (MetaFrames *frames,
 }
 
 static void
-clip_to_screen (GdkRegion *region, MetaUIFrame *frame)
+clip_to_screen (cairo_region_t *region, MetaUIFrame *frame)
 {
-  GdkRectangle frame_area;
-  GdkRectangle screen_area = { 0, 0, 0, 0 };
-  GdkRegion *tmp_region;
+  cairo_rectangle_int_t frame_area;
+  cairo_rectangle_int_t screen_area = { 0, 0, 0, 0 };
+  cairo_region_t *tmp_region;
   
   /* Chop off stuff outside the screen; this optimization
    * is crucial to handle huge client windows,
@@ -2218,71 +2138,90 @@ clip_to_screen (GdkRegion *region, MetaUIFrame *frame)
                  META_CORE_GET_SCREEN_HEIGHT, &screen_area.height,
                  META_CORE_GET_END);
 
-  gdk_region_offset (region, frame_area.x, frame_area.y);
+  cairo_region_translate (region, frame_area.x, frame_area.y);
 
-  tmp_region = gdk_region_rectangle (&frame_area);
-  gdk_region_intersect (region, tmp_region);
-  gdk_region_destroy (tmp_region);
+  tmp_region = cairo_region_create_rectangle (&frame_area);
+  cairo_region_intersect (region, tmp_region);
+  cairo_region_destroy (tmp_region);
 
-  gdk_region_offset (region, - frame_area.x, - frame_area.y);
+  tmp_region = cairo_region_create_rectangle (&screen_area);
+  cairo_region_intersect (region, tmp_region);
+  cairo_region_destroy (tmp_region);
+
+  cairo_region_translate (region, - frame_area.x, - frame_area.y);
 }
 
 static void
-subtract_from_region (GdkRegion *region, GdkDrawable *drawable,
-                      gint x, gint y)
+subtract_client_area (cairo_region_t *region,
+                      MetaUIFrame    *frame)
 {
-  GdkRectangle rect;
-  GdkRegion *reg_rect;
+  cairo_rectangle_int_t area;
+  MetaFrameFlags flags;
+  MetaFrameType type;
+  cairo_region_t *tmp_region;
+  Display *display;
+  
+  display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 
-  gdk_drawable_get_size (drawable, &rect.width, &rect.height);
-  rect.x = x;
-  rect.y = y;
+  meta_core_get (display, frame->xwindow,
+                 META_CORE_GET_FRAME_FLAGS, &flags,
+                 META_CORE_GET_FRAME_TYPE, &type,
+                 META_CORE_GET_CLIENT_WIDTH, &area.width,
+                 META_CORE_GET_CLIENT_HEIGHT, &area.height,
+                 META_CORE_GET_END);
+  meta_theme_get_frame_borders (meta_theme_get_current (),
+                         type, frame->text_height, flags, 
+                         &area.y, NULL, &area.x, NULL);
 
-  reg_rect = gdk_region_rectangle (&rect);
-  gdk_region_subtract (region, reg_rect);
-  gdk_region_destroy (reg_rect);
+  tmp_region = cairo_region_create_rectangle (&area);
+  cairo_region_subtract (region, tmp_region);
+  cairo_region_destroy (tmp_region);
 }
 
 static void
-cached_pixels_draw (CachedPixels *pixels,
-                    GdkWindow *window,
-                    GdkRegion *region)
+cached_pixels_draw (CachedPixels   *pixels,
+                    cairo_t        *cr,
+                    cairo_region_t *region)
 {
-  cairo_t *cr;
+  cairo_region_t *region_piece;
   int i;
 
-  cr = gdk_cairo_create (window);
-
   for (i = 0; i < 4; i++)
     {
       CachedFramePiece *piece;
       piece = &pixels->piece[i];
-      
+
       if (piece->pixmap)
         {
-          gdk_cairo_set_source_pixmap (cr, piece->pixmap,
-                                       piece->rect.x, piece->rect.y);
+          cairo_set_source_surface (cr, piece->pixmap,
+                                    piece->rect.x, piece->rect.y);
           cairo_paint (cr);
-          subtract_from_region (region, piece->pixmap,
-          piece->rect.x, piece->rect.y);
+
+          region_piece = cairo_region_create_rectangle (&piece->rect);
+          cairo_region_subtract (region, region_piece);
+          cairo_region_destroy (region_piece);
         }
     }
-  
-  cairo_destroy (cr);
 }
 
 static gboolean
-meta_frames_expose_event (GtkWidget           *widget,
-                          GdkEventExpose      *event)
+meta_frames_draw (GtkWidget *widget,
+                  cairo_t   *cr)
 {
   MetaUIFrame *frame;
   MetaFrames *frames;
-  GdkRegion *region;
   CachedPixels *pixels;
+  cairo_region_t *region;
+  cairo_rectangle_int_t clip;
+  int i, n_areas;
+  cairo_surface_t *target;
 
   frames = META_FRAMES (widget);
+  target = cairo_get_target (cr);
+  gdk_cairo_get_clip_rectangle (cr, &clip);
 
-  frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window));
+  g_assert (cairo_surface_get_type (target) == CAIRO_SURFACE_TYPE_XLIB);
+  frame = meta_frames_lookup_window (frames, cairo_xlib_surface_get_drawable (target));
   if (frame == NULL)
     return FALSE;
 
@@ -2295,17 +2234,40 @@ meta_frames_expose_event (GtkWidget           *widget,
 
   populate_cache (frames, frame);
 
-  region = gdk_region_copy (event->region);
+  region = cairo_region_create_rectangle (&clip);
   
   pixels = get_cache (frames, frame);
 
-  cached_pixels_draw (pixels, frame->window, region);
+  cached_pixels_draw (pixels, cr, region);
   
   clip_to_screen (region, frame);
-  meta_frames_paint_to_drawable (frames, frame, frame->window, region, 0, 0);
+  subtract_client_area (region, frame);
+
+  n_areas = cairo_region_num_rectangles (region);
+
+  for (i = 0; i < n_areas; i++)
+    {
+      cairo_rectangle_int_t area;
+
+      cairo_region_get_rectangle (region, i, &area);
+
+      cairo_save (cr);
+
+      cairo_rectangle (cr, area.x, area.y, area.width, area.height);
+      cairo_clip (cr);
+
+      cairo_push_group (cr);
+
+      meta_frames_paint (frames, frame, cr);
+
+      cairo_pop_group_to_source (cr);
+      cairo_paint (cr);
+
+      cairo_restore (cr);
+    }
+
+  cairo_region_destroy (region);
 
-  gdk_region_destroy (region);
-  
   return TRUE;
 }
 
@@ -2315,12 +2277,9 @@ meta_frames_expose_event (GtkWidget           *widget,
 #define DECORATING_BORDER 100
 
 static void
-meta_frames_paint_to_drawable (MetaFrames   *frames,
-                               MetaUIFrame  *frame,
-                               GdkDrawable  *drawable,
-                               GdkRegion    *region,
-                               int           x_offset,
-                               int           y_offset)
+meta_frames_paint (MetaFrames   *frames,
+                   MetaUIFrame  *frame,
+                   cairo_t      *cr)
 {
   GtkWidget *widget;
   MetaFrameFlags flags;
@@ -2333,14 +2292,16 @@ meta_frames_paint_to_drawable (MetaFrames   *frames,
   int i;
   MetaButtonLayout button_layout;
   MetaGrabOp grab_op;
-  
+  Display *display;
+
   widget = GTK_WIDGET (frames);
+  display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 
   for (i = 0; i < META_BUTTON_TYPE_LAST; i++)
     button_states[i] = META_BUTTON_STATE_NORMAL;
 
-  grab_frame = meta_core_get_grab_frame (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
-  grab_op = meta_core_get_grab_op (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
+  grab_frame = meta_core_get_grab_frame (display);
+  grab_op = meta_core_get_grab_op (display);
   if (grab_frame != frame->xwindow)
     grab_op = META_GRAB_OP_NONE;
   
@@ -2417,7 +2378,7 @@ meta_frames_paint_to_drawable (MetaFrames   *frames,
       break;
     }
 
-  meta_core_get (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), frame->xwindow,
+  meta_core_get (display, frame->xwindow,
                  META_CORE_GET_FRAME_FLAGS, &flags,
                  META_CORE_GET_FRAME_TYPE, &type,
                  META_CORE_GET_MINI_ICON, &mini_icon,
@@ -2430,107 +2391,18 @@ meta_frames_paint_to_drawable (MetaFrames   *frames,
 
   meta_prefs_get_button_layout (&button_layout);
 
-  if (G_LIKELY (GDK_IS_WINDOW (drawable)))
-    {
-      /* A window; happens about 2/3 of the time */
-
-      GdkRectangle area, *areas;
-      int n_areas;
-      int screen_width, screen_height;
-      GdkRegion *edges, *tmp_region;
-      int top, bottom, left, right;
- 
-      /* Repaint each side of the frame */
-
-      meta_theme_get_frame_borders (meta_theme_get_current (),
-                             type, frame->text_height, flags, 
-                             &top, &bottom, &left, &right);
-
-      meta_core_get (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), frame->xwindow,
-                     META_CORE_GET_SCREEN_WIDTH, &screen_width,
-                     META_CORE_GET_SCREEN_HEIGHT, &screen_height,
-                     META_CORE_GET_END);
-
-      edges = gdk_region_copy (region);
-
-      /* Punch out the client area */
-
-      area.x = left;
-      area.y = top;
-      area.width = w;
-      area.height = h;
-      tmp_region = gdk_region_rectangle (&area);
-      gdk_region_subtract (edges, tmp_region);
-      gdk_region_destroy (tmp_region);
-
-      /* Now draw remaining portion of region */
-
-      gdk_region_get_rectangles (edges, &areas, &n_areas);
-
-      for (i = 0; i < n_areas; i++)
-        {
-          /* Bug 399529: clamp areas[i] so that it doesn't go too far
-           * off the edge of the screen. This works around a GDK bug
-           * which makes gdk_window_begin_paint_rect cause an X error
-           * if the window is insanely huge. If the client is a GDK program
-           * and does this, it will still probably cause an X error in that
-           * program, but the last thing we want is for Metacity to crash
-           * because it attempted to decorate the silly window.
-           */
-
-          areas[i].x = MAX (areas[i].x, -DECORATING_BORDER); 
-          areas[i].y = MAX (areas[i].y, -DECORATING_BORDER); 
-          if (areas[i].x+areas[i].width  > screen_width  + DECORATING_BORDER)
-            areas[i].width  = MIN (0, screen_width  - areas[i].x);
-          if (areas[i].y+areas[i].height > screen_height + DECORATING_BORDER)
-            areas[i].height = MIN (0, screen_height - areas[i].y);
-
-          /* Okay, so let's start painting. */
-
-          gdk_window_begin_paint_rect (drawable, &areas[i]);
-
-          meta_theme_draw_frame_with_style (meta_theme_get_current (),
-            frame->style,
-            widget,
-            drawable,
-            NULL, /* &areas[i], */
-            x_offset, y_offset,
-            type,
-            flags,
-            w, h,
-            frame->layout,
-            frame->text_height,
-            &button_layout,
-            button_states,
-            mini_icon, icon);
-
-          gdk_window_end_paint (drawable);
-        }
-
-      g_free (areas);
-      gdk_region_destroy (edges);
-
-    }
-  else
-    {
-      /* Not a window; happens about 1/3 of the time */
-
-      meta_theme_draw_frame_with_style (meta_theme_get_current (),
-                                        frame->style,
-                                        widget,
-                                        drawable,
-                                        NULL,
-                                        x_offset, y_offset,
-                                        type,
-                                        flags,
-                                        w, h,
-                                        frame->layout,
-                                        frame->text_height,
-                                        &button_layout,
-                                        button_states,
-                                        mini_icon, icon);
-    }
-
+  meta_theme_draw_frame_with_style (meta_theme_get_current (),
+                                    frame->style,
+                                    widget,
+                                    cr,
+                                    type,
+                                    flags,
+                                    w, h,
+                                    frame->layout,
+                                    frame->text_height,
+                                    &button_layout,
+                                    button_states,
+                                    mini_icon, icon);
 }
 
 static void
@@ -2556,11 +2428,11 @@ meta_frames_set_window_background (MetaFrames   *frames,
 
   if (frame_exists && style->window_background_color != NULL)
     {
-      GdkColor color;
+      GdkRGBA color;
       GdkVisual *visual;
 
       meta_color_spec_render (style->window_background_color,
-                              GTK_WIDGET (frames),
+                              frame->style,
                               &color);
 
       /* Set A in ARGB to window_background_alpha, if we have ARGB */
@@ -2568,16 +2440,14 @@ meta_frames_set_window_background (MetaFrames   *frames,
       visual = gtk_widget_get_visual (GTK_WIDGET (frames));
       if (gdk_visual_get_depth (visual) == 32) /* we have ARGB */
         {
-          color.pixel = (color.pixel & 0xffffff) &
-            style->window_background_alpha << 24;
+          color.alpha = style->window_background_alpha / 255.0;
         }
 
-      gdk_window_set_background (frame->window, &color);
+      gdk_window_set_background_rgba (frame->window, &color);
     }
   else
     {
-      gtk_style_set_background (frame->style,
-                                frame->window, GTK_STATE_NORMAL);
+      gtk_style_context_set_background (frame->style, frame->window);
     }
  }
 
diff --git a/src/ui/frames.h b/src/ui/frames.h
index 6d03c19..1c949ca 100644
--- a/src/ui/frames.h
+++ b/src/ui/frames.h
@@ -73,7 +73,7 @@ struct _MetaUIFrame
 {
   Window xwindow;
   GdkWindow *window;
-  GtkStyle *style;
+  GtkStyleContext *style;
   MetaFrameStyle *cache_style;
   PangoLayout *layout;
   int text_height;
@@ -153,8 +153,6 @@ void meta_frames_queue_draw (MetaFrames *frames,
 
 void meta_frames_notify_menu_hide (MetaFrames *frames);
 
-Window meta_frames_get_moving_frame (MetaFrames *frames);
-
 void meta_frames_push_delay_exposes (MetaFrames *frames);
 void meta_frames_pop_delay_exposes  (MetaFrames *frames);
 
diff --git a/src/ui/gradient.c b/src/ui/gradient.c
index 5fc5e64..982faf9 100644
--- a/src/ui/gradient.c
+++ b/src/ui/gradient.c
@@ -29,27 +29,27 @@
  */
 static GdkPixbuf* meta_gradient_create_horizontal       (int             width,
                                                          int             height,
-                                                         const GdkColor *from,
-                                                         const GdkColor *to);
+                                                         const GdkRGBA  *from,
+                                                         const GdkRGBA  *to);
 static GdkPixbuf* meta_gradient_create_vertical         (int             width,
                                                          int             height,
-                                                         const GdkColor *from,
-                                                         const GdkColor *to);
+                                                         const GdkRGBA  *from,
+                                                         const GdkRGBA  *to);
 static GdkPixbuf* meta_gradient_create_diagonal         (int             width,
                                                          int             height,
-                                                         const GdkColor *from,
-                                                         const GdkColor *to);
+                                                         const GdkRGBA  *from,
+                                                         const GdkRGBA  *to);
 static GdkPixbuf* meta_gradient_create_multi_horizontal (int             width,
                                                          int             height,
-                                                         const GdkColor *colors,
+                                                         const GdkRGBA  *colors,
                                                          int             count);
 static GdkPixbuf* meta_gradient_create_multi_vertical   (int             width,
                                                          int             height,
-                                                         const GdkColor *colors,
+                                                         const GdkRGBA  *colors,
                                                          int             count);
 static GdkPixbuf* meta_gradient_create_multi_diagonal   (int             width,
                                                          int             height,
-                                                         const GdkColor *colors,
+                                                         const GdkRGBA  *colors,
                                                          int             count);
 
 
@@ -88,8 +88,8 @@ blank_pixbuf (int width, int height, gboolean no_padding)
 GdkPixbuf*
 meta_gradient_create_simple (int              width,
                              int              height,
-                             const GdkColor  *from,
-                             const GdkColor  *to,
+                             const GdkRGBA   *from,
+                             const GdkRGBA   *to,
                              MetaGradientType style)
 {
   switch (style)
@@ -114,7 +114,7 @@ meta_gradient_create_simple (int              width,
 GdkPixbuf*
 meta_gradient_create_multi (int              width,
                             int              height,
-                            const GdkColor  *colors,
+                            const GdkRGBA   *colors,
                             int              n_colors,
                             MetaGradientType style)
 {
@@ -156,9 +156,9 @@ meta_gradient_create_multi (int              width,
 GdkPixbuf*
 meta_gradient_create_interwoven (int            width,
                                  int            height,
-                                 const GdkColor colors1[2],
+                                 const GdkRGBA  colors1[2],
                                  int            thickness1,
-                                 const GdkColor colors2[2],
+                                 const GdkRGBA  colors2[2],
                                  int            thickness2)
 {
   
@@ -177,21 +177,21 @@ meta_gradient_create_interwoven (int            width,
   pixels = gdk_pixbuf_get_pixels (pixbuf);
   rowstride = gdk_pixbuf_get_rowstride (pixbuf);
   
-  r1 = colors1[0].red<<8;
-  g1 = colors1[0].green<<8;
-  b1 = colors1[0].blue<<8;
+  r1 = (long)(colors1[0].red*0xffffff);
+  g1 = (long)(colors1[0].green*0xffffff);
+  b1 = (long)(colors1[0].blue*0xffffff);
 
-  r2 = colors2[0].red<<8;
-  g2 = colors2[0].green<<8;
-  b2 = colors2[0].blue<<8;
+  r2 = (long)(colors2[0].red*0xffffff);
+  g2 = (long)(colors2[0].green*0xffffff);
+  b2 = (long)(colors2[0].blue*0xffffff);
 
-  dr1 = ((colors1[1].red-colors1[0].red)<<8)/(int)height;
-  dg1 = ((colors1[1].green-colors1[0].green)<<8)/(int)height;
-  db1 = ((colors1[1].blue-colors1[0].blue)<<8)/(int)height;
+  dr1 = ((colors1[1].red-colors1[0].red)*0xffffff)/(int)height;
+  dg1 = ((colors1[1].green-colors1[0].green)*0xffffff)/(int)height;
+  db1 = ((colors1[1].blue-colors1[0].blue)*0xffffff)/(int)height;
 
-  dr2 = ((colors2[1].red-colors2[0].red)<<8)/(int)height;
-  dg2 = ((colors2[1].green-colors2[0].green)<<8)/(int)height;
-  db2 = ((colors2[1].blue-colors2[0].blue)<<8)/(int)height;
+  dr2 = ((colors2[1].red-colors2[0].red)*0xffffff)/(int)height;
+  dg2 = ((colors2[1].green-colors2[0].green)*0xffffff)/(int)height;
+  db2 = ((colors2[1].blue-colors2[0].blue)*0xffffff)/(int)height;
 
   for (i=0,k=0,l=0,ll=thickness1; i<height; i++)
     {
@@ -255,8 +255,8 @@ meta_gradient_create_interwoven (int            width,
  */
 static GdkPixbuf*
 meta_gradient_create_horizontal (int width, int height,
-                                 const GdkColor *from,
-                                 const GdkColor *to)
+                                 const GdkRGBA  *from,
+                                 const GdkRGBA  *to)
 {    
   int i;
   long r, g, b, dr, dg, db;
@@ -275,12 +275,12 @@ meta_gradient_create_horizontal (int width, int height,
   ptr = pixels;
   rowstride = gdk_pixbuf_get_rowstride (pixbuf);
   
-  r0 = (guchar) (from->red / 256.0);
-  g0 = (guchar) (from->green / 256.0);
-  b0 = (guchar) (from->blue / 256.0);
-  rf = (guchar) (to->red / 256.0);
-  gf = (guchar) (to->green / 256.0);
-  bf = (guchar) (to->blue / 256.0);  
+  r0 = (guchar) (from->red * 0xff);
+  g0 = (guchar) (from->green * 0xff);
+  b0 = (guchar) (from->blue * 0xff);
+  rf = (guchar) (to->red * 0xff);
+  gf = (guchar) (to->green * 0xff);
+  bf = (guchar) (to->blue * 0xff);  
   
   r = r0 << 16;
   g = g0 << 16;
@@ -323,8 +323,8 @@ meta_gradient_create_horizontal (int width, int height,
  */
 static GdkPixbuf*
 meta_gradient_create_vertical (int width, int height,
-                               const GdkColor *from,
-                               const GdkColor *to)
+                               const GdkRGBA  *from,
+                               const GdkRGBA  *to)
 {
   int i, j;
   long r, g, b, dr, dg, db;
@@ -342,12 +342,12 @@ meta_gradient_create_vertical (int width, int height,
   pixels = gdk_pixbuf_get_pixels (pixbuf);
   rowstride = gdk_pixbuf_get_rowstride (pixbuf);
   
-  r0 = (guchar) (from->red / 256.0);
-  g0 = (guchar) (from->green / 256.0);
-  b0 = (guchar) (from->blue / 256.0);
-  rf = (guchar) (to->red / 256.0);
-  gf = (guchar) (to->green / 256.0);
-  bf = (guchar) (to->blue / 256.0);
+  r0 = (guchar) (from->red * 0xff);
+  g0 = (guchar) (from->green * 0xff);
+  b0 = (guchar) (from->blue * 0xff);
+  rf = (guchar) (to->red * 0xff);
+  gf = (guchar) (to->green * 0xff);
+  bf = (guchar) (to->blue * 0xff);
   
   r = r0<<16;
   g = g0<<16;
@@ -394,8 +394,8 @@ meta_gradient_create_vertical (int width, int height,
 
 static GdkPixbuf*
 meta_gradient_create_diagonal (int width, int height,
-                               const GdkColor *from,
-                               const GdkColor *to)
+                               const GdkRGBA  *from,
+                               const GdkRGBA  *to)
 {
   GdkPixbuf *pixbuf, *tmp;
   int j;
@@ -442,7 +442,7 @@ meta_gradient_create_diagonal (int width, int height,
 
 static GdkPixbuf*
 meta_gradient_create_multi_horizontal (int width, int height,
-                                       const GdkColor *colors,
+                                       const GdkRGBA  *colors,
                                        int count)
 {
   int i, j, k;
@@ -473,16 +473,16 @@ meta_gradient_create_multi_horizontal (int width, int height,
     
   k = 0;
 
-  r = colors[0].red << 8;
-  g = colors[0].green << 8;
-  b = colors[0].blue << 8;
+  r = (long)(colors[0].red * 0xffffff);
+  g = (long)(colors[0].green * 0xffffff);
+  b = (long)(colors[0].blue * 0xffffff);
 
   /* render the first line */
   for (i=1; i<count; i++)
     {
-      dr = ((int)(colors[i].red   - colors[i-1].red)  <<8)/(int)width2;
-      dg = ((int)(colors[i].green - colors[i-1].green)<<8)/(int)width2;
-      db = ((int)(colors[i].blue  - colors[i-1].blue) <<8)/(int)width2;
+      dr = (int)((colors[i].red   - colors[i-1].red)  *0xffffff)/(int)width2;
+      dg = (int)((colors[i].green - colors[i-1].green)*0xffffff)/(int)width2;
+      db = (int)((colors[i].blue  - colors[i-1].blue) *0xffffff)/(int)width2;
       for (j=0; j<width2; j++)
         {
           *ptr++ = (unsigned char)(r>>16);
@@ -493,9 +493,9 @@ meta_gradient_create_multi_horizontal (int width, int height,
           b += db;
           k++;
        }
-      r = colors[i].red << 8;
-      g = colors[i].green << 8;
-      b = colors[i].blue << 8;
+      r = (long)(colors[i].red   * 0xffffff);
+      g = (long)(colors[i].green * 0xffffff);
+      b = (long)(colors[i].blue  * 0xffffff);
     }
   for (j=k; j<width; j++)
     {
@@ -514,7 +514,7 @@ meta_gradient_create_multi_horizontal (int width, int height,
 
 static GdkPixbuf*
 meta_gradient_create_multi_vertical (int width, int height,
-                                     const GdkColor *colors,
+                                     const GdkRGBA  *colors,
                                      int count)
 {
   int i, j, k;
@@ -545,15 +545,15 @@ meta_gradient_create_multi_vertical (int width, int height,
     
   k = 0;
 
-  r = colors[0].red << 8;
-  g = colors[0].green << 8;
-  b = colors[0].blue << 8;
+  r = (long)(colors[0].red * 0xffffff);
+  g = (long)(colors[0].green * 0xffffff);
+  b = (long)(colors[0].blue * 0xffffff);
 
   for (i=1; i<count; i++)
     {
-      dr = ((int)(colors[i].red   - colors[i-1].red)  <<8)/(int)height2;
-      dg = ((int)(colors[i].green - colors[i-1].green)<<8)/(int)height2;
-      db = ((int)(colors[i].blue  - colors[i-1].blue) <<8)/(int)height2;
+      dr = (int)((colors[i].red   - colors[i-1].red)  *0xffffff)/(int)height2;
+      dg = (int)((colors[i].green - colors[i-1].green)*0xffffff)/(int)height2;
+      db = (int)((colors[i].blue  - colors[i-1].blue) *0xffffff)/(int)height2;
 
       for (j=0; j<height2; j++)
         {
@@ -572,9 +572,9 @@ meta_gradient_create_multi_vertical (int width, int height,
           b += db;
           k++;
        }
-      r = colors[i].red << 8;
-      g = colors[i].green << 8;
-      b = colors[i].blue << 8;
+      r = (long)(colors[i].red   * 0xffffff);
+      g = (long)(colors[i].green * 0xffffff);
+      b = (long)(colors[i].blue  * 0xffffff);
     }
 
   if (k<height)
@@ -604,7 +604,7 @@ meta_gradient_create_multi_vertical (int width, int height,
 
 static GdkPixbuf*
 meta_gradient_create_multi_diagonal (int width, int height,
-                                     const GdkColor *colors,
+                                     const GdkRGBA  *colors,
                                      int count)
 {
   GdkPixbuf *pixbuf, *tmp;
diff --git a/src/ui/gradient.h b/src/ui/gradient.h
index addd8f0..23ec094 100644
--- a/src/ui/gradient.h
+++ b/src/ui/gradient.h
@@ -35,19 +35,19 @@ typedef enum
 
 GdkPixbuf* meta_gradient_create_simple     (int               width,
                                             int               height,
-                                            const GdkColor   *from,
-                                            const GdkColor   *to,
+                                            const GdkRGBA    *from,
+                                            const GdkRGBA    *to,
                                             MetaGradientType  style);
 GdkPixbuf* meta_gradient_create_multi      (int               width,
                                             int               height,
-                                            const GdkColor   *colors,
+                                            const GdkRGBA    *colors,
                                             int               n_colors,
                                             MetaGradientType  style);
 GdkPixbuf* meta_gradient_create_interwoven (int               width,
                                             int               height,
-                                            const GdkColor    colors1[2],
+                                            const GdkRGBA     colors1[2],
                                             int               thickness1,
-                                            const GdkColor    colors2[2],
+                                            const GdkRGBA     colors2[2],
                                             int               thickness2);
 
 
diff --git a/src/ui/menu.c b/src/ui/menu.c
index 921bb95..4bad592 100644
--- a/src/ui/menu.c
+++ b/src/ui/menu.c
@@ -114,7 +114,7 @@ popup_position_func (GtkMenu   *menu,
 
   pos = user_data;
   
-  gtk_widget_size_request (GTK_WIDGET (menu), &req);
+  gtk_widget_get_preferred_size (GTK_WIDGET (menu), &req, NULL);
 
   *x = pos->x;
   *y = pos->y;
diff --git a/src/ui/metaaccellabel.c b/src/ui/metaaccellabel.c
index 0c7b852..2289ca6 100644
--- a/src/ui/metaaccellabel.c
+++ b/src/ui/metaaccellabel.c
@@ -35,38 +35,35 @@
 #include <string.h>
 #include "util.h"
 
-static void     meta_accel_label_class_init   (MetaAccelLabelClass *klass);
-static void     meta_accel_label_init         (MetaAccelLabel      *accel_label);
-static void     meta_accel_label_destroy      (GtkObject           *object);
+static void     meta_accel_label_destroy      (GtkWidget           *widget);
 static void     meta_accel_label_finalize     (GObject             *object);
-static void     meta_accel_label_size_request (GtkWidget           *widget,
-                                               GtkRequisition      *requisition);
-static gboolean meta_accel_label_expose_event (GtkWidget           *widget,
-                                               GdkEventExpose      *event);
+static void     meta_accel_label_get_preferred_width  (GtkWidget *widget,
+                                                       gint      *minimum,
+                                                       gint      *natural);
+static void     meta_accel_label_get_preferred_height (GtkWidget *widget,
+                                                       gint      *minimum,
+                                                       gint      *natural);
+static gboolean meta_accel_label_draw (GtkWidget *widget,
+                                       cairo_t   *cr);
 
 static void  meta_accel_label_update          (MetaAccelLabel *accel_label);
 static int   meta_accel_label_get_accel_width (MetaAccelLabel *accel_label);
 
-
-static GtkLabelClass *parent_class = NULL;
-
 G_DEFINE_TYPE (MetaAccelLabel, meta_accel_label, GTK_TYPE_LABEL);
 
 static void
 meta_accel_label_class_init (MetaAccelLabelClass *class)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
-  GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
 
-  parent_class = g_type_class_peek_parent (class);
-
   gobject_class->finalize = meta_accel_label_finalize;
 
-  object_class->destroy = meta_accel_label_destroy;
+  widget_class->destroy = meta_accel_label_destroy;
 
-  widget_class->size_request = meta_accel_label_size_request;
-  widget_class->expose_event = meta_accel_label_expose_event;
+  widget_class->get_preferred_width = meta_accel_label_get_preferred_width;
+  widget_class->get_preferred_height = meta_accel_label_get_preferred_height;
+  widget_class->draw = meta_accel_label_draw;
 
   class->signal_quote1 = g_strdup ("<:");
   class->signal_quote2 = g_strdup (":>");
@@ -160,9 +157,9 @@ meta_accel_label_new_with_mnemonic (const gchar *string)
 }
 
 static void
-meta_accel_label_destroy (GtkObject *object)
+meta_accel_label_destroy (GtkWidget *widget)
 {
-  MetaAccelLabel *accel_label = META_ACCEL_LABEL (object);
+  MetaAccelLabel *accel_label = META_ACCEL_LABEL (widget);
 
 
   g_free (accel_label->accel_string);
@@ -171,7 +168,7 @@ meta_accel_label_destroy (GtkObject *object)
   accel_label->accel_mods = 0;
   accel_label->accel_key = 0;
 
-  GTK_OBJECT_CLASS (parent_class)->destroy (object);
+  GTK_WIDGET_CLASS (meta_accel_label_parent_class)->destroy (widget);
 }
 
 static void
@@ -181,7 +178,7 @@ meta_accel_label_finalize (GObject *object)
 
   g_free (accel_label->accel_string);
 
-  G_OBJECT_CLASS (parent_class)->finalize (object);
+  G_OBJECT_CLASS (meta_accel_label_parent_class)->finalize (object);
 }
 
 void
@@ -211,15 +208,15 @@ meta_accel_label_get_accel_width (MetaAccelLabel *accel_label)
 }
 
 static void
-meta_accel_label_size_request (GtkWidget            *widget,
-                             GtkRequisition *requisition)
+meta_accel_label_get_preferred_width (GtkWidget *widget,
+                                      gint      *minimum,
+                                      gint      *natural)
 {
   MetaAccelLabel *accel_label = META_ACCEL_LABEL (widget);
   PangoLayout *layout;
   gint width;
 
-  if (GTK_WIDGET_CLASS (parent_class)->size_request)
-    GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition);
+  GTK_WIDGET_CLASS (meta_accel_label_parent_class)->get_preferred_width (widget, minimum, natural);
 
   layout = gtk_widget_create_pango_layout (widget, accel_label->accel_string);
   pango_layout_get_pixel_size (layout, &width, NULL);
@@ -228,85 +225,100 @@ meta_accel_label_size_request (GtkWidget      *widget,
   g_object_unref (G_OBJECT (layout));
 }
 
+static void
+meta_accel_label_get_preferred_height (GtkWidget *widget,
+                                       gint      *minimum,
+                                       gint      *natural)
+{
+  GTK_WIDGET_CLASS (meta_accel_label_parent_class)->get_preferred_height (widget, minimum, natural);
+}
+
+/* Mostly taken from GTK3. */
 static gboolean
-meta_accel_label_expose_event (GtkWidget      *widget,
-                             GdkEventExpose *event)
+meta_accel_label_draw (GtkWidget *widget,
+                       cairo_t   *cr)
 {
   MetaAccelLabel *accel_label = META_ACCEL_LABEL (widget);
   GtkMisc *misc = GTK_MISC (accel_label);
-  PangoLayout *layout;
-
-  if (gtk_widget_is_drawable (GTK_WIDGET (accel_label)))
+  GtkTextDirection direction;
+  int ac_width;
+  GtkAllocation allocation;
+  GtkRequisition requisition;
+
+  direction = gtk_widget_get_direction (widget);
+  ac_width = meta_accel_label_get_accel_width (accel_label);
+  gtk_widget_get_allocation (widget, &allocation);
+  gtk_widget_get_preferred_size (widget,
+                                 &requisition, NULL);
+
+  if (allocation.width >= requisition.width + ac_width)
     {
-      GtkAllocation allocation;
-      GtkRequisition requisition;
-      int ac_width;
-
-      gtk_widget_get_allocation (widget, &allocation);
-      gtk_widget_get_requisition (widget, &requisition);
-      ac_width = meta_accel_label_get_accel_width (accel_label);
-
-      if (allocation.width >= requisition.width + ac_width)
-       {
-          GtkTextDirection direction = gtk_widget_get_direction (widget);
-         gfloat xalign, yalign;
-         gint x, y;
-         gint xpad, ypad;
-
-         gtk_misc_get_padding (misc, &xpad, &ypad);
-         gtk_misc_get_alignment (misc, &xalign, &yalign);
-
-          if (direction == GTK_TEXT_DIR_RTL)
-            {
-              allocation.x += ac_width;
-            }
-         allocation.width -= ac_width;
-         gtk_widget_set_allocation (widget, &allocation);
-
-         if (GTK_WIDGET_CLASS (parent_class)->expose_event)
-           GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
-
-          if (direction == GTK_TEXT_DIR_RTL)
-            {
-              allocation.x -= ac_width;
-            }
-          allocation.width += ac_width;
-         gtk_widget_set_allocation (widget, &allocation);
-
-          if (direction == GTK_TEXT_DIR_RTL)
-            {
-              x = allocation.x + xpad;
-            }
-          else
-            {
-              x = allocation.x + allocation.width - xpad - ac_width;
-            }
-
-         y = (allocation.y * (1.0 - yalign) +
-              (allocation.y + allocation.height -
-               (requisition.height - ypad * 2)) * yalign) + 1.5;
-
-         layout = gtk_widget_create_pango_layout (widget, accel_label->accel_string);
-
-          gtk_paint_layout (gtk_widget_get_style (widget),
-                            gtk_widget_get_window (widget),
-                            gtk_widget_get_state (widget),
-                           FALSE,
-                            &event->area,
-                            widget,
-                            "accellabel",
-                            x, y,
-                            layout);
-
-          g_object_unref (G_OBJECT (layout));
-       }
+      GtkStyleContext *style;
+      PangoLayout *label_layout;
+      PangoLayout *accel_layout;
+      GtkLabel *label = GTK_LABEL (widget);
+      gint x, y, xpad, ypad;
+      gfloat xalign, yalign;
+
+      label_layout = gtk_label_get_layout (GTK_LABEL (accel_label));
+      gtk_misc_get_alignment (misc, &xalign, &yalign);
+
+      cairo_save (cr);
+
+      /* XXX: Mad hack: We modify the label's width so it renders
+       * properly in its draw function that we chain to. */
+      if (direction == GTK_TEXT_DIR_RTL)
+        cairo_translate (cr, ac_width, 0);
+      if (gtk_label_get_ellipsize (label))
+        pango_layout_set_width (label_layout,
+                                pango_layout_get_width (label_layout) 
+                                - ac_width * PANGO_SCALE);
+      
+      allocation.width -= ac_width;
+      gtk_widget_set_allocation (widget, &allocation);
+      if (GTK_WIDGET_CLASS (meta_accel_label_parent_class)->draw)
+        GTK_WIDGET_CLASS (meta_accel_label_parent_class)->draw (widget,
+                                                               cr);
+      allocation.width += ac_width;
+      gtk_widget_set_allocation (widget, &allocation);
+      if (gtk_label_get_ellipsize (label))
+        pango_layout_set_width (label_layout,
+                                pango_layout_get_width (label_layout) 
+                                + ac_width * PANGO_SCALE);
+
+      cairo_restore (cr);
+
+      gtk_misc_get_padding (misc, &xpad, &ypad);
+
+      if (direction == GTK_TEXT_DIR_RTL)
+        x = xpad;
       else
-       {
-         if (GTK_WIDGET_CLASS (parent_class)->expose_event)
-           GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
-       }
-    }
+        x = gtk_widget_get_allocated_width (widget) - xpad - ac_width;
+
+      gtk_label_get_layout_offsets (GTK_LABEL (accel_label), NULL, &y);
+
+      accel_layout = gtk_widget_create_pango_layout (widget, accel_label->accel_string);
+
+      y = (allocation.height - (requisition.height - ypad * 2)) * yalign + 1.5;
 
+      style = gtk_widget_get_style_context (widget);
+      gtk_style_context_save (style);
+      gtk_style_context_set_state (style,
+                                   gtk_widget_get_state_flags (widget));
+      gtk_render_layout (gtk_widget_get_style_context (widget),
+                         cr,
+                         x, y,
+                         accel_layout);
+      gtk_style_context_restore (style);
+
+      g_object_unref (accel_layout);
+    }
+  else
+    {
+      if (GTK_WIDGET_CLASS (meta_accel_label_parent_class)->draw)
+        GTK_WIDGET_CLASS (meta_accel_label_parent_class)->draw (widget, cr);
+    }
+  
   return FALSE;
 }
 
diff --git a/src/ui/preview-widget.c b/src/ui/preview-widget.c
index 34436cd..fe5d848 100644
--- a/src/ui/preview-widget.c
+++ b/src/ui/preview-widget.c
@@ -26,18 +26,18 @@
 #include <gtk/gtk.h>
 #include "preview-widget.h"
 
-static void     meta_preview_class_init    (MetaPreviewClass *klass);
-static void     meta_preview_init          (MetaPreview      *preview);
-static void     meta_preview_size_request  (GtkWidget        *widget,
-                                            GtkRequisition   *req);
+static void     meta_preview_get_preferred_width  (GtkWidget *widget,
+                                                   gint      *minimum,
+                                                   gint      *natural);
+static void     meta_preview_get_preferred_height (GtkWidget *widget,
+                                                   gint      *minimum,
+                                                   gint      *natural);
 static void     meta_preview_size_allocate (GtkWidget        *widget,
                                             GtkAllocation    *allocation);
-static gboolean meta_preview_expose        (GtkWidget        *widget,
-                                            GdkEventExpose   *event);
+static gboolean meta_preview_draw          (GtkWidget        *widget,
+                                            cairo_t          *cr);
 static void     meta_preview_finalize      (GObject          *object);
 
-static GtkWidgetClass *parent_class;
-
 G_DEFINE_TYPE (MetaPreview, meta_preview, GTK_TYPE_BIN);
 
 static void
@@ -47,13 +47,15 @@ meta_preview_class_init (MetaPreviewClass *class)
   GtkWidgetClass *widget_class;
 
   widget_class = (GtkWidgetClass*) class;
-  parent_class = g_type_class_peek (GTK_TYPE_BIN);
 
   gobject_class->finalize = meta_preview_finalize;
 
-  widget_class->expose_event = meta_preview_expose;
-  widget_class->size_request = meta_preview_size_request;
+  widget_class->draw = meta_preview_draw;
+  widget_class->get_preferred_width = meta_preview_get_preferred_width;
+  widget_class->get_preferred_height = meta_preview_get_preferred_height;
   widget_class->size_allocate = meta_preview_size_allocate;
+
+  gtk_container_class_handle_border_width (GTK_CONTAINER_CLASS (class));
 }
 
 static void
@@ -115,7 +117,7 @@ meta_preview_finalize (GObject *object)
   g_free (preview->title);
   preview->title = NULL;
   
-  G_OBJECT_CLASS (parent_class)->finalize (object);
+  G_OBJECT_CLASS (meta_preview_parent_class)->finalize (object);
 }
 
 static void
@@ -187,8 +189,8 @@ ensure_info (MetaPreview *preview)
 }
 
 static gboolean
-meta_preview_expose (GtkWidget      *widget,
-                     GdkEventExpose *event)
+meta_preview_draw (GtkWidget *widget,
+                   cairo_t   *cr)
 {
   MetaPreview *preview;
   GtkAllocation allocation;
@@ -204,12 +206,13 @@ meta_preview_expose (GtkWidget      *widget,
   };
   
   g_return_val_if_fail (META_IS_PREVIEW (widget), FALSE);
-  g_return_val_if_fail (event != NULL, FALSE);
 
   preview = META_PREVIEW (widget);
 
   ensure_info (preview);
 
+  cairo_save (cr);
+
   border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
   
   gtk_widget_get_allocation (widget, &allocation);
@@ -227,10 +230,7 @@ meta_preview_expose (GtkWidget      *widget,
       
       meta_theme_draw_frame (preview->theme,
                              widget,
-                             gtk_widget_get_window (widget),
-                             &event->area,
-                             allocation.x + border_width,
-                             allocation.y + border_width,
+                             cr,
                              preview->type,
                              preview->flags,
                              client_width, client_height,
@@ -242,47 +242,85 @@ meta_preview_expose (GtkWidget      *widget,
                              meta_preview_get_icon ());
     }
 
+  cairo_restore (cr);
+
   /* draw child */
-  return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
+  return GTK_WIDGET_CLASS (meta_preview_parent_class)->draw (widget, cr);
 }
 
+#define NO_CHILD_WIDTH 80
+#define NO_CHILD_HEIGHT 20
+
 static void
-meta_preview_size_request (GtkWidget      *widget,
-                           GtkRequisition *req)
+meta_preview_get_preferred_width (GtkWidget *widget,
+                                  gint      *minimum,
+                                  gint      *natural)
 {
   MetaPreview *preview;
+  int border_width;
   GtkWidget *child;
-  guint border_width;
 
   preview = META_PREVIEW (widget);
 
   ensure_info (preview);
 
-  req->width = preview->left_width + preview->right_width;
-  req->height = preview->top_height + preview->bottom_height;
-  
+  *minimum = *natural = preview->left_width + preview->right_width;
+
   child = gtk_bin_get_child (GTK_BIN (preview));
-  if (child &&
-      gtk_widget_get_visible (child))
+  if (child && gtk_widget_get_visible (child))
     {
-      GtkRequisition child_requisition;
+      gint child_min, child_nat;
 
-      gtk_widget_size_request (child, &child_requisition);
+      gtk_widget_get_preferred_width (child, &child_min, &child_nat);
 
-      req->width += child_requisition.width;
-      req->height += child_requisition.height;
+      *minimum += child_min;
+      *natural += child_nat;
     }
   else
     {
-#define NO_CHILD_WIDTH 80
-#define NO_CHILD_HEIGHT 20
-      req->width += NO_CHILD_WIDTH;
-      req->height += NO_CHILD_HEIGHT;
+      *minimum += NO_CHILD_WIDTH;
+      *natural += NO_CHILD_WIDTH;
     }
 
   border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
-  req->width += border_width * 2;
-  req->height += border_width * 2;
+  *minimum += border_width * 2;
+  *natural += border_width * 2;
+}
+
+static void
+meta_preview_get_preferred_height (GtkWidget *widget,
+                                   gint      *minimum,
+                                   gint      *natural)
+{
+  MetaPreview *preview;
+  int border_width;
+  GtkWidget *child;
+
+  preview = META_PREVIEW (widget);
+
+  ensure_info (preview);
+
+  *minimum = *natural = preview->top_height + preview->bottom_height;
+
+  child = gtk_bin_get_child (GTK_BIN (preview));
+  if (child && gtk_widget_get_visible (child))
+    {
+      gint child_min, child_nat;
+
+      gtk_widget_get_preferred_height (child, &child_min, &child_nat);
+
+      *minimum += child_min;
+      *natural += child_nat;
+    }
+  else
+    {
+      *minimum += NO_CHILD_HEIGHT;
+      *natural += NO_CHILD_HEIGHT;
+    }
+
+  border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+  *minimum += border_width * 2;
+  *natural += border_width * 2;
 }
 
 static void
@@ -461,117 +499,3 @@ meta_preview_get_mini_icon (void)
   
   return default_icon;
 }
-
-GdkRegion *
-meta_preview_get_clip_region (MetaPreview *preview, gint new_window_width, gint new_window_height)
-{
-  GdkRectangle xrect;
-  GdkRegion *corners_xregion, *window_xregion;
-  gint flags;
-  MetaFrameLayout *fgeom;
-  MetaFrameStyle *frame_style;
-
-  g_return_val_if_fail (META_IS_PREVIEW (preview), NULL);
-
-  flags = (META_PREVIEW (preview)->flags);
-
-  window_xregion = gdk_region_new ();
-
-  xrect.x = 0;
-  xrect.y = 0;
-  xrect.width = new_window_width;
-  xrect.height = new_window_height;
-
-  gdk_region_union_with_rect (window_xregion, &xrect);
-
-  if (preview->theme == NULL)
-    return window_xregion;
-
-  /* Otherwise, we do have a theme, so calculate the corners */
-  frame_style = meta_theme_get_frame_style (preview->theme,
-      META_FRAME_TYPE_NORMAL, flags);
-
-  fgeom = frame_style->layout;
-
-  corners_xregion = gdk_region_new ();
-
-  if (fgeom->top_left_corner_rounded_radius != 0)
-    {
-      const int corner = fgeom->top_left_corner_rounded_radius;
-      const float radius = sqrt(corner) + corner;
-      int i;
-
-      for (i=0; i<corner; i++)
-        {
-
-          const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5))));
-          xrect.x = 0;
-          xrect.y = i;
-          xrect.width = width;
-          xrect.height = 1;
-
-          gdk_region_union_with_rect (corners_xregion, &xrect);
-        }
-    }
-
-  if (fgeom->top_right_corner_rounded_radius != 0)
-    {
-      const int corner = fgeom->top_right_corner_rounded_radius;
-      const float radius = sqrt(corner) + corner;
-      int i;
-
-      for (i=0; i<corner; i++)
-        {
-          const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5))));
-          xrect.x = new_window_width - width;
-          xrect.y = i;
-          xrect.width = width;
-          xrect.height = 1;
-
-          gdk_region_union_with_rect (corners_xregion, &xrect);
-        }
-    }
-
-  if (fgeom->bottom_left_corner_rounded_radius != 0)
-    {
-      const int corner = fgeom->bottom_left_corner_rounded_radius;
-      const float radius = sqrt(corner) + corner;
-      int i;
-
-      for (i=0; i<corner; i++)
-        {
-          const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5))));
-          xrect.x = 0;
-          xrect.y = new_window_height - i - 1;
-          xrect.width = width;
-          xrect.height = 1;
-
-          gdk_region_union_with_rect (corners_xregion, &xrect);
-        }
-    }
-
-  if (fgeom->bottom_right_corner_rounded_radius != 0)
-    {
-      const int corner = fgeom->bottom_right_corner_rounded_radius;
-      const float radius = sqrt(corner) + corner;
-      int i;
-
-      for (i=0; i<corner; i++)
-        {
-          const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5))));
-          xrect.x = new_window_width - width;
-          xrect.y = new_window_height - i - 1;
-          xrect.width = width;
-          xrect.height = 1;
-
-          gdk_region_union_with_rect (corners_xregion, &xrect);
-        }
-    }
-
-  gdk_region_subtract (window_xregion, corners_xregion);
-  gdk_region_destroy (corners_xregion);
-
-  return window_xregion;
-}
-
-
diff --git a/src/ui/preview-widget.h b/src/ui/preview-widget.h
index ec220ab..c26a5c5 100644
--- a/src/ui/preview-widget.h
+++ b/src/ui/preview-widget.h
@@ -75,10 +75,6 @@ void meta_preview_set_frame_flags   (MetaPreview            *preview,
 void meta_preview_set_button_layout (MetaPreview            *preview,
                                      const MetaButtonLayout *button_layout);
 
-GdkRegion * meta_preview_get_clip_region (MetaPreview *preview,
-                                          gint new_window_width,
-                                          gint new_window_height);
-
 GdkPixbuf* meta_preview_get_icon (void);
 GdkPixbuf* meta_preview_get_mini_icon (void);
 
diff --git a/src/ui/tabpopup.c b/src/ui/tabpopup.c
index 71acf2f..4a96018 100644
--- a/src/ui/tabpopup.c
+++ b/src/ui/tabpopup.c
@@ -70,15 +70,12 @@ static void       select_workspace         (GtkWidget *widget);
 static void       unselect_workspace       (GtkWidget *widget);
 
 static gboolean
-outline_window_expose (GtkWidget      *widget,
-                       GdkEventExpose *event,
-                       gpointer        data)
+outline_window_draw (GtkWidget *widget,
+                     cairo_t   *cr,
+                     gpointer   data)
 {
   MetaTabPopup *popup;
   TabEntry *te;  
-  GtkStyle *style;
-  GdkWindow *window;
-  cairo_t *cr;
   
   popup = data;
 
@@ -86,12 +83,9 @@ outline_window_expose (GtkWidget      *widget,
     return FALSE;
 
   te = popup->current_selected_entry;
-  window = gtk_widget_get_window (widget);
-  style = gtk_widget_get_style (widget);
-  cr = gdk_cairo_create (window);
   
   cairo_set_line_width (cr, 1.0);
-  gdk_cairo_set_source_color (cr, &style->white);
+  cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
 
   cairo_rectangle (cr,
                    0.5, 0.5,
@@ -105,8 +99,6 @@ outline_window_expose (GtkWidget      *widget,
                    te->inner_rect.height + 1);
   cairo_stroke (cr);
 
-  cairo_destroy (cr);
-
   return FALSE;
 }
 
@@ -247,8 +239,8 @@ meta_ui_tab_popup_new (const MetaTabEntry *entries,
   gtk_widget_set_app_paintable (popup->outline_window, TRUE);
   gtk_widget_realize (popup->outline_window);
 
-  g_signal_connect (G_OBJECT (popup->outline_window), "expose_event",
-                    G_CALLBACK (outline_window_expose), popup);
+  g_signal_connect (G_OBJECT (popup->outline_window), "draw",
+                    G_CALLBACK (outline_window_draw), popup);
   
   popup->window = gtk_window_new (GTK_WINDOW_POPUP);
 
@@ -366,7 +358,7 @@ meta_ui_tab_popup_new (const MetaTabEntry *entries,
           /* Efficiency rules! */
           gtk_label_set_markup (GTK_LABEL (popup->label),
                               te->title);
-          gtk_widget_size_request (popup->label, &req);
+          gtk_widget_get_preferred_size (popup->label, &req, NULL);
           max_label_width = MAX (max_label_width, req.width);
           
           tmp = tmp->next;
@@ -454,8 +446,6 @@ display_entry (MetaTabPopup *popup,
                TabEntry     *te)
 {
   GdkRectangle rect;
-  GdkRegion *region;
-  GdkRegion *inner_region;
   GdkWindow *window;
 
   
@@ -476,6 +466,10 @@ display_entry (MetaTabPopup *popup,
 
   if (popup->outline)
     {
+      cairo_region_t *region;
+      cairo_region_t *inner_region;
+      GdkRGBA black = { 0.0, 0.0, 0.0, 1.0 };
+
       window = gtk_widget_get_window (popup->outline_window);
 
       /* Do stuff behind gtk's back */
@@ -490,19 +484,18 @@ display_entry (MetaTabPopup *popup,
                               te->rect.x, te->rect.y,
                               te->rect.width, te->rect.height);
   
-      gdk_window_set_background (window,
-                                 &gtk_widget_get_style (popup->outline_window)->black);
-  
-      region = gdk_region_rectangle (&rect);
-      inner_region = gdk_region_rectangle (&te->inner_rect);
-      gdk_region_subtract (region, inner_region);
-      gdk_region_destroy (inner_region);
+      gdk_window_set_background_rgba (window, &black);
+
+      region = cairo_region_create_rectangle (&rect);
+      inner_region = cairo_region_create_rectangle (&te->inner_rect);
+      cairo_region_subtract (region, inner_region);
+      cairo_region_destroy (inner_region);
   
       gdk_window_shape_combine_region (window,
                                        region,
                                        0, 0);
 
-      gdk_region_destroy (region);
+      cairo_region_destroy (region);
   
       /* This should piss off gtk a bit, but we don't want to raise
        * above the tab popup.  So, instead of calling gtk_widget_show,
@@ -646,8 +639,8 @@ unselect_image (GtkWidget *widget)
 }
 
 static void     meta_select_image_class_init   (MetaSelectImageClass *klass);
-static gboolean meta_select_image_expose_event (GtkWidget            *widget,
-                                                GdkEventExpose       *event);
+static gboolean meta_select_image_draw         (GtkWidget            *widget,
+                                                cairo_t              *cr);
 
 static GtkImageClass *parent_class;
 
@@ -686,74 +679,59 @@ meta_select_image_class_init (MetaSelectImageClass *klass)
 
   widget_class = GTK_WIDGET_CLASS (klass);
   
-  widget_class->expose_event = meta_select_image_expose_event;
+  widget_class->draw= meta_select_image_draw;
 }
 
 static gboolean
-meta_select_image_expose_event (GtkWidget      *widget,
-                                GdkEventExpose *event)
+meta_select_image_draw (GtkWidget *widget,
+                        cairo_t   *cr)
 {
+  GtkAllocation allocation;
+
+  gtk_widget_get_allocation (widget, &allocation);
+
   if (META_SELECT_IMAGE (widget)->selected)
     {
-      GtkAllocation allocation;
-      GtkRequisition requisition;
       GtkMisc *misc;
-      GtkStyle *style;
-      GtkStateType state;
-      GdkWindow *window;
+      GtkRequisition requisition;
+      GtkStyleContext *context;
+      GdkRGBA color;
       int x, y, w, h;
-      int xpad, ypad;
-      float xalign, yalign;
-      cairo_t *cr;
+      gint xpad, ypad;
+      gfloat xalign, yalign;
 
       misc = GTK_MISC (widget);
       
-      gtk_widget_get_allocation (widget, &allocation);
-      gtk_widget_get_requisition (widget, &requisition);
-      gtk_misc_get_padding (misc, &xpad, &ypad);
+      gtk_widget_get_preferred_size (widget, &requisition, 0);
       gtk_misc_get_alignment (misc, &xalign, &yalign);
+      gtk_misc_get_padding (misc, &xpad, &ypad);
 
-      x = (allocation.x * (1.0 - xalign) +
-           (allocation.x + allocation.width
-            - (requisition.width - xpad * 2)) * xalign) + 0.5;
-      y = (allocation.y * (1.0 - yalign) +
-           (allocation.y + allocation.height
-            - (requisition.height - ypad * 2)) * yalign) + 0.5;
+      x = (allocation.width - (requisition.width - xpad * 2)) * xalign + 0.5;
+      y = (allocation.height - (requisition.height - ypad * 2)) * yalign + 0.5;
 
       x -= INSIDE_SELECT_RECT + 1;
-      y -= INSIDE_SELECT_RECT + 1;      
+      y -= INSIDE_SELECT_RECT + 1;       
       
       w = requisition.width - OUTSIDE_SELECT_RECT * 2 - 1;
       h = requisition.height - OUTSIDE_SELECT_RECT * 2 - 1;
 
-      window = gtk_widget_get_window (widget);
-      style = gtk_widget_get_style (widget);
-      state = gtk_widget_get_state (widget);
-      cr = gdk_cairo_create (window);
+      context = gtk_widget_get_style_context (widget);
+
+      gtk_style_context_set_state (context,
+                                   gtk_widget_get_state_flags (widget));
+
+      gtk_style_context_lookup_color (context, "color", &color);
 
       cairo_set_line_width (cr, 2.0);
-      gdk_cairo_set_source_color (cr, &style->fg[state]);
+      cairo_set_source_rgb (cr, color.red, color.green, color.blue);
 
       cairo_rectangle (cr, x, y, w + 1, h + 1);
       cairo_stroke (cr);
 
       cairo_set_line_width (cr, 1.0);
-#if 0
-      gdk_cairo_set_source_color (cr, &style->bg[GTK_STATE_SELECTED]);
-      cairo_rectangle (cr, x, y, w, h);
-      cairo_fill (cr);
-#endif
-
-#if 0      
-      gtk_paint_focus (widget->style, widget->window,
-                       &event->area, widget, "meta-tab-image",
-                       x, y, w, h);
-#endif
-
-      cairo_destroy (cr);
     }
 
-  return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
+  return GTK_WIDGET_CLASS (parent_class)->draw (widget, cr);
 }
 
 #define META_TYPE_SELECT_WORKSPACE   (meta_select_workspace_get_type ())
@@ -817,8 +795,8 @@ unselect_workspace (GtkWidget *widget)
 
 static void meta_select_workspace_class_init (MetaSelectWorkspaceClass *klass);
 
-static gboolean meta_select_workspace_expose_event (GtkWidget      *widget,
-                                                    GdkEventExpose *event);
+static gboolean meta_select_workspace_draw (GtkWidget *widget,
+                                            cairo_t   *cr);
 
 GType
 meta_select_workspace_get_type (void)
@@ -856,7 +834,7 @@ meta_select_workspace_class_init (MetaSelectWorkspaceClass *klass)
   
   widget_class = GTK_WIDGET_CLASS (klass);
   
-  widget_class->expose_event = meta_select_workspace_expose_event;
+  widget_class->draw = meta_select_workspace_draw;
 }
 
 /**
@@ -894,15 +872,12 @@ meta_convert_meta_to_wnck (MetaWindow *window, MetaScreen *screen)
 
 
 static gboolean
-meta_select_workspace_expose_event (GtkWidget      *widget,
-                                    GdkEventExpose *event)
+meta_select_workspace_draw (GtkWidget *widget,
+                            cairo_t   *cr)
 {
   MetaWorkspace *workspace;
   WnckWindowDisplayInfo *windows;
   GtkAllocation allocation;
-  GtkStyle *style;
-  GdkWindow *window;
-  cairo_t *cr;
   int i, n_windows;
   GList *tmp, *list;
 
@@ -941,11 +916,10 @@ meta_select_workspace_expose_event (GtkWidget      *widget,
 
   g_list_free (list);
 
-  window = gtk_widget_get_window (widget);
   gtk_widget_get_allocation (widget, &allocation);
 
   wnck_draw_workspace (widget,
-                       window,
+                       cr,
                        SELECT_OUTLINE_WIDTH,
                        SELECT_OUTLINE_WIDTH,
                        allocation.width - SELECT_OUTLINE_WIDTH * 2,
@@ -961,20 +935,24 @@ meta_select_workspace_expose_event (GtkWidget      *widget,
   
   if (META_SELECT_WORKSPACE (widget)->selected)
     {
-      style = gtk_widget_get_style (widget);
-      cr = gdk_cairo_create (window);
+      GtkStyleContext *context;
+      GdkRGBA color;
+
+      context = gtk_widget_get_style_context (widget);
+
+      gtk_style_context_set_state (context,
+                                   gtk_widget_get_state_flags (widget));
+
+      gtk_style_context_lookup_color (context, "color", &color);
 
-      gdk_cairo_set_source_color (cr,
-                                  &style->fg[gtk_widget_get_state (widget)]);
       cairo_set_line_width (cr, SELECT_OUTLINE_WIDTH);
+      cairo_set_source_rgb (cr, color.red, color.green, color.blue);
 
       cairo_rectangle (cr,
                        SELECT_OUTLINE_WIDTH / 2.0, SELECT_OUTLINE_WIDTH / 2.0,
                        allocation.width - SELECT_OUTLINE_WIDTH,
                        allocation.height - SELECT_OUTLINE_WIDTH);
       cairo_stroke (cr);
-
-      cairo_destroy (cr);
     }
 
   return TRUE;
diff --git a/src/ui/testgradient.c b/src/ui/testgradient.c
index 33087c3..d24fc40 100644
--- a/src/ui/testgradient.c
+++ b/src/ui/testgradient.c
@@ -21,32 +21,30 @@
 #include "gradient.h"
 #include <gtk/gtk.h>
 
-typedef void (* RenderGradientFunc) (GdkDrawable *drawable,
-                                     cairo_t     *cr,
+typedef void (* RenderGradientFunc) (cairo_t     *cr,
                                      int          width,
                                      int          height);
 
 static void
-draw_checkerboard (GdkDrawable *drawable,
-                   int          width,
-                   int          height)
+draw_checkerboard (cairo_t *cr,
+                   int      width,
+                   int      height)
 {
   gint i, j, xcount, ycount;
-  GdkColor color1, color2;
-  cairo_t *cr;
+  GdkRGBA color1, color2;
   
 #define CHECK_SIZE 10
 #define SPACING 2  
   
-  color1.red = 30000;
-  color1.green = 30000;
-  color1.blue = 30000;
+  color1.red = 30000. / 65535.;
+  color1.green = 30000. / 65535.;
+  color1.blue = 30000. / 65535.;
+  color1.alpha = 1.0;
 
-  color2.red = 50000;
-  color2.green = 50000;
-  color2.blue = 50000;
-
-  cr = gdk_cairo_create (drawable);
+  color2.red = 50000. / 65535.;
+  color2.green = 50000. / 65535.;
+  color2.blue = 50000. / 65535.;
+  color2.alpha = 1.0;
 
   xcount = 0;
   i = SPACING;
@@ -57,9 +55,9 @@ draw_checkerboard (GdkDrawable *drawable,
       while (j < height)
        {
          if (ycount % 2)
-           gdk_cairo_set_source_color (cr, &color1);
+           gdk_cairo_set_source_rgba (cr, &color1);
          else
-           gdk_cairo_set_source_color (cr, &color2);
+           gdk_cairo_set_source_rgba (cr, &color2);
 
          /* If we're outside event->area, this will do nothing.
           * It might be mildly more efficient if we handled
@@ -75,22 +73,19 @@ draw_checkerboard (GdkDrawable *drawable,
       i += CHECK_SIZE + SPACING;
       ++xcount;
     }
-  
-  cairo_destroy (cr);
 }
 
 static void
-render_simple (GdkDrawable *drawable,
-               cairo_t     *cr,
+render_simple (cairo_t     *cr,
                int width, int height,
                MetaGradientType type,
                gboolean    with_alpha)
 {
   GdkPixbuf *pixbuf;
-  GdkColor from, to;
+  GdkRGBA from, to;
   
-  gdk_color_parse ("blue", &from);
-  gdk_color_parse ("green", &to);
+  gdk_rgba_parse (&from, "blue");
+  gdk_rgba_parse (&to, "green");
 
   pixbuf = meta_gradient_create_simple (width, height,
                                         &from, &to,
@@ -113,7 +108,7 @@ render_simple (GdkDrawable *drawable,
                                alphas, G_N_ELEMENTS (alphas),
                                META_GRADIENT_HORIZONTAL);
       
-      draw_checkerboard (drawable, width, height);
+      draw_checkerboard (cr, width, height);
     }
     
   gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
@@ -124,52 +119,47 @@ render_simple (GdkDrawable *drawable,
 }
 
 static void
-render_vertical_func (GdkDrawable *drawable,
-                      cairo_t *cr,
+render_vertical_func (cairo_t *cr,
                       int width, int height)
 {
-  render_simple (drawable, cr, width, height, META_GRADIENT_VERTICAL, FALSE);
+  render_simple (cr, width, height, META_GRADIENT_VERTICAL, FALSE);
 }
 
 static void
-render_horizontal_func (GdkDrawable *drawable,
-                        cairo_t *cr,
+render_horizontal_func (cairo_t *cr,
                         int width, int height)
 {
-  render_simple (drawable, cr, width, height, META_GRADIENT_HORIZONTAL, FALSE);
+  render_simple (cr, width, height, META_GRADIENT_HORIZONTAL, FALSE);
 }
 
 static void
-render_diagonal_func (GdkDrawable *drawable,
-                      cairo_t *cr,
+render_diagonal_func (cairo_t *cr,
                       int width, int height)
 {
-  render_simple (drawable, cr, width, height, META_GRADIENT_DIAGONAL, FALSE);
+  render_simple (cr, width, height, META_GRADIENT_DIAGONAL, FALSE);
 }
 
 static void
-render_diagonal_alpha_func (GdkDrawable *drawable,
-                            cairo_t *cr,
+render_diagonal_alpha_func (cairo_t *cr,
                             int width, int height)
 {
-  render_simple (drawable, cr, width, height, META_GRADIENT_DIAGONAL, TRUE);
+  render_simple (cr, width, height, META_GRADIENT_DIAGONAL, TRUE);
 }
 
 static void
-render_multi (GdkDrawable *drawable,
-              cairo_t     *cr,
+render_multi (cairo_t     *cr,
               int width, int height,
               MetaGradientType type)
 {
   GdkPixbuf *pixbuf;
 #define N_COLORS 5
-  GdkColor colors[N_COLORS];
+  GdkRGBA colors[N_COLORS];
 
-  gdk_color_parse ("red", &colors[0]);
-  gdk_color_parse ("blue", &colors[1]);
-  gdk_color_parse ("orange", &colors[2]);
-  gdk_color_parse ("pink", &colors[3]);
-  gdk_color_parse ("green", &colors[4]);
+  gdk_rgba_parse (&colors[0], "red");
+  gdk_rgba_parse (&colors[1], "blue");
+  gdk_rgba_parse (&colors[2], "orange");
+  gdk_rgba_parse (&colors[3], "pink");
+  gdk_rgba_parse (&colors[4], "green");
 
   pixbuf = meta_gradient_create_multi (width, height,
                                        colors, N_COLORS,
@@ -184,42 +174,38 @@ render_multi (GdkDrawable *drawable,
 }
 
 static void
-render_vertical_multi_func (GdkDrawable *drawable,
-                            cairo_t *cr,
+render_vertical_multi_func (cairo_t *cr,
                             int width, int height)
 {
-  render_multi (drawable, cr, width, height, META_GRADIENT_VERTICAL);
+  render_multi (cr, width, height, META_GRADIENT_VERTICAL);
 }
 
 static void
-render_horizontal_multi_func (GdkDrawable *drawable,
-                              cairo_t *cr,
+render_horizontal_multi_func (cairo_t *cr,
                               int width, int height)
 {
-  render_multi (drawable, cr, width, height, META_GRADIENT_HORIZONTAL);
+  render_multi (cr, width, height, META_GRADIENT_HORIZONTAL);
 }
 
 static void
-render_diagonal_multi_func (GdkDrawable *drawable,
-                            cairo_t *cr,
+render_diagonal_multi_func (cairo_t *cr,
                             int width, int height)
 {
-  render_multi (drawable, cr, width, height, META_GRADIENT_DIAGONAL);
+  render_multi (cr, width, height, META_GRADIENT_DIAGONAL);
 }
 
 static void
-render_interwoven_func (GdkDrawable *drawable,
-                        cairo_t     *cr,
+render_interwoven_func (cairo_t     *cr,
                         int width, int height)
 {
   GdkPixbuf *pixbuf;
 #define N_COLORS 4
-  GdkColor colors[N_COLORS];
+  GdkRGBA colors[N_COLORS];
 
-  gdk_color_parse ("red", &colors[0]);
-  gdk_color_parse ("blue", &colors[1]);
-  gdk_color_parse ("pink", &colors[2]);
-  gdk_color_parse ("green", &colors[3]);
+  gdk_rgba_parse (&colors[0], "red");
+  gdk_rgba_parse (&colors[1], "blue");
+  gdk_rgba_parse (&colors[2], "pink");
+  gdk_rgba_parse (&colors[3], "green");
 
   pixbuf = meta_gradient_create_interwoven (width, height,
                                             colors, height / 10,
@@ -233,31 +219,28 @@ render_interwoven_func (GdkDrawable *drawable,
 }
 
 static gboolean
-expose_callback (GtkWidget *widget,
-                 GdkEventExpose *event,
-                 gpointer data)
+draw_callback (GtkWidget *widget,
+               cairo_t   *cr,
+               gpointer   data)
 {
   RenderGradientFunc func = data;
-  GdkWindow *window;
-  GtkAllocation allocation;
-  GtkStyle *style;
-  cairo_t *cr;
+  GtkStyleContext *style;
+  GdkRGBA color;
 
-  style = gtk_widget_get_style (widget);
-  gtk_widget_get_allocation (widget, &allocation);
+  style = gtk_widget_get_style_context (widget);
 
-  window = gtk_widget_get_window (widget);
-  cr = gdk_cairo_create (window);
-  gdk_cairo_set_source_color (cr, &style->fg[gtk_widget_get_state (widget)]);
+  gtk_style_context_save (style);
+  gtk_style_context_set_state (style, gtk_widget_get_state_flags (widget));
+  gtk_style_context_lookup_color (style, "foreground-color", &color);
+  gtk_style_context_restore (style);
 
-  (* func) (window,
-            cr,
-            allocation.width,
-            allocation.height);
+  cairo_set_source_rgba (cr, color.red, color.green, color.blue, color.alpha);
 
-  cairo_destroy (cr);
+  (* func) (cr,
+            gtk_widget_get_allocated_width (widget),
+            gtk_widget_get_allocated_height (widget));
 
-  return TRUE;
+  return FALSE;
 }
 
 static GtkWidget*
@@ -278,8 +261,8 @@ create_gradient_window (const char *title,
   gtk_window_set_default_size (GTK_WINDOW (window), 175, 175);
   
   g_signal_connect (G_OBJECT (drawing_area),
-                    "expose_event",
-                    G_CALLBACK (expose_callback),
+                    "draw",
+                    G_CALLBACK (draw_callback),
                     func);
 
   gtk_container_add (GTK_CONTAINER (window), drawing_area);
@@ -292,31 +275,29 @@ create_gradient_window (const char *title,
 static void
 meta_gradient_test (void)
 {
-  GtkWidget *window;
-
-  window = create_gradient_window ("Simple vertical",
-                                   render_vertical_func);
+  create_gradient_window ("Simple vertical",
+                          render_vertical_func);
   
-  window = create_gradient_window ("Simple horizontal",
-                                   render_horizontal_func);
+  create_gradient_window ("Simple horizontal",
+                          render_horizontal_func);
 
-  window = create_gradient_window ("Simple diagonal",
-                                   render_diagonal_func);
+  create_gradient_window ("Simple diagonal",
+                          render_diagonal_func);
 
-  window = create_gradient_window ("Multi vertical",
-                                   render_vertical_multi_func);
+  create_gradient_window ("Multi vertical",
+                          render_vertical_multi_func);
   
-  window = create_gradient_window ("Multi horizontal",
-                                   render_horizontal_multi_func);
+  create_gradient_window ("Multi horizontal",
+                          render_horizontal_multi_func);
 
-  window = create_gradient_window ("Multi diagonal",
-                                   render_diagonal_multi_func);
+  create_gradient_window ("Multi diagonal",
+                          render_diagonal_multi_func);
 
-  window = create_gradient_window ("Interwoven",
-                                   render_interwoven_func);
+  create_gradient_window ("Interwoven",
+                          render_interwoven_func);
 
-  window = create_gradient_window ("Simple diagonal with horizontal multi alpha",
-                                   render_diagonal_alpha_func);
+  create_gradient_window ("Simple diagonal with horizontal multi alpha",
+                          render_diagonal_alpha_func);
 
 }
 
diff --git a/src/ui/theme-viewer.c b/src/ui/theme-viewer.c
index 0a9acbe..db76ec8 100644
--- a/src/ui/theme-viewer.c
+++ b/src/ui/theme-viewer.c
@@ -353,14 +353,15 @@ border_only_contents (void)
   GtkWidget *event_box;
   GtkWidget *vbox;
   GtkWidget *w;
-  GdkColor color;
+  GdkRGBA color;
 
   event_box = gtk_event_box_new ();
 
-  color.red = 40000;
+  color.red = 0.6;
   color.green = 0;
-  color.blue = 40000;
-  gtk_widget_modify_bg (event_box, GTK_STATE_NORMAL, &color);
+  color.blue = 0.6;
+  color.alpha = 1.0;
+  gtk_widget_override_background_color (event_box, 0, &color);
   
   vbox = gtk_vbox_new (FALSE, 0);
   gtk_container_set_border_width (GTK_CONTAINER (vbox), 3);
@@ -468,7 +469,7 @@ preview_collection (int font_size,
 {
   GtkWidget *box;
   GtkWidget *sw;
-  GdkColor desktop_color;
+  GdkRGBA desktop_color;
   int i;
   GtkWidget *eventbox;
 
@@ -486,11 +487,12 @@ preview_collection (int font_size,
   
   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), eventbox);
 
-  desktop_color.red = 0x5144;
-  desktop_color.green = 0x75D6;
-  desktop_color.blue = 0xA699;
+  desktop_color.red = 0.32;
+  desktop_color.green = 0.46;
+  desktop_color.blue = 0.65;
+  desktop_color.alpha = 1.0;
 
-  gtk_widget_modify_bg (eventbox, GTK_STATE_NORMAL, &desktop_color);
+  gtk_widget_override_background_color (eventbox, 0, &desktop_color);
 
   i = 0;
   while (i < META_FRAME_TYPE_LAST)
@@ -685,7 +687,7 @@ previews_of_button_layouts (void)
   static gboolean initted = FALSE;
   GtkWidget *box;
   GtkWidget *sw;
-  GdkColor desktop_color;
+  GdkRGBA desktop_color;
   int i;
   GtkWidget *eventbox;
   
@@ -709,11 +711,12 @@ previews_of_button_layouts (void)
   
   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), eventbox);
 
-  desktop_color.red = 0x5144;
-  desktop_color.green = 0x75D6;
-  desktop_color.blue = 0xA699;
+  desktop_color.red = 0.32;
+  desktop_color.green = 0.46;
+  desktop_color.blue = 0.65;
+  desktop_color.alpha = 1.0;
 
-  gtk_widget_modify_bg (eventbox, GTK_STATE_NORMAL, &desktop_color);
+  gtk_widget_override_background_color (eventbox, 0, &desktop_color);
 
   i = 0;
   while (i < BUTTON_LAYOUT_COMBINATIONS)
@@ -939,7 +942,7 @@ static void
 run_theme_benchmark (void)
 {
   GtkWidget* widget;
-  GdkPixmap *pixmap;
+  cairo_surface_t *pixmap;
   int top_height, bottom_height, left_width, right_width;
   MetaButtonState button_states[META_BUTTON_TYPE_LAST] =
   {
@@ -957,6 +960,7 @@ run_theme_benchmark (void)
 #define ITERATIONS 100
   int client_width;
   int client_height;
+  cairo_t *cr;
   int inc;
   
   widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
@@ -1002,16 +1006,15 @@ run_theme_benchmark (void)
       /* Creating the pixmap in the loop is right, since
        * GDK does the same with its double buffering.
        */
-      pixmap = gdk_pixmap_new (gtk_widget_get_window (widget),
-                               client_width + left_width + right_width,
-                               client_height + top_height + bottom_height,
-                               -1);
+      pixmap = gdk_window_create_similar_surface (gtk_widget_get_window (widget),
+                                                  CAIRO_CONTENT_COLOR,
+                                                  client_width + left_width + right_width,
+                                                  client_height + top_height + bottom_height);
+      cr = cairo_create (pixmap);
 
       meta_theme_draw_frame (global_theme,
                              widget,
-                             pixmap,
-                             NULL,
-                             0, 0,
+                             cr,
                              META_FRAME_TYPE_NORMAL,
                              get_flags (widget),
                              client_width, client_height,
@@ -1022,7 +1025,8 @@ run_theme_benchmark (void)
                              meta_preview_get_mini_icon (),
                              meta_preview_get_icon ());
 
-      g_object_unref (G_OBJECT (pixmap));
+      cairo_destroy (cr);
+      cairo_surface_destroy (pixmap);
       
       ++i;
       client_width += inc;
diff --git a/src/ui/theme.c b/src/ui/theme.c
index e92945a..b707036 100644
--- a/src/ui/theme.c
+++ b/src/ui/theme.c
@@ -63,14 +63,14 @@
 
 #define GDK_COLOR_RGBA(color)                                           \
                          ((guint32) (0xff                         |     \
-                                     (((color).red / 256) << 24)   |    \
-                                     (((color).green / 256) << 16) |    \
-                                     (((color).blue / 256) << 8)))
+                                     ((int)((color).red * 255) << 24)   |    \
+                                     ((int)((color).green * 255) << 16) |    \
+                                     ((int)((color).blue * 255) << 8)))
 
 #define GDK_COLOR_RGB(color)                                            \
-                         ((guint32) ((((color).red / 256) << 16)   |    \
-                                     (((color).green / 256) << 8)  |    \
-                                     (((color).blue / 256))))
+                         ((guint32) (((int)((color).red * 255) << 16)   |    \
+                                     ((int)((color).green * 255) << 8)  |    \
+                                     ((int)((color).blue * 255))))
 
 #define ALPHA_TO_UCHAR(d) ((unsigned char) ((d) * 255))
 
@@ -78,8 +78,8 @@
 #define CLAMP_UCHAR(v) ((guchar) (CLAMP (((int)v), (int)0, (int)255)))
 #define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
 
-static void gtk_style_shade            (GdkColor        *a,
-                                        GdkColor        *b,
+static void gtk_style_shade            (GdkRGBA         *a,
+                                        GdkRGBA         *b,
                                         gdouble          k);
 static void rgb_to_hls                 (gdouble         *r,
                                         gdouble         *g,
@@ -95,7 +95,7 @@ static MetaTheme *meta_current_theme = NULL;
 
 static GdkPixbuf *
 colorize_pixbuf (GdkPixbuf *orig,
-                 GdkColor  *new_color)
+                 GdkRGBA   *new_color)
 {
   GdkPixbuf *pixbuf;
   double intensity;
@@ -138,16 +138,16 @@ colorize_pixbuf (GdkPixbuf *orig,
           if (intensity <= 0.5)
             {
               /* Go from black at intensity = 0.0 to new_color at intensity = 0.5 */
-              dr = (new_color->red * intensity * 2.0) / 65535.0;
-              dg = (new_color->green * intensity * 2.0) / 65535.0;
-              db = (new_color->blue * intensity * 2.0) / 65535.0;
+              dr = new_color->red * intensity * 2.0;
+              dg = new_color->green * intensity * 2.0;
+              db = new_color->blue * intensity * 2.0;
             }
           else
             {
               /* Go from new_color at intensity = 0.5 to white at intensity = 1.0 */
-              dr = (new_color->red + (65535 - new_color->red) * (intensity - 0.5) * 2.0) / 65535.0;
-              dg = (new_color->green + (65535 - new_color->green) * (intensity - 0.5) * 2.0) / 65535.0;
-              db = (new_color->blue + (65535 - new_color->blue) * (intensity - 0.5) * 2.0) / 65535.0;
+              dr = new_color->red + (1.0 - new_color->red) * (intensity - 0.5) * 2.0;
+              dg = new_color->green + (1.0 - new_color->green) * (intensity - 0.5) * 2.0;
+              db = new_color->blue + (1.0 - new_color->blue) * (intensity - 0.5) * 2.0;
             }
           
           dest[0] = CLAMP_UCHAR (255 * dr);
@@ -172,18 +172,15 @@ colorize_pixbuf (GdkPixbuf *orig,
 }
 
 static void
-color_composite (const GdkColor *bg,
-                 const GdkColor *fg,
-                 double          alpha_d,
-                 GdkColor       *color)
+color_composite (const GdkRGBA *bg,
+                 const GdkRGBA *fg,
+                 double         alpha,
+                 GdkRGBA       *color)
 {
-  guint16 alpha;
-
   *color = *bg;
-  alpha = alpha_d * 0xffff;
-  color->red = color->red + (((fg->red - color->red) * alpha + 0x8000) >> 16);
-  color->green = color->green + (((fg->green - color->green) * alpha + 0x8000) >> 16);
-  color->blue = color->blue + (((fg->blue - color->blue) * alpha + 0x8000) >> 16);
+  color->red = color->red + (fg->red - color->red) * alpha;
+  color->green = color->green + (fg->green - color->green) * alpha;
+  color->blue = color->blue + (fg->blue - color->blue) * alpha;
 }
 
 /**
@@ -1007,12 +1004,12 @@ meta_gradient_spec_free (MetaGradientSpec *spec)
 
 GdkPixbuf*
 meta_gradient_spec_render (const MetaGradientSpec *spec,
-                           GtkWidget              *widget,
+                           GtkStyleContext        *style,
                            int                     width,
                            int                     height)
 {
   int n_colors;
-  GdkColor *colors;
+  GdkRGBA *colors;
   GSList *tmp;
   int i;
   GdkPixbuf *pixbuf;
@@ -1022,13 +1019,13 @@ meta_gradient_spec_render (const MetaGradientSpec *spec,
   if (n_colors == 0)
     return NULL;
 
-  colors = g_new (GdkColor, n_colors);
+  colors = g_new (GdkRGBA, n_colors);
 
   i = 0;
   tmp = spec->color_specs;
   while (tmp != NULL)
     {
-      meta_color_spec_render (tmp->data, widget, &colors[i]);
+      meta_color_spec_render (tmp->data, style, &colors[i]);
 
       tmp = tmp->next;
       ++i;
@@ -1361,7 +1358,7 @@ meta_color_spec_new_from_string (const char *str,
     {
       spec = meta_color_spec_new (META_COLOR_SPEC_BASIC);
       
-      if (!gdk_color_parse (str, &spec->data.basic.color))
+      if (!gdk_rgba_parse (&spec->data.basic.color, str))
         {
           g_set_error (err, META_THEME_ERROR,
                        META_THEME_ERROR_FAILED,
@@ -1391,18 +1388,80 @@ meta_color_spec_new_gtk (MetaGtkColorComponent component,
   return spec;
 }
 
+/* Based on set_color() in gtkstyle.c */
+#define LIGHTNESS_MULT 1.3
+#define DARKNESS_MULT  0.7
 void
-meta_color_spec_render (MetaColorSpec *spec,
-                        GtkWidget     *widget,
-                        GdkColor      *color)
+meta_gtk_style_get_light_color (GtkStyleContext *style,
+                                GtkStateFlags    state,
+                                GdkRGBA         *color)
 {
-  GtkStyle *widget_style;
+  gtk_style_context_get_background_color (style, state, color);
+  gtk_style_shade (color, color, LIGHTNESS_MULT);
+}
 
-  g_return_if_fail (spec != NULL);
-  g_return_if_fail (GTK_IS_WIDGET (widget));
+void
+meta_gtk_style_get_dark_color (GtkStyleContext *style,
+                               GtkStateFlags    state,
+                               GdkRGBA         *color)
+{
+  gtk_style_context_get_background_color (style, state, color);
+  gtk_style_shade (color, color, DARKNESS_MULT);
+}
+
+static void
+meta_set_color_from_style (GdkRGBA               *color,
+                           GtkStyleContext       *context,
+                           GtkStateFlags          state,
+                           MetaGtkColorComponent  component)
+{
+  GdkRGBA other;
+
+  switch (component)
+    {
+    case META_GTK_COLOR_BG:
+    case META_GTK_COLOR_BASE:
+      gtk_style_context_get_background_color (context, state, color);
+      break;
+    case META_GTK_COLOR_FG:
+    case META_GTK_COLOR_TEXT:
+      gtk_style_context_get_color (context, state, color);
+      break;
+    case META_GTK_COLOR_TEXT_AA:
+      gtk_style_context_get_color (context, state, color);
+      meta_set_color_from_style (&other, context, state, META_GTK_COLOR_BASE);
+
+      color->red = (color->red + other.red) / 2;
+      color->green = (color->green + other.green) / 2;
+      color->blue = (color->blue + other.blue) / 2;
+      break;
+    case META_GTK_COLOR_MID:
+      meta_gtk_style_get_light_color (context, state, color);
+      meta_gtk_style_get_dark_color (context, state, &other);
+
+      color->red = (color->red + other.red) / 2;
+      color->green = (color->green + other.green) / 2;
+      color->blue = (color->blue + other.blue) / 2;
+      break;
+    case META_GTK_COLOR_LIGHT:
+      meta_gtk_style_get_light_color (context, state, color);
+      break;
+    case META_GTK_COLOR_DARK:
+      meta_gtk_style_get_dark_color (context, state, color);
+      break;
+    case META_GTK_COLOR_LAST:
+      g_assert_not_reached ();
+      break;
+    }
+}
 
-  widget_style = gtk_widget_get_style (widget);
-  g_return_if_fail (widget_style != NULL);
+void
+meta_color_spec_render (MetaColorSpec *spec,
+                        GtkStyleContext *context,
+                        GdkRGBA         *color)
+{
+  g_return_if_fail (spec != NULL);
+  g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
 
   switch (spec->type)
     {
@@ -1411,44 +1470,18 @@ meta_color_spec_render (MetaColorSpec *spec,
       break;
 
     case META_COLOR_SPEC_GTK:
-      switch (spec->data.gtk.component)
-        {
-        case META_GTK_COLOR_BG:
-          *color = widget_style->bg[spec->data.gtk.state];
-          break;
-        case META_GTK_COLOR_FG:
-          *color = widget_style->fg[spec->data.gtk.state];
-          break;
-        case META_GTK_COLOR_BASE:
-          *color = widget_style->base[spec->data.gtk.state];
-          break;
-        case META_GTK_COLOR_TEXT:
-          *color = widget_style->text[spec->data.gtk.state];
-          break;
-        case META_GTK_COLOR_LIGHT:
-          *color = widget_style->light[spec->data.gtk.state];
-          break;
-        case META_GTK_COLOR_DARK:
-          *color = widget_style->dark[spec->data.gtk.state];
-          break;
-        case META_GTK_COLOR_MID:
-          *color = widget_style->mid[spec->data.gtk.state];
-          break;
-        case META_GTK_COLOR_TEXT_AA:
-          *color = widget_style->text_aa[spec->data.gtk.state];
-          break;
-        case META_GTK_COLOR_LAST:
-          g_assert_not_reached ();
-          break;
-        }
+      meta_set_color_from_style (color,
+                                 context,
+                                 spec->data.gtk.state,
+                                 spec->data.gtk.component);
       break;
 
     case META_COLOR_SPEC_BLEND:
       {
-        GdkColor bg, fg;
+        GdkRGBA bg, fg;
 
-        meta_color_spec_render (spec->data.blend.background, widget, &bg);
-        meta_color_spec_render (spec->data.blend.foreground, widget, &fg);
+        meta_color_spec_render (spec->data.blend.background, context, &bg);
+        meta_color_spec_render (spec->data.blend.foreground, context, &fg);
 
         color_composite (&bg, &fg, spec->data.blend.alpha, 
                          &spec->data.blend.color);
@@ -1459,7 +1492,7 @@ meta_color_spec_render (MetaColorSpec *spec,
 
     case META_COLOR_SPEC_SHADE:
       {
-        meta_color_spec_render (spec->data.shade.base, widget, 
+        meta_color_spec_render (spec->data.shade.base, context, 
                                 &spec->data.shade.color);
             
         gtk_style_shade (&spec->data.shade.color, 
@@ -3205,7 +3238,7 @@ scale_and_alpha_pixbuf (GdkPixbuf             *src,
 
 static GdkPixbuf*
 draw_op_as_pixbuf (const MetaDrawOp    *op,
-                   GtkWidget           *widget,
+                   GtkStyleContext     *context,
                    const MetaDrawInfo  *info,
                    int                  width,
                    int                  height)
@@ -3226,10 +3259,10 @@ draw_op_as_pixbuf (const MetaDrawOp    *op,
     case META_DRAW_RECTANGLE:
       if (op->data.rectangle.filled)
         {
-          GdkColor color;
+          GdkRGBA color;
 
           meta_color_spec_render (op->data.rectangle.color_spec,
-                                  widget,
+                                  context,
                                   &color);
 
           pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
@@ -3248,12 +3281,12 @@ draw_op_as_pixbuf (const MetaDrawOp    *op,
       
     case META_DRAW_TINT:
       {
-        GdkColor color;
+        GdkRGBA color;
         guint32 rgba;
         gboolean has_alpha;
 
         meta_color_spec_render (op->data.rectangle.color_spec,
-                                widget,
+                                context,
                                 &color);
 
         has_alpha =
@@ -3296,7 +3329,7 @@ draw_op_as_pixbuf (const MetaDrawOp    *op,
     case META_DRAW_GRADIENT:
       {
         pixbuf = meta_gradient_spec_render (op->data.gradient.gradient_spec,
-                                            widget, width, height);
+                                            context, width, height);
 
         pixbuf = apply_alpha (pixbuf,
                               op->data.gradient.alpha_spec,
@@ -3309,10 +3342,10 @@ draw_op_as_pixbuf (const MetaDrawOp    *op,
       {
        if (op->data.image.colorize_spec)
          {
-           GdkColor color;
+           GdkRGBA color;
 
             meta_color_spec_render (op->data.image.colorize_spec,
-                                    widget, &color);
+                                    context, &color);
             
             if (op->data.image.colorize_cache_pixbuf == NULL ||
                 op->data.image.colorize_cache_pixel != GDK_COLOR_RGB (color))
@@ -3433,35 +3466,28 @@ fill_env (MetaPositionExprEnv *env,
  */
 static void
 meta_draw_op_draw_with_env (const MetaDrawOp    *op,
-                            GtkStyle            *style_gtk,
+                            GtkStyleContext     *style_gtk,
                             GtkWidget           *widget,
-                            GdkDrawable         *drawable,
-                            const GdkRectangle  *clip,
+                            cairo_t             *cr,
                             const MetaDrawInfo  *info,
                             MetaRectangle        rect,
                             MetaPositionExprEnv *env)
 {
-  GdkColor color;
-  cairo_t *cr;
+  GdkRGBA color;
 
-  cr = gdk_cairo_create (drawable);
+  cairo_save (cr);
+  gtk_style_context_save (style_gtk);
 
   cairo_set_line_width (cr, 1.0);
 
-  if (clip)
-    {
-      gdk_cairo_rectangle (cr, clip);
-      cairo_clip (cr);
-    }
-  
   switch (op->type)
     {
     case META_DRAW_LINE:
       {
         int x1, x2, y1, y2;
 
-        meta_color_spec_render (op->data.line.color_spec, widget, &color);
-        gdk_cairo_set_source_color (cr, &color);
+        meta_color_spec_render (op->data.line.color_spec, style_gtk, &color);
+        gdk_cairo_set_source_rgba (cr, &color);
 
         if (op->data.line.width > 0)
           cairo_set_line_width (cr, op->data.line.width);
@@ -3548,8 +3574,8 @@ meta_draw_op_draw_with_env (const MetaDrawOp    *op,
       {
         int rx, ry, rwidth, rheight;
 
-        meta_color_spec_render (op->data.rectangle.color_spec, widget, &color);
-        gdk_cairo_set_source_color (cr, &color);
+        meta_color_spec_render (op->data.rectangle.color_spec, style_gtk, &color);
+        gdk_cairo_set_source_rgba (cr, &color);
 
         rx = parse_x_position_unchecked (op->data.rectangle.x, env);
         ry = parse_y_position_unchecked (op->data.rectangle.y, env);
@@ -3578,8 +3604,8 @@ meta_draw_op_draw_with_env (const MetaDrawOp    *op,
         double start_angle, end_angle;
         double center_x, center_y;
 
-        meta_color_spec_render (op->data.arc.color_spec, widget, &color);
-        gdk_cairo_set_source_color (cr, &color);
+        meta_color_spec_render (op->data.arc.color_spec, style_gtk, &color);
+        gdk_cairo_set_source_rgba (cr, &color);
 
         rx = parse_x_position_unchecked (op->data.arc.x, env);
         ry = parse_y_position_unchecked (op->data.arc.y, env);
@@ -3633,8 +3659,8 @@ meta_draw_op_draw_with_env (const MetaDrawOp    *op,
 
         if (!needs_alpha)
           {
-            meta_color_spec_render (op->data.tint.color_spec, widget, &color);
-            gdk_cairo_set_source_color (cr, &color);
+            meta_color_spec_render (op->data.tint.color_spec, style_gtk, &color);
+            gdk_cairo_set_source_rgba (cr, &color);
 
             cairo_rectangle (cr, rx, ry, rwidth, rheight);
             cairo_fill (cr);
@@ -3643,7 +3669,7 @@ meta_draw_op_draw_with_env (const MetaDrawOp    *op,
           {
             GdkPixbuf *pixbuf;
 
-            pixbuf = draw_op_as_pixbuf (op, widget, info,
+            pixbuf = draw_op_as_pixbuf (op, style_gtk, info,
                                         rwidth, rheight);
 
             if (pixbuf)
@@ -3667,7 +3693,7 @@ meta_draw_op_draw_with_env (const MetaDrawOp    *op,
         rwidth = parse_size_unchecked (op->data.gradient.width, env);
         rheight = parse_size_unchecked (op->data.gradient.height, env);
 
-        pixbuf = draw_op_as_pixbuf (op, widget, info,
+        pixbuf = draw_op_as_pixbuf (op, style_gtk, info,
                                     rwidth, rheight);
 
         if (pixbuf)
@@ -3694,7 +3720,7 @@ meta_draw_op_draw_with_env (const MetaDrawOp    *op,
         rwidth = parse_size_unchecked (op->data.image.width, env);
         rheight = parse_size_unchecked (op->data.image.height, env);
         
-        pixbuf = draw_op_as_pixbuf (op, widget, info,
+        pixbuf = draw_op_as_pixbuf (op, style_gtk, info,
                                     rwidth, rheight);
 
         if (pixbuf)
@@ -3713,22 +3739,35 @@ meta_draw_op_draw_with_env (const MetaDrawOp    *op,
     case META_DRAW_GTK_ARROW:
       {
         int rx, ry, rwidth, rheight;
+        double angle = 0, size;
 
         rx = parse_x_position_unchecked (op->data.gtk_arrow.x, env);
         ry = parse_y_position_unchecked (op->data.gtk_arrow.y, env);
         rwidth = parse_size_unchecked (op->data.gtk_arrow.width, env);
         rheight = parse_size_unchecked (op->data.gtk_arrow.height, env);
 
-        gtk_paint_arrow (style_gtk,
-                         drawable,
-                         op->data.gtk_arrow.state,
-                         op->data.gtk_arrow.shadow,
-                         (GdkRectangle*) clip,
-                         widget,
-                         "metacity",
-                         op->data.gtk_arrow.arrow,
-                         op->data.gtk_arrow.filled,
-                         rx, ry, rwidth, rheight);
+        size = MAX(rwidth, rheight);
+
+        switch (op->data.gtk_arrow.arrow)
+          {
+          case GTK_ARROW_UP:
+            angle = 0;
+            break;
+          case GTK_ARROW_RIGHT:
+            angle = M_PI / 2;
+            break;
+          case GTK_ARROW_DOWN:
+            angle = M_PI;
+            break;
+          case GTK_ARROW_LEFT:
+            angle = 3 * M_PI / 2;
+            break;
+          case GTK_ARROW_NONE:
+            return;
+          }
+
+        gtk_style_context_set_state (style_gtk, op->data.gtk_arrow.state);
+        gtk_render_arrow (style_gtk, cr, angle, rx, ry, size);
       }
       break;
 
@@ -3741,14 +3780,9 @@ meta_draw_op_draw_with_env (const MetaDrawOp    *op,
         rwidth = parse_size_unchecked (op->data.gtk_box.width, env);
         rheight = parse_size_unchecked (op->data.gtk_box.height, env);
 
-        gtk_paint_box (style_gtk,
-                       drawable,
-                       op->data.gtk_box.state,
-                       op->data.gtk_box.shadow,
-                       (GdkRectangle*) clip,
-                       widget,
-                       "metacity",
-                       rx, ry, rwidth, rheight);
+        gtk_style_context_set_state (style_gtk, op->data.gtk_box.state);
+        gtk_render_background (style_gtk, cr, rx, ry, rwidth, rheight);
+        gtk_render_frame (style_gtk, cr, rx, ry, rwidth, rheight);
       }
       break;
 
@@ -3760,13 +3794,8 @@ meta_draw_op_draw_with_env (const MetaDrawOp    *op,
         ry1 = parse_y_position_unchecked (op->data.gtk_vline.y1, env);
         ry2 = parse_y_position_unchecked (op->data.gtk_vline.y2, env);
         
-        gtk_paint_vline (style_gtk,
-                         drawable,
-                         op->data.gtk_vline.state,
-                         (GdkRectangle*) clip,
-                         widget,
-                         "metacity",
-                         ry1, ry2, rx);
+        gtk_style_context_set_state (style_gtk, op->data.gtk_vline.state);
+        gtk_render_line (style_gtk, cr, rx, ry1, rx, ry2);
       }
       break;
 
@@ -3778,7 +3807,7 @@ meta_draw_op_draw_with_env (const MetaDrawOp    *op,
         rwidth = parse_size_unchecked (op->data.icon.width, env);
         rheight = parse_size_unchecked (op->data.icon.height, env);
         
-        pixbuf = draw_op_as_pixbuf (op, widget, info,
+        pixbuf = draw_op_as_pixbuf (op, style_gtk, info,
                                     rwidth, rheight);
 
         if (pixbuf)
@@ -3799,8 +3828,8 @@ meta_draw_op_draw_with_env (const MetaDrawOp    *op,
         {
           int rx, ry;
 
-          meta_color_spec_render (op->data.title.color_spec, widget, &color);
-          gdk_cairo_set_source_color (cr, &color);
+          meta_color_spec_render (op->data.title.color_spec, style_gtk, &color);
+          gdk_cairo_set_source_rgba (cr, &color);
 
           rx = parse_x_position_unchecked (op->data.title.x, env);
           ry = parse_y_position_unchecked (op->data.title.y, env);
@@ -3820,7 +3849,7 @@ meta_draw_op_draw_with_env (const MetaDrawOp    *op,
         d_rect.height = parse_size_unchecked (op->data.op_list.height, env);
 
         meta_draw_op_list_draw_with_style (op->data.op_list.op_list,
-                                           style_gtk, widget, drawable, clip, info,
+                                           style_gtk, widget, cr, info,
                                            d_rect);
       }
       break;
@@ -3829,7 +3858,6 @@ meta_draw_op_draw_with_env (const MetaDrawOp    *op,
       {
         int rx, ry, rwidth, rheight;
         int tile_xoffset, tile_yoffset; 
-        GdkRectangle new_clip;
         MetaRectangle tile;
         
         rx = parse_x_position_unchecked (op->data.tile.x, env);
@@ -3837,78 +3865,43 @@ meta_draw_op_draw_with_env (const MetaDrawOp    *op,
         rwidth = parse_size_unchecked (op->data.tile.width, env);
         rheight = parse_size_unchecked (op->data.tile.height, env);
 
-        new_clip.x = rx;
-        new_clip.y = ry;
-        new_clip.width = rwidth;
-        new_clip.height = rheight;
+        cairo_save (cr);
 
-        if (clip == NULL || gdk_rectangle_intersect ((GdkRectangle*)clip, &new_clip,
-                                                     &new_clip))
-          {
-            tile_xoffset = parse_x_position_unchecked (op->data.tile.tile_xoffset, env);
-            tile_yoffset = parse_y_position_unchecked (op->data.tile.tile_yoffset, env);
-            /* tile offset should not include x/y */
-            tile_xoffset -= rect.x;
-            tile_yoffset -= rect.y;
-            
-            tile.width = parse_size_unchecked (op->data.tile.tile_width, env);
-            tile.height = parse_size_unchecked (op->data.tile.tile_height, env);
+        cairo_rectangle (cr, rx, ry, rwidth, rheight);
+        cairo_clip (cr);
 
-            tile.x = rx - tile_xoffset;
+        tile_xoffset = parse_x_position_unchecked (op->data.tile.tile_xoffset, env);
+        tile_yoffset = parse_y_position_unchecked (op->data.tile.tile_yoffset, env);
+        /* tile offset should not include x/y */
+        tile_xoffset -= rect.x;
+        tile_yoffset -= rect.y;
         
-            while (tile.x < (rx + rwidth))
-              {
-                tile.y = ry - tile_yoffset;
-                while (tile.y < (ry + rheight))
-                  {
-                    meta_draw_op_list_draw_with_style (op->data.tile.op_list,
-                                                       style_gtk, widget, drawable, &new_clip, info,
-                                                       tile);
+        tile.width = parse_size_unchecked (op->data.tile.tile_width, env);
+        tile.height = parse_size_unchecked (op->data.tile.tile_height, env);
 
-                    tile.y += tile.height;
-                  }
+        tile.x = rx - tile_xoffset;
+    
+        while (tile.x < (rx + rwidth))
+          {
+            tile.y = ry - tile_yoffset;
+            while (tile.y < (ry + rheight))
+              {
+                meta_draw_op_list_draw_with_style (op->data.tile.op_list,
+                                                   style_gtk, widget, cr, info,
+                                        tile);
 
-                tile.x += tile.width;
+                tile.y += tile.height;
               }
+
+            tile.x += tile.width;
           }
+        cairo_restore (cr);
       }
       break;
     }
 
-  cairo_destroy (cr);
-}
-
-void
-meta_draw_op_draw_with_style (const MetaDrawOp    *op,
-                              GtkStyle            *style_gtk,
-                              GtkWidget           *widget,
-                              GdkDrawable         *drawable,
-                              const GdkRectangle  *clip,
-                              const MetaDrawInfo  *info,
-                              MetaRectangle        logical_region)
-{
-  MetaPositionExprEnv env;
-
-  g_return_if_fail (style_gtk->colormap == gdk_drawable_get_colormap (drawable));
-
-  fill_env (&env, info, logical_region);
-
-  meta_draw_op_draw_with_env (op, style_gtk, widget, drawable, clip,
-                              info, logical_region,
-                              &env);
-
-}
-
-void
-meta_draw_op_draw (const MetaDrawOp    *op,
-                   GtkWidget           *widget,
-                   GdkDrawable         *drawable,
-                   const GdkRectangle  *clip,
-                   const MetaDrawInfo  *info,
-                   MetaRectangle        logical_region)
-{
-  meta_draw_op_draw_with_style (op, gtk_widget_get_style (widget), widget,
-                                drawable, clip, info, logical_region);
+   cairo_restore (cr);
+   gtk_style_context_restore (style_gtk);
 }
 
 MetaDrawOpList*
@@ -3960,23 +3953,15 @@ meta_draw_op_list_unref (MetaDrawOpList *op_list)
 
 void
 meta_draw_op_list_draw_with_style  (const MetaDrawOpList *op_list,
-                                    GtkStyle             *style_gtk,
+                                    GtkStyleContext      *style_gtk,
                                     GtkWidget            *widget,
-                                    GdkDrawable          *drawable,
-                                    const GdkRectangle   *clip,
+                                    cairo_t              *cr,
                                     const MetaDrawInfo   *info,
                                     MetaRectangle         rect)
 {
   int i;
-  GdkRectangle active_clip;
-  GdkRectangle orig_clip;
   MetaPositionExprEnv env;
 
-  g_return_if_fail (style_gtk->colormap == gdk_drawable_get_colormap (drawable));
-
-  if (op_list->n_ops == 0)
-    return;
-  
   fill_env (&env, info, rect);
   
   /* FIXME this can be optimized, potentially a lot, by
@@ -3990,19 +3975,7 @@ meta_draw_op_list_draw_with_style  (const MetaDrawOpList *op_list,
    * evaluated), we make an array of those, and then fold
    * adjacent items when possible.
    */
-  if (clip)
-    {
-      orig_clip = *clip;
-    }
-  else
-    {
-      orig_clip.x = rect.x;
-      orig_clip.y = rect.y;
-      orig_clip.width = rect.width;
-      orig_clip.height = rect.height;
-    }
-
-  active_clip = orig_clip;
+  cairo_save (cr);
 
   for (i = 0; i < op_list->n_ops; i++)
     {
@@ -4010,35 +3983,24 @@ meta_draw_op_list_draw_with_style  (const MetaDrawOpList *op_list,
       
       if (op->type == META_DRAW_CLIP)
         {
-          active_clip.x = parse_x_position_unchecked (op->data.clip.x, &env);
-          active_clip.y = parse_y_position_unchecked (op->data.clip.y, &env);
-          active_clip.width = parse_size_unchecked (op->data.clip.width, &env);
-          active_clip.height = parse_size_unchecked (op->data.clip.height, &env);
+          cairo_restore (cr);
+
+          cairo_rectangle (cr, 
+                           parse_x_position_unchecked (op->data.clip.x, &env),
+                           parse_y_position_unchecked (op->data.clip.y, &env),
+                           parse_size_unchecked (op->data.clip.width, &env),
+                           parse_size_unchecked (op->data.clip.height, &env));
+          cairo_clip (cr);
           
-          gdk_rectangle_intersect (&orig_clip, &active_clip, &active_clip);
+          cairo_save (cr);
         }
-      else if (active_clip.width > 0 &&
-               active_clip.height > 0)
+      else if (gdk_cairo_get_clip_rectangle (cr, NULL))
         {
-          meta_draw_op_draw_with_env (op,
-                                      style_gtk, widget, drawable, &active_clip, info,
-                                      rect,
-                                      &env);
+          meta_draw_op_draw_with_env (op, style_gtk, widget, cr, info, rect, &env);
         }
     }
-}
 
-void
-meta_draw_op_list_draw  (const MetaDrawOpList *op_list,
-                         GtkWidget            *widget,
-                         GdkDrawable          *drawable,
-                         const GdkRectangle   *clip,
-                         const MetaDrawInfo   *info,
-                         MetaRectangle         rect)
-
-{
-  meta_draw_op_list_draw_with_style (op_list, gtk_widget_get_style (widget), widget,
-                                     drawable, clip, info, rect);
+  cairo_restore (cr);
 }
 
 void
@@ -4402,12 +4364,9 @@ button_rect (MetaButtonType           type,
 
 void
 meta_frame_style_draw_with_style (MetaFrameStyle          *style,
-                                  GtkStyle                *style_gtk,
+                                  GtkStyleContext         *style_gtk,
                                   GtkWidget               *widget,
-                                  GdkDrawable             *drawable,
-                                  int                      x_offset,
-                                  int                      y_offset,
-                                  const GdkRectangle      *clip,
+                                  cairo_t                 *cr,
                                   const MetaFrameGeometry *fgeom,
                                   int                      client_width,
                                   int                      client_height,
@@ -4426,8 +4385,6 @@ meta_frame_style_draw_with_style (MetaFrameStyle          *style,
   GdkRectangle left_edge, right_edge, bottom_edge;
   PangoRectangle extents;
   MetaDrawInfo draw_info;
-  
-  g_return_if_fail (style_gtk->colormap == gdk_drawable_get_colormap (drawable));
 
   titlebar_rect.x = 0;
   titlebar_rect.y = 0;
@@ -4485,7 +4442,6 @@ meta_frame_style_draw_with_style (MetaFrameStyle          *style,
   while (i < META_FRAME_PIECE_LAST)
     {
       GdkRectangle rect;
-      GdkRectangle combined_clip;
       
       switch ((MetaFramePiece) i)
         {
@@ -4552,17 +4508,12 @@ meta_frame_style_draw_with_style (MetaFrameStyle          *style,
           break;
         }
 
-      rect.x += x_offset;
-      rect.y += y_offset;
+      cairo_save (cr);
 
-      if (clip == NULL)
-        combined_clip = rect;
-      else
-        gdk_rectangle_intersect ((GdkRectangle*) clip, /* const cast */
-                                 &rect,
-                                 &combined_clip);
+      gdk_cairo_rectangle (cr, &rect);
+      cairo_clip (cr);
 
-      if (combined_clip.width > 0 && combined_clip.height > 0)
+      if (gdk_cairo_get_clip_rectangle (cr, NULL))
         {
           MetaDrawOpList *op_list;
           MetaFrameStyle *parent;
@@ -4582,17 +4533,18 @@ meta_frame_style_draw_with_style (MetaFrameStyle          *style,
               meta_draw_op_list_draw_with_style (op_list,
                                                  style_gtk,
                                                  widget,
-                                                 drawable,
-                                                 &combined_clip,
+                                                 cr,
                                                  &draw_info,
                                                  m_rect);
             }
         }
 
+      cairo_restore (cr);
 
       /* Draw buttons just before overlay */
       if ((i + 1) == META_FRAME_PIECE_OVERLAY)
         {
+          MetaDrawOpList *op_list;
           int middle_bg_offset;
 
           middle_bg_offset = 0;
@@ -4603,25 +4555,16 @@ meta_frame_style_draw_with_style (MetaFrameStyle          *style,
 
               button_rect (j, fgeom, middle_bg_offset, &rect);
               
-              rect.x += x_offset;
-              rect.y += y_offset;
-              
-              if (clip == NULL)
-                combined_clip = rect;
-              else
-                gdk_rectangle_intersect ((GdkRectangle*) clip, /* const cast */
-                                         &rect,
-                                         &combined_clip);
+              button_state = map_button_state (j, fgeom, middle_bg_offset, button_states);
+              op_list = get_button (style, j, button_state);
               
-              if (combined_clip.width > 0 && combined_clip.height > 0)
+              if (op_list)
                 {
-                  MetaDrawOpList *op_list;
+                  cairo_save (cr);
+                  gdk_cairo_rectangle (cr, &rect);
+                  cairo_clip (cr);
                   
-                  button_state = map_button_state (j, fgeom, middle_bg_offset, button_states);
-
-                  op_list = get_button (style, j, button_state);
-                  
-                  if (op_list)
+                  if (gdk_cairo_get_clip_rectangle (cr, NULL))
                     {
                       MetaRectangle m_rect;
                       m_rect = meta_rect (rect.x, rect.y,
@@ -4629,11 +4572,11 @@ meta_frame_style_draw_with_style (MetaFrameStyle          *style,
                       meta_draw_op_list_draw_with_style (op_list,
                                                          style_gtk,
                                                          widget,
-                                                         drawable,
-                                                         &combined_clip,
+                                                         cr,
                                                          &draw_info,
                                                          m_rect);
                     }
+                  cairo_restore (cr);
                 }
 
               /* MIDDLE_BACKGROUND type may get drawn more than once */
@@ -4658,10 +4601,7 @@ meta_frame_style_draw_with_style (MetaFrameStyle          *style,
 void
 meta_frame_style_draw (MetaFrameStyle          *style,
                        GtkWidget               *widget,
-                       GdkDrawable             *drawable,
-                       int                      x_offset,
-                       int                      y_offset,
-                       const GdkRectangle      *clip,
+                       cairo_t                 *cr,
                        const MetaFrameGeometry *fgeom,
                        int                      client_width,
                        int                      client_height,
@@ -4671,9 +4611,8 @@ meta_frame_style_draw (MetaFrameStyle          *style,
                        GdkPixbuf               *mini_icon,
                        GdkPixbuf               *icon)
 {
-  meta_frame_style_draw_with_style (style, gtk_widget_get_style (widget), widget,
-                                    drawable, x_offset, y_offset,
-                                    clip, fgeom, client_width, client_height,
+  meta_frame_style_draw_with_style (style, gtk_widget_get_style_context (widget), widget,
+                                    cr, fgeom, client_width, client_height,
                                     title_layout, text_height,
                                     button_states, mini_icon, icon);
 }
@@ -5226,12 +5165,9 @@ meta_theme_get_title_scale (MetaTheme     *theme,
 
 void
 meta_theme_draw_frame_with_style (MetaTheme              *theme,
-                                  GtkStyle               *style_gtk,
+                                  GtkStyleContext        *style_gtk,
                                   GtkWidget              *widget,
-                                  GdkDrawable            *drawable,
-                                  const GdkRectangle     *clip,
-                                  int                     x_offset,
-                                  int                     y_offset,
+                                  cairo_t                *cr,
                                   MetaFrameType           type,
                                   MetaFrameFlags          flags,
                                   int                     client_width,
@@ -5265,9 +5201,7 @@ meta_theme_draw_frame_with_style (MetaTheme              *theme,
   meta_frame_style_draw_with_style (style,
                                     style_gtk,
                                     widget,
-                                    drawable,
-                                    x_offset, y_offset,
-                                    clip,
+                                    cr,
                                     &fgeom,
                                     client_width, client_height,
                                     title_layout,
@@ -5279,10 +5213,7 @@ meta_theme_draw_frame_with_style (MetaTheme              *theme,
 void
 meta_theme_draw_frame (MetaTheme              *theme,
                        GtkWidget              *widget,
-                       GdkDrawable            *drawable,
-                       const GdkRectangle     *clip,
-                       int                     x_offset,
-                       int                     y_offset,
+                       cairo_t                *cr,
                        MetaFrameType           type,
                        MetaFrameFlags          flags,
                        int                     client_width,
@@ -5294,8 +5225,8 @@ meta_theme_draw_frame (MetaTheme              *theme,
                        GdkPixbuf              *mini_icon,
                        GdkPixbuf              *icon)
 {
-  meta_theme_draw_frame_with_style (theme, gtk_widget_get_style (widget), widget,
-                                    drawable, clip, x_offset, y_offset, type,flags,
+  meta_theme_draw_frame_with_style (theme, gtk_widget_get_style_context (widget), widget,
+                                    cr, type, flags,
                                     client_width, client_height,
                                     title_layout, text_height,
                                     button_layout, button_states,
@@ -5303,54 +5234,6 @@ meta_theme_draw_frame (MetaTheme              *theme,
 }
 
 void
-meta_theme_draw_frame_by_name (MetaTheme              *theme,
-                               GtkWidget              *widget,
-                               GdkDrawable            *drawable,
-                               const GdkRectangle     *clip,
-                               int                     x_offset,
-                               int                     y_offset,
-                               const gchar             *style_name,
-                               MetaFrameFlags          flags,
-                               int                     client_width,
-                               int                     client_height,
-                               PangoLayout            *title_layout,
-                               int                     text_height,
-                               const MetaButtonLayout *button_layout,
-                               MetaButtonState         button_states[META_BUTTON_TYPE_LAST],
-                               GdkPixbuf              *mini_icon,
-                               GdkPixbuf              *icon)
-{
-  MetaFrameGeometry fgeom;
-  MetaFrameStyle *style;
-
-  style = meta_theme_lookup_style (theme, style_name);
-  
-  /* Parser is not supposed to allow this currently */
-  if (style == NULL)
-    return;
-  
-  meta_frame_layout_calc_geometry (style->layout,
-                                   text_height,
-                                   flags,
-                                   client_width, client_height,
-                                   button_layout,
-                                   &fgeom,
-                                   theme);  
-
-  meta_frame_style_draw (style,
-                         widget,
-                         drawable,
-                         x_offset, y_offset,
-                         clip,
-                         &fgeom,
-                         client_width, client_height,
-                         title_layout,
-                         text_height,
-                         button_states,
-                         mini_icon, icon);
-}
-
-void
 meta_theme_get_frame_borders (MetaTheme      *theme,
                               MetaFrameType   type,
                               int             text_height,
@@ -5686,11 +5569,13 @@ meta_gtk_widget_get_font_desc (GtkWidget *widget,
                                double     scale,
                               const PangoFontDescription *override)
 {
+  GtkStyleContext *style;
   PangoFontDescription *font_desc;
   
   g_return_val_if_fail (gtk_widget_get_realized (widget), NULL);
 
-  font_desc = pango_font_description_copy (gtk_widget_get_style (widget)->font_desc);
+  style = gtk_widget_get_style_context (widget);
+  font_desc = pango_font_description_copy (gtk_style_context_get_font (style, 0));
 
   if (override)
     pango_font_description_merge (font_desc, override, TRUE);
@@ -5750,34 +5635,6 @@ meta_color_component_from_string (const char *str)
     return META_GTK_COLOR_LAST;
 }
 
-const char*
-meta_color_component_to_string (MetaGtkColorComponent component)
-{
-  switch (component)
-    {
-    case META_GTK_COLOR_FG:
-      return "fg";
-    case META_GTK_COLOR_BG:
-      return "bg";
-    case META_GTK_COLOR_LIGHT:
-      return "light";
-    case META_GTK_COLOR_DARK:
-      return "dark";
-    case META_GTK_COLOR_MID:
-      return "mid";
-    case META_GTK_COLOR_TEXT:
-      return "text";
-    case META_GTK_COLOR_BASE:
-      return "base";
-    case META_GTK_COLOR_TEXT_AA:
-      return "text_aa";
-    case META_GTK_COLOR_LAST:
-      break;
-    }
-
-  return "<unknown>";
-}
-
 MetaButtonState
 meta_button_state_from_string (const char *str)
 {
@@ -5927,42 +5784,6 @@ meta_frame_piece_from_string (const char *str)
     return META_FRAME_PIECE_LAST;
 }
 
-const char*
-meta_frame_piece_to_string (MetaFramePiece piece)
-{
-  switch (piece)
-    {
-    case META_FRAME_PIECE_ENTIRE_BACKGROUND:
-      return "entire_background";
-    case META_FRAME_PIECE_TITLEBAR:
-      return "titlebar";
-    case META_FRAME_PIECE_TITLEBAR_MIDDLE:
-      return "titlebar_middle";
-    case META_FRAME_PIECE_LEFT_TITLEBAR_EDGE:
-      return "left_titlebar_edge";
-    case META_FRAME_PIECE_RIGHT_TITLEBAR_EDGE:
-      return "right_titlebar_edge";
-    case META_FRAME_PIECE_TOP_TITLEBAR_EDGE:
-      return "top_titlebar_edge";
-    case META_FRAME_PIECE_BOTTOM_TITLEBAR_EDGE:
-      return "bottom_titlebar_edge";
-    case META_FRAME_PIECE_TITLE:
-      return "title";
-    case META_FRAME_PIECE_LEFT_EDGE:
-      return "left_edge";
-    case META_FRAME_PIECE_RIGHT_EDGE:
-      return "right_edge";
-    case META_FRAME_PIECE_BOTTOM_EDGE:
-      return "bottom_edge";
-    case META_FRAME_PIECE_OVERLAY:
-      return "overlay";
-    case META_FRAME_PIECE_LAST:
-      break;
-    }
-
-  return "<unknown>";
-}
-
 MetaFrameState
 meta_frame_state_from_string (const char *str)
 {
@@ -6124,24 +5945,6 @@ meta_gradient_type_from_string (const char *str)
     return META_GRADIENT_LAST;
 }
 
-const char*
-meta_gradient_type_to_string (MetaGradientType type)
-{
-  switch (type)
-    {
-    case META_GRADIENT_VERTICAL:
-      return "vertical";
-    case META_GRADIENT_HORIZONTAL:
-      return "horizontal";
-    case META_GRADIENT_DIAGONAL:
-      return "diagonal";
-    case META_GRADIENT_LAST:
-      break;
-    }
-
-  return "<unknown>";
-}
-
 GtkStateType
 meta_gtk_state_from_string (const char *str)
 {
@@ -6159,26 +5962,6 @@ meta_gtk_state_from_string (const char *str)
     return -1; /* hack */
 }
 
-const char*
-meta_gtk_state_to_string (GtkStateType state)
-{
-  switch (state)
-    {
-    case GTK_STATE_NORMAL:
-      return "NORMAL";
-    case GTK_STATE_PRELIGHT:
-      return "PRELIGHT";
-    case GTK_STATE_ACTIVE:
-      return "ACTIVE";
-    case GTK_STATE_SELECTED:
-      return "SELECTED";
-    case GTK_STATE_INSENSITIVE:
-      return "INSENSITIVE";
-    }
-
-  return "<unknown>";
-}
-
 GtkShadowType
 meta_gtk_shadow_from_string (const char *str)
 {
@@ -6196,26 +5979,6 @@ meta_gtk_shadow_from_string (const char *str)
     return -1;
 }
 
-const char*
-meta_gtk_shadow_to_string (GtkShadowType shadow)
-{
-  switch (shadow)
-    {
-    case GTK_SHADOW_NONE:
-      return "none";
-    case GTK_SHADOW_IN:
-      return "in";
-    case GTK_SHADOW_OUT:
-      return "out";
-    case GTK_SHADOW_ETCHED_IN:
-      return "etched_in";
-    case GTK_SHADOW_ETCHED_OUT:
-      return "etched_out";
-    }
-
-  return "<unknown>";
-}
-
 GtkArrowType
 meta_gtk_arrow_from_string (const char *str)
 {
@@ -6233,26 +5996,6 @@ meta_gtk_arrow_from_string (const char *str)
     return -1;
 }
 
-const char*
-meta_gtk_arrow_to_string (GtkArrowType arrow)
-{
-  switch (arrow)
-    {
-    case GTK_ARROW_UP:
-      return "up";
-    case GTK_ARROW_DOWN:
-      return "down";
-    case GTK_ARROW_LEFT:
-      return "left";
-    case GTK_ARROW_RIGHT:
-      return "right";
-    case GTK_ARROW_NONE:
-      return "none";
-    }
-
-  return "<unknown>";
-}
-
 /**
  * Returns a fill_type from a string.  The inverse of
  * meta_image_fill_type_to_string().
@@ -6272,27 +6015,6 @@ meta_image_fill_type_from_string (const char *str)
 }
 
 /**
- * Returns a string representation of a fill_type.  The inverse of
- * meta_image_fill_type_from_string().
- *
- * \param fill_type  the fill type
- * \result  a string representing that type
- */
-const char*
-meta_image_fill_type_to_string (MetaImageFillType fill_type)
-{
-  switch (fill_type)
-    {
-    case META_IMAGE_FILL_TILE:
-      return "tile";
-    case META_IMAGE_FILL_SCALE:
-      return "scale";
-    }
-  
-  return "<unknown>";
-}
-
-/**
  * Takes a colour "a", scales the lightness and saturation by a certain amount,
  * and sets "b" to the resulting colour.
  * gtkstyle.c cut-and-pastage.
@@ -6302,17 +6024,17 @@ meta_image_fill_type_to_string (MetaImageFillType fill_type)
  * \param k  amount to scale lightness and saturation by
  */ 
 static void
-gtk_style_shade (GdkColor *a,
-                 GdkColor *b,
-                 gdouble   k)
+gtk_style_shade (GdkRGBA *a,
+                 GdkRGBA *b,
+                 gdouble  k)
 {
   gdouble red;
   gdouble green;
   gdouble blue;
   
-  red = (gdouble) a->red / 65535.0;
-  green = (gdouble) a->green / 65535.0;
-  blue = (gdouble) a->blue / 65535.0;
+  red = a->red;
+  green = a->green;
+  blue = a->blue;
   
   rgb_to_hls (&red, &green, &blue);
   
@@ -6330,9 +6052,9 @@ gtk_style_shade (GdkColor *a,
   
   hls_to_rgb (&red, &green, &blue);
   
-  b->red = red * 65535.0;
-  b->green = green * 65535.0;
-  b->blue = blue * 65535.0;
+  b->red = red;
+  b->green = green;
+  b->blue = blue;
 }
 
 /**
@@ -6499,216 +6221,6 @@ hls_to_rgb (gdouble *h,
     }
 }
 
-#if 0
-/* These are some functions I'm saving to use in optimizing
- * MetaDrawOpList, namely to pre-composite pixbufs on client side
- * prior to rendering to the server
- */
-static void
-draw_bg_solid_composite (const MetaTextureSpec *bg,
-                         const MetaTextureSpec *fg,
-                         double                 alpha,
-                         GtkWidget             *widget,
-                         GdkDrawable           *drawable,
-                         const GdkRectangle    *clip,
-                         MetaTextureDrawMode    mode,
-                         double                 xalign,
-                         double                 yalign,
-                         int                    x,
-                         int                    y,
-                         int                    width,
-                         int                    height)
-{
-  GdkColor bg_color;
-
-  g_assert (bg->type == META_TEXTURE_SOLID);
-  g_assert (fg->type != META_TEXTURE_COMPOSITE);
-  g_assert (fg->type != META_TEXTURE_SHAPE_LIST);
-
-  meta_color_spec_render (bg->data.solid.color_spec,
-                          widget,
-                          &bg_color);
-
-  switch (fg->type)
-    {
-    case META_TEXTURE_SOLID:
-      {
-        GdkColor fg_color;
-
-        meta_color_spec_render (fg->data.solid.color_spec,
-                                widget,
-                                &fg_color);
-
-        color_composite (&bg_color, &fg_color,
-                         alpha, &fg_color);
-
-        draw_color_rectangle (widget, drawable, &fg_color, clip,
-                              x, y, width, height);
-      }
-      break;
-
-    case META_TEXTURE_GRADIENT:
-      /* FIXME I think we could just composite all the colors in
-       * the gradient prior to generating the gradient?
-       */
-      /* FALL THRU */
-    case META_TEXTURE_IMAGE:
-      {
-        GdkPixbuf *pixbuf;
-        GdkPixbuf *composited;
-
-        pixbuf = meta_texture_spec_render (fg, widget, mode, 255,
-                                           width, height);
-
-        if (pixbuf == NULL)
-          return;
-
-        composited = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
-                                     gdk_pixbuf_get_has_alpha (pixbuf), 8,
-                                     gdk_pixbuf_get_width (pixbuf),
-                                     gdk_pixbuf_get_height (pixbuf));
-
-        if (composited == NULL)
-          {
-            g_object_unref (G_OBJECT (pixbuf));
-            return;
-          }
-
-        gdk_pixbuf_composite_color (pixbuf,
-                                    composited,
-                                    0, 0,
-                                    gdk_pixbuf_get_width (pixbuf),
-                                    gdk_pixbuf_get_height (pixbuf),
-                                    0.0, 0.0, /* offsets */
-                                    1.0, 1.0, /* scale */
-                                    GDK_INTERP_BILINEAR,
-                                    255 * alpha,
-                                    0, 0,     /* check offsets */
-                                    0,        /* check size */
-                                    GDK_COLOR_RGB (bg_color),
-                                    GDK_COLOR_RGB (bg_color));
-
-        /* Need to draw background since pixbuf is not
-         * necessarily covering the whole thing
-         */
-        draw_color_rectangle (widget, drawable, &bg_color, clip,
-                              x, y, width, height);
-
-        render_pixbuf_aligned (drawable, clip, composited,
-                               xalign, yalign,
-                               x, y, width, height);
-
-        g_object_unref (G_OBJECT (pixbuf));
-        g_object_unref (G_OBJECT (composited));
-      }
-      break;
-
-    case META_TEXTURE_BLANK:
-    case META_TEXTURE_COMPOSITE:
-    case META_TEXTURE_SHAPE_LIST:
-      g_assert_not_reached ();
-      break;
-    }
-}
-
-static void
-draw_bg_gradient_composite (const MetaTextureSpec *bg,
-                            const MetaTextureSpec *fg,
-                            double                 alpha,
-                            GtkWidget             *widget,
-                            GdkDrawable           *drawable,
-                            const GdkRectangle    *clip,
-                            MetaTextureDrawMode    mode,
-                            double                 xalign,
-                            double                 yalign,
-                            int                    x,
-                            int                    y,
-                            int                    width,
-                            int                    height)
-{
-  g_assert (bg->type == META_TEXTURE_GRADIENT);
-  g_assert (fg->type != META_TEXTURE_COMPOSITE);
-  g_assert (fg->type != META_TEXTURE_SHAPE_LIST);
-
-  switch (fg->type)
-    {
-    case META_TEXTURE_SOLID:
-    case META_TEXTURE_GRADIENT:
-    case META_TEXTURE_IMAGE:
-      {
-        GdkPixbuf *bg_pixbuf;
-        GdkPixbuf *fg_pixbuf;
-        GdkPixbuf *composited;
-        int fg_width, fg_height;
-
-        bg_pixbuf = meta_texture_spec_render (bg, widget, mode, 255,
-                                              width, height);
-
-        if (bg_pixbuf == NULL)
-          return;
-
-        fg_pixbuf = meta_texture_spec_render (fg, widget, mode, 255,
-                                              width, height);
-
-        if (fg_pixbuf == NULL)
-          {
-            g_object_unref (G_OBJECT (bg_pixbuf));
-            return;
-          }
-
-        /* gradients always fill the entire target area */
-        g_assert (gdk_pixbuf_get_width (bg_pixbuf) == width);
-        g_assert (gdk_pixbuf_get_height (bg_pixbuf) == height);
-
-        composited = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
-                                     gdk_pixbuf_get_has_alpha (bg_pixbuf), 8,
-                                     gdk_pixbuf_get_width (bg_pixbuf),
-                                     gdk_pixbuf_get_height (bg_pixbuf));
-
-        if (composited == NULL)
-          {
-            g_object_unref (G_OBJECT (bg_pixbuf));
-            g_object_unref (G_OBJECT (fg_pixbuf));
-            return;
-          }
-
-        fg_width = gdk_pixbuf_get_width (fg_pixbuf);
-        fg_height = gdk_pixbuf_get_height (fg_pixbuf);
-
-        /* If we wanted to be all cool we could deal with the
-         * offsets and try to composite only in the clip rectangle,
-         * but I just don't care enough to figure it out.
-         */
-
-        gdk_pixbuf_composite (fg_pixbuf,
-                              composited,
-                              x + (width - fg_width) * xalign,
-                              y + (height - fg_height) * yalign,
-                              gdk_pixbuf_get_width (fg_pixbuf),
-                              gdk_pixbuf_get_height (fg_pixbuf),
-                              0.0, 0.0, /* offsets */
-                              1.0, 1.0, /* scale */
-                              GDK_INTERP_BILINEAR,
-                              255 * alpha);
-
-        gdk_cairo_set_source_pixbuf (cr, composited, x, y);
-        cairo_paint (cr);
-
-        g_object_unref (G_OBJECT (bg_pixbuf));
-        g_object_unref (G_OBJECT (fg_pixbuf));
-        g_object_unref (G_OBJECT (composited));
-      }
-      break;
-
-    case META_TEXTURE_BLANK:
-    case META_TEXTURE_SHAPE_LIST:
-    case META_TEXTURE_COMPOSITE:
-      g_assert_not_reached ();
-      break;
-    }
-}
-#endif
-
 /**
  * Returns the earliest version of the theme format which required support
  * for a particular button.  (For example, "shade" first appeared in v2, and
diff --git a/src/ui/theme.h b/src/ui/theme.h
index 394b2b4..ca8d808 100644
--- a/src/ui/theme.h
+++ b/src/ui/theme.h
@@ -251,7 +251,7 @@ struct _MetaColorSpec
   union
   {
     struct {
-      GdkColor color;
+      GdkRGBA color;
     } basic;
     struct {
       MetaGtkColorComponent component;
@@ -262,13 +262,13 @@ struct _MetaColorSpec
       MetaColorSpec *background;
       double alpha;
 
-      GdkColor color;
+      GdkRGBA color;
     } blend;
     struct {
       MetaColorSpec *base;
       double factor;
 
-      GdkColor color;
+      GdkRGBA color;
     } shade;
   } data;
 };
@@ -890,43 +890,20 @@ MetaColorSpec* meta_color_spec_new_gtk         (MetaGtkColorComponent component,
                                                 GtkStateType          state);
 void           meta_color_spec_free            (MetaColorSpec     *spec);
 void           meta_color_spec_render          (MetaColorSpec     *spec,
-                                                GtkWidget         *widget,
-                                                GdkColor          *color);
+                                                GtkStyleContext   *style_gtk,
+                                                GdkRGBA           *color);
 
 
 MetaDrawOp*    meta_draw_op_new  (MetaDrawType        type);
 void           meta_draw_op_free (MetaDrawOp          *op);
-void           meta_draw_op_draw (const MetaDrawOp    *op,
-                                  GtkWidget           *widget,
-                                  GdkDrawable         *drawable,
-                                  const GdkRectangle  *clip,
-                                  const MetaDrawInfo  *info,
-                                  /* logical region being drawn */
-                                  MetaRectangle        logical_region);
-
-void           meta_draw_op_draw_with_style (const MetaDrawOp    *op,
-                                             GtkStyle            *style_gtk,
-                                             GtkWidget           *widget,
-                                             GdkDrawable         *drawable,
-                                             const GdkRectangle  *clip,
-                                             const MetaDrawInfo  *info,
-                                             /* logical region being drawn */
-                                             MetaRectangle        logical_region);
 
 MetaDrawOpList* meta_draw_op_list_new   (int                   n_preallocs);
 void            meta_draw_op_list_ref   (MetaDrawOpList       *op_list);
 void            meta_draw_op_list_unref (MetaDrawOpList       *op_list);
-void            meta_draw_op_list_draw  (const MetaDrawOpList *op_list,
-                                         GtkWidget            *widget,
-                                         GdkDrawable          *drawable,
-                                         const GdkRectangle   *clip,
-                                         const MetaDrawInfo   *info,
-                                         MetaRectangle         rect);
 void            meta_draw_op_list_draw_with_style  (const MetaDrawOpList *op_list,
-                                                    GtkStyle             *style_gtk,
+                                                    GtkStyleContext      *style_gtk,
                                                     GtkWidget            *widget,
-                                                    GdkDrawable          *drawable,
-                                                    const GdkRectangle   *clip,
+                                                    cairo_t              *cr,
                                                     const MetaDrawInfo   *info,
                                                     MetaRectangle         rect);
 void           meta_draw_op_list_append (MetaDrawOpList       *op_list,
@@ -939,7 +916,7 @@ gboolean       meta_draw_op_list_contains (MetaDrawOpList    *op_list,
 MetaGradientSpec* meta_gradient_spec_new    (MetaGradientType        type);
 void              meta_gradient_spec_free   (MetaGradientSpec       *desc);
 GdkPixbuf*        meta_gradient_spec_render (const MetaGradientSpec *desc,
-                                             GtkWidget              *widget,
+                                             GtkStyleContext        *widget,
                                              int                     width,
                                              int                     height);
 gboolean          meta_gradient_spec_validate (MetaGradientSpec     *spec,
@@ -956,10 +933,7 @@ void            meta_frame_style_unref (MetaFrameStyle *style);
 
 void meta_frame_style_draw (MetaFrameStyle          *style,
                             GtkWidget               *widget,
-                            GdkDrawable             *drawable,
-                            int                      x_offset,
-                            int                      y_offset,
-                            const GdkRectangle      *clip,
+                            cairo_t                 *cr,
                             const MetaFrameGeometry *fgeom,
                             int                      client_width,
                             int                      client_height,
@@ -971,12 +945,9 @@ void meta_frame_style_draw (MetaFrameStyle          *style,
 
 
 void meta_frame_style_draw_with_style (MetaFrameStyle          *style,
-                                       GtkStyle                *style_gtk,
+                                       GtkStyleContext         *style_gtk,
                                        GtkWidget               *widget,
-                                       GdkDrawable             *drawable,
-                                       int                      x_offset,
-                                       int                      y_offset,
-                                       const GdkRectangle      *clip,
+                                       cairo_t                 *cr,
                                        const MetaFrameGeometry *fgeom,
                                        int                      client_width,
                                        int                      client_height,
@@ -1021,10 +992,7 @@ double meta_theme_get_title_scale (MetaTheme     *theme,
 
 void meta_theme_draw_frame (MetaTheme              *theme,
                             GtkWidget              *widget,
-                            GdkDrawable            *drawable,
-                            const GdkRectangle     *clip,
-                            int                     x_offset,
-                            int                     y_offset,
+                            cairo_t                *cr,
                             MetaFrameType           type,
                             MetaFrameFlags          flags,
                             int                     client_width,
@@ -1036,30 +1004,10 @@ void meta_theme_draw_frame (MetaTheme              *theme,
                             GdkPixbuf              *mini_icon,
                             GdkPixbuf              *icon);
 
-void meta_theme_draw_frame_by_name (MetaTheme              *theme,
-                                    GtkWidget              *widget,
-                                    GdkDrawable            *drawable,
-                                    const GdkRectangle     *clip,
-                                    int                     x_offset,
-                                    int                     y_offset,
-                                    const gchar             *style_name,
-                                    MetaFrameFlags          flags,
-                                    int                     client_width,
-                                    int                     client_height,
-                                    PangoLayout            *title_layout,
-                                    int                     text_height,
-                                    const MetaButtonLayout *button_layout,
-                                    MetaButtonState         button_states[META_BUTTON_TYPE_LAST],
-                                    GdkPixbuf              *mini_icon,
-                                    GdkPixbuf              *icon);
-
 void meta_theme_draw_frame_with_style (MetaTheme              *theme,
-                                       GtkStyle               *style_gtk,
+                                       GtkStyleContext        *style_gtk,
                                        GtkWidget              *widget,
-                                       GdkDrawable            *drawable,
-                                       const GdkRectangle     *clip,
-                                       int                     x_offset,
-                                       int                     y_offset,
+                                       cairo_t                *cr,
                                        MetaFrameType           type,
                                        MetaFrameFlags          flags,
                                        int                     client_width,
@@ -1147,14 +1095,12 @@ int                   meta_pango_font_desc_get_text_height (const PangoFontDescr
 
 /* Enum converters */
 MetaGtkColorComponent meta_color_component_from_string (const char            *str);
-const char*           meta_color_component_to_string   (MetaGtkColorComponent  component);
 MetaButtonState       meta_button_state_from_string    (const char            *str);
 const char*           meta_button_state_to_string      (MetaButtonState        state);
 MetaButtonType        meta_button_type_from_string     (const char            *str,
                                                         MetaTheme             *theme);
 const char*           meta_button_type_to_string       (MetaButtonType         type);
 MetaFramePiece        meta_frame_piece_from_string     (const char            *str);
-const char*           meta_frame_piece_to_string       (MetaFramePiece         piece);
 MetaFrameState        meta_frame_state_from_string     (const char            *str);
 const char*           meta_frame_state_to_string       (MetaFrameState         state);
 MetaFrameResize       meta_frame_resize_from_string    (const char            *str);
@@ -1164,15 +1110,17 @@ const char*           meta_frame_focus_to_string       (MetaFrameFocus         f
 MetaFrameType         meta_frame_type_from_string      (const char            *str);
 const char*           meta_frame_type_to_string        (MetaFrameType          type);
 MetaGradientType      meta_gradient_type_from_string   (const char            *str);
-const char*           meta_gradient_type_to_string     (MetaGradientType       type);
 GtkStateType          meta_gtk_state_from_string       (const char            *str);
-const char*           meta_gtk_state_to_string         (GtkStateType           state);
 GtkShadowType         meta_gtk_shadow_from_string      (const char            *str);
-const char*           meta_gtk_shadow_to_string        (GtkShadowType          shadow);
 GtkArrowType          meta_gtk_arrow_from_string       (const char            *str);
-const char*           meta_gtk_arrow_to_string         (GtkArrowType           arrow);
 MetaImageFillType     meta_image_fill_type_from_string (const char            *str);
-const char*           meta_image_fill_type_to_string   (MetaImageFillType      fill_type);
+
+void                  meta_gtk_style_get_light_color   (GtkStyleContext      *style,
+                                                        GtkStateFlags         state,
+                                                        GdkRGBA              *color);
+void                  meta_gtk_style_get_dark_color    (GtkStyleContext      *style,
+                                                        GtkStateFlags         state,
+                                                        GdkRGBA              *color);
 
 guint meta_theme_earliest_version_with_button (MetaButtonType type);
 
diff --git a/src/ui/ui.c b/src/ui/ui.c
index 3865827..6a6ae45 100644
--- a/src/ui/ui.c
+++ b/src/ui/ui.c
@@ -32,6 +32,7 @@
 
 #include <string.h>
 #include <stdlib.h>
+#include <cairo-xlib.h>
 
 static void meta_stock_icons_init (void);
 static void meta_ui_accelerator_parse (const char      *accel,
@@ -56,6 +57,16 @@ struct _MetaUI
 void
 meta_ui_init (int *argc, char ***argv)
 {
+  /* As of 2.91.7, Gdk uses XI2 by default, which conflicts with the
+   * direct X calls we use - in particular, events caused by calls to
+   * XGrabPointer/XGrabKeyboard are no longer understood by GDK, while
+   * GDK will no longer generate the core XEvents we process.
+   * So at least for now, enforce the previous behavior.
+   */
+#if GTK_CHECK_VERSION(2, 91, 7)
+  gdk_disable_multidevice ();
+#endif
+
   if (!gtk_init_check (argc, argv))
     meta_fatal ("Unable to open X display %s\n", XDisplayName (NULL));
 
@@ -87,8 +98,10 @@ static gboolean
 maybe_redirect_mouse_event (XEvent *xevent)
 {
   GdkDisplay *gdisplay;
+  GdkDeviceManager *gmanager;
+  GdkDevice *gdevice;
   MetaUI *ui;
-  GdkEvent gevent;
+  GdkEvent *gevent;
   GdkWindow *gdk_window;
   Window window;
 
@@ -114,19 +127,20 @@ maybe_redirect_mouse_event (XEvent *xevent)
   if (!ui)
     return FALSE;
 
-  gdk_window = gdk_window_lookup_for_display (gdisplay, window);
+  gdk_window = gdk_x11_window_lookup_for_display (gdisplay, window);
   if (gdk_window == NULL)
     return FALSE;
 
+  gmanager = gdk_display_get_device_manager (gdisplay);
+  gdevice = gdk_device_manager_get_client_pointer (gmanager);
+
   /* If GDK already thinks it has a grab, we better let it see events; this
    * is the menu-navigation case and events need to get sent to the appropriate
    * (client-side) subwindow for individual menu items.
    */
-  if (gdk_display_pointer_is_grabbed (gdisplay))
+  if (gdk_display_device_is_grabbed (gdisplay, gdevice))
     return FALSE;
 
-  memset (&gevent, 0, sizeof (gevent));
-
   switch (xevent->type)
     {
     case ButtonPress:
@@ -148,13 +162,13 @@ maybe_redirect_mouse_event (XEvent *xevent)
               ABS (xevent->xbutton.x - ui->button_click_x) <= double_click_distance &&
               ABS (xevent->xbutton.y - ui->button_click_y) <= double_click_distance)
             {
-              gevent.button.type = GDK_2BUTTON_PRESS;
+              gevent = gdk_event_new (GDK_2BUTTON_PRESS);
 
               ui->button_click_number = 0;
             }
           else
             {
-              gevent.button.type = GDK_BUTTON_PRESS;
+              gevent = gdk_event_new (GDK_BUTTON_PRESS);
               ui->button_click_number = xevent->xbutton.button;
               ui->button_click_window = xevent->xbutton.window;
               ui->button_click_time = xevent->xbutton.time;
@@ -164,28 +178,29 @@ maybe_redirect_mouse_event (XEvent *xevent)
         }
       else
         {
-          gevent.button.type = GDK_BUTTON_RELEASE;
+          gevent = gdk_event_new (GDK_BUTTON_RELEASE);
         }
 
-      gevent.button.window = gdk_window;
-      gevent.button.button = xevent->xbutton.button;
-      gevent.button.time = xevent->xbutton.time;
-      gevent.button.x = xevent->xbutton.x;
-      gevent.button.y = xevent->xbutton.y;
-      gevent.button.x_root = xevent->xbutton.x_root;
-      gevent.button.y_root = xevent->xbutton.y_root;
+      gevent->button.window = g_object_ref (gdk_window);
+      gevent->button.button = xevent->xbutton.button;
+      gevent->button.time = xevent->xbutton.time;
+      gevent->button.x = xevent->xbutton.x;
+      gevent->button.y = xevent->xbutton.y;
+      gevent->button.x_root = xevent->xbutton.x_root;
+      gevent->button.y_root = xevent->xbutton.y_root;
 
       break;
     case MotionNotify:
-      gevent.motion.type = GDK_MOTION_NOTIFY;
-      gevent.motion.window = gdk_window;
+      gevent = gdk_event_new (GDK_MOTION_NOTIFY);
+      gevent->motion.type = GDK_MOTION_NOTIFY;
+      gevent->motion.window = g_object_ref (gdk_window);
       break;
     case EnterNotify:
     case LeaveNotify:
-      gevent.crossing.type = xevent->type == EnterNotify ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY;
-      gevent.crossing.window = gdk_window;
-      gevent.crossing.x = xevent->xcrossing.x;
-      gevent.crossing.y = xevent->xcrossing.y;
+      gevent = gdk_event_new (xevent->type == EnterNotify ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY);
+      gevent->crossing.window = g_object_ref (gdk_window);
+      gevent->crossing.x = xevent->xcrossing.x;
+      gevent->crossing.y = xevent->xcrossing.y;
       break;
     default:
       g_assert_not_reached ();
@@ -193,7 +208,9 @@ maybe_redirect_mouse_event (XEvent *xevent)
     }
 
   /* If we've gotten here, we've filled in the gdk_event and should send it on */
-  gtk_main_do_event (&gevent);
+  gdk_event_set_device (gevent, gdevice);
+  gtk_main_do_event (gevent);
+  gdk_event_free (gevent);
 
   return TRUE;
 }
@@ -266,7 +283,10 @@ meta_ui_new (Display *xdisplay,
 
   g_assert (xdisplay == GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
   ui->frames = meta_frames_new (XScreenNumberOfScreen (screen));
-  gtk_widget_realize (GTK_WIDGET (ui->frames));
+  /* This does not actually show any widget. MetaFrames has been hacked so
+   * that showing it doesn't actually do anything. But we need the flags
+   * set for GTK to deliver events properly. */
+  gtk_widget_show (GTK_WIDGET (ui->frames));
 
   g_object_set_data (G_OBJECT (gdisplay), "meta-ui", ui);
 
@@ -313,7 +333,6 @@ meta_ui_create_frame_window (MetaUI *ui,
   gint attributes_mask;
   GdkWindow *window;
   GdkVisual *visual;
-  GdkColormap *cmap = gdk_screen_get_default_colormap (screen);
   
   /* Default depth/visual handles clients with weird visuals; they can
    * always be children of the root depth/visual obviously, but
@@ -326,7 +345,6 @@ meta_ui_create_frame_window (MetaUI *ui,
     {
       visual = gdk_x11_screen_lookup_visual (screen,
                                              XVisualIDFromVisual (xvisual));
-      cmap = gdk_colormap_new (visual, FALSE);
     }
 
   attrs.title = NULL;
@@ -342,7 +360,6 @@ meta_ui_create_frame_window (MetaUI *ui,
   attrs.y = y;
   attrs.wclass = GDK_INPUT_OUTPUT;
   attrs.visual = visual;
-  attrs.colormap = cmap;
   attrs.window_type = GDK_WINDOW_CHILD;
   attrs.cursor = NULL;
   attrs.wmclass_name = NULL;
@@ -352,7 +369,7 @@ meta_ui_create_frame_window (MetaUI *ui,
   attrs.width  = width;
   attrs.height = height;
 
-  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
 
   window =
     gdk_window_new (gdk_screen_get_root_window(screen),
@@ -388,8 +405,10 @@ meta_ui_map_frame   (MetaUI *ui,
                      Window  xwindow)
 {
   GdkWindow *window;
+  GdkDisplay *display;
 
-  window = gdk_xid_table_lookup (xwindow);
+  display = gdk_x11_lookup_xdisplay (ui->xdisplay);
+  window = gdk_x11_window_lookup_for_display (display, xwindow);
 
   if (window)
     gdk_window_show_unraised (window);
@@ -400,8 +419,10 @@ meta_ui_unmap_frame (MetaUI *ui,
                      Window  xwindow)
 {
   GdkWindow *window;
+  GdkDisplay *display;
 
-  window = gdk_xid_table_lookup (xwindow);
+  display = gdk_x11_lookup_xdisplay (ui->xdisplay);
+  window = gdk_x11_window_lookup_for_display (display, xwindow);
 
   if (window)
     gdk_window_hide (window);
@@ -493,121 +514,52 @@ meta_ui_window_menu_free (MetaWindowMenu *menu)
   meta_window_menu_free (menu);
 }
 
-static GdkColormap*
-get_cmap (GdkPixmap *pixmap)
-{
-  GdkColormap *cmap;
-
-  cmap = gdk_drawable_get_colormap (pixmap);
-  if (cmap)
-    g_object_ref (G_OBJECT (cmap));
-
-  if (cmap == NULL)
-    {
-      if (gdk_drawable_get_depth (pixmap) == 1)
-        {
-          meta_verbose ("Using NULL colormap for snapshotting bitmap\n");
-          cmap = NULL;
-        }
-      else
-        {
-          meta_verbose ("Using system cmap to snapshot pixmap\n");
-          cmap = gdk_screen_get_system_colormap (gdk_drawable_get_screen (pixmap));
-
-          g_object_ref (G_OBJECT (cmap));
-        }
-    }
-
-  /* Be sure we aren't going to blow up due to visual mismatch */
-  if (cmap &&
-      (gdk_visual_get_depth (gdk_colormap_get_visual (cmap)) !=
-       gdk_drawable_get_depth (pixmap)))
-    {
-      cmap = NULL;
-      meta_verbose ("Switching back to NULL cmap because of depth mismatch\n");
-    }
-  
-  return cmap;
-}
-
 GdkPixbuf*
-meta_gdk_pixbuf_get_from_window (GdkPixbuf   *dest,
-                                 Window       xwindow,
+meta_gdk_pixbuf_get_from_pixmap (Pixmap       xpixmap,
                                  int          src_x,
                                  int          src_y,
-                                 int          dest_x,
-                                 int          dest_y,
                                  int          width,
                                  int          height)
 {
-  GdkDrawable *drawable;
+  cairo_surface_t *surface;
+  Display *display;
+  Window root_return;
+  int x_ret, y_ret;
+  unsigned int w_ret, h_ret, bw_ret, depth_ret;
+  XWindowAttributes attrs;
   GdkPixbuf *retval;
-  GdkColormap *cmap;
-  
-  retval = NULL;
-  
-  drawable = gdk_xid_table_lookup (xwindow);
 
-  if (drawable)
-    g_object_ref (G_OBJECT (drawable));
-  else
-    drawable = gdk_window_foreign_new (xwindow);
-
-  cmap = get_cmap (drawable);
-  
-  retval = gdk_pixbuf_get_from_drawable (dest,
-                                         drawable,
-                                         cmap,
-                                         src_x, src_y,
-                                         dest_x, dest_y,
-                                         width, height);
+  display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 
-  if (cmap)
-    g_object_unref (G_OBJECT (cmap));
-  g_object_unref (G_OBJECT (drawable));
-
-  return retval;
-}
+  if (!XGetGeometry (display, xpixmap, &root_return,
+                     &x_ret, &y_ret, &w_ret, &h_ret, &bw_ret, &depth_ret))
+    return NULL;
 
-GdkPixbuf*
-meta_gdk_pixbuf_get_from_pixmap (GdkPixbuf   *dest,
-                                 Pixmap       xpixmap,
-                                 int          src_x,
-                                 int          src_y,
-                                 int          dest_x,
-                                 int          dest_y,
-                                 int          width,
-                                 int          height)
-{
-  GdkDrawable *drawable;
-  GdkPixbuf *retval;
-  GdkColormap *cmap;
-  
-  retval = NULL;
-  cmap = NULL;
-  
-  drawable = gdk_xid_table_lookup (xpixmap);
-
-  if (drawable)
-    g_object_ref (G_OBJECT (drawable));
+  if (depth_ret == 1)
+    {
+      surface = cairo_xlib_surface_create_for_bitmap (display,
+                                                      xpixmap,
+                                                      GDK_SCREEN_XSCREEN (gdk_screen_get_default ()),
+                                                      w_ret,
+                                                      h_ret);
+    }
   else
-    drawable = gdk_pixmap_foreign_new (xpixmap);
-
-  if (drawable)
     {
-      cmap = get_cmap (drawable);
-  
-      retval = gdk_pixbuf_get_from_drawable (dest,
-                                             drawable,
-                                             cmap,
-                                             src_x, src_y,
-                                             dest_x, dest_y,
-                                             width, height);
+      if (!XGetWindowAttributes (display, root_return, &attrs))
+        return NULL;
+
+      surface = cairo_xlib_surface_create (display,
+                                           xpixmap,
+                                           attrs.visual,
+                                           w_ret, h_ret);
     }
-  if (cmap)
-    g_object_unref (G_OBJECT (cmap));
-  if (drawable)
-    g_object_unref (G_OBJECT (drawable));
+
+  retval = gdk_pixbuf_get_from_surface (surface,
+                                        src_x,
+                                        src_y,
+                                        width,
+                                        height);
+  cairo_surface_destroy (surface);
 
   return retval;
 }
@@ -695,8 +647,10 @@ meta_ui_window_should_not_cause_focus (Display *xdisplay,
                                        Window   xwindow)
 {
   GdkWindow *window;
+  GdkDisplay *display;
 
-  window = gdk_xid_table_lookup (xwindow);
+  display = gdk_x11_lookup_xdisplay (xdisplay);
+  window = gdk_x11_window_lookup_for_display (display, xwindow);
 
   /* we shouldn't cause focus if we're an override redirect
    * toplevel which is not foreign
@@ -711,17 +665,20 @@ char*
 meta_text_property_to_utf8 (Display             *xdisplay,
                             const XTextProperty *prop)
 {
+  GdkDisplay *display;
   char **list;
   int count;
   char *retval;
   
   list = NULL;
 
-  count = gdk_text_property_to_utf8_list (gdk_x11_xatom_to_atom (prop->encoding),
-                                          prop->format,
-                                          prop->value,
-                                          prop->nitems,
-                                          &list);
+  display = gdk_x11_lookup_xdisplay (xdisplay);
+  count = gdk_text_property_to_utf8_list_for_display (display,
+                                                      gdk_x11_xatom_to_atom_for_display (display, 
prop->encoding),
+                                                      prop->format,
+                                                      prop->value,
+                                                      prop->nitems,
+                                                      &list);
 
   if (count == 0)
     retval = NULL;
@@ -748,7 +705,7 @@ meta_ui_theme_get_frame_borders (MetaUI *ui,
   int text_height;
   PangoContext *context;
   const PangoFontDescription *font_desc;
-  GtkStyle *default_style;
+  GtkStyleContext *style = NULL;
 
   if (meta_ui_have_a_theme ())
     {
@@ -757,8 +714,8 @@ meta_ui_theme_get_frame_borders (MetaUI *ui,
 
       if (!font_desc)
         {
-          default_style = gtk_widget_get_default_style ();
-          font_desc = default_style->font_desc;
+          style = gtk_style_context_new ();
+          font_desc = gtk_style_context_get_font (style, 0);
         }
 
       text_height = meta_pango_font_desc_get_text_height (font_desc, context);
@@ -772,6 +729,9 @@ meta_ui_theme_get_frame_borders (MetaUI *ui,
     {
       *top_height = *bottom_height = *left_width = *right_width = 0;
     }
+
+  if (style != NULL)
+    g_object_unref (style);
 }
 
 void
@@ -982,9 +942,11 @@ gboolean
 meta_ui_window_is_widget (MetaUI *ui,
                           Window  xwindow)
 {
+  GdkDisplay *display;
   GdkWindow *window;
 
-  window = gdk_xid_table_lookup (xwindow);
+  display = gdk_x11_lookup_xdisplay (ui->xdisplay);
+  window = gdk_x11_window_lookup_for_display (display, xwindow);
 
   if (window)
     {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]