diff --git a/SOURCES/0001-Add-a-framework-for-restarting-the-compositor-with-n.patch b/SOURCES/0001-Add-a-framework-for-restarting-the-compositor-with-n.patch
new file mode 100644
index 0000000..7291174
--- /dev/null
+++ b/SOURCES/0001-Add-a-framework-for-restarting-the-compositor-with-n.patch
@@ -0,0 +1,559 @@
+From 6710b03d1ebafc15ee4e826a5281204c6441c083 Mon Sep 17 00:00:00 2001
+From: "Owen W. Taylor" <otaylor@fishsoup.net>
+Date: Thu, 8 May 2014 18:35:49 -0400
+Subject: [PATCH 1/4] Add a framework for restarting the compositor with nice
+ visuals
+
+The current GNOME Shell Alt-F2 restart looks very messy and also
+provides no indication to the user what is going on. We need to
+restart the compositor to switch in and out of stereo mode, so
+add a framework for doing this more cleanly:
+
+Additions:
+
+ meta_restart(): restarts the compositor with a message
+ MetaDisplay::show-restart-message: signal the embedding
+    shell to show a message
+ MetaDisplay::restart: signal the embedding shell to restart
+    itself.
+ meta_is_restart(): indicates whether the current instance is a
+                    restart so we can suppress login animations.
+
+A helper program meta-restart-helper holds the composite overlay
+window up during the restart to avoid visual artifacts.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=733026
+---
+ configure.ac                |   1 +
+ src/Makefile.am             |   5 ++
+ src/compositor/compositor.c |   5 ++
+ src/core/display-private.h  |   7 ++
+ src/core/display.c          |  80 +++++++++++++++++
+ src/core/main.c             |   3 +
+ src/core/restart-helper.c   |  82 +++++++++++++++++
+ src/core/restart.c          | 212 ++++++++++++++++++++++++++++++++++++++++++++
+ src/meta/main.h             |   3 +
+ 9 files changed, 398 insertions(+)
+ create mode 100644 src/core/restart-helper.c
+ create mode 100644 src/core/restart.c
+
+diff --git a/configure.ac b/configure.ac
+index 6e9ca8c..dcd8a54 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -69,6 +69,7 @@ CLUTTER_PACKAGE=clutter-1.0
+ MUTTER_PC_MODULES="
+    gtk+-3.0 >= 3.3.7
+    gio-2.0 >= 2.25.10
++   gio-unix-2.0 >= 2.25.10
+    pango >= 1.2.0
+    cairo >= 1.10.0
+    gsettings-desktop-schemas >= 3.7.3
+diff --git a/src/Makefile.am b/src/Makefile.am
+index e2cec91..d664b54 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -119,6 +119,7 @@ libmutter_la_SOURCES =				\
+ 	core/screen-private.h			\
+ 	meta/screen.h				\
+ 	meta/types.h				\
++	core/restart.c				\
+ 	core/session.c				\
+ 	core/session.h				\
+ 	core/stack.c				\
+@@ -213,6 +214,10 @@ bin_PROGRAMS=mutter mutter-theme-viewer
+ mutter_SOURCES = core/mutter.c
+ mutter_LDADD = $(MUTTER_LIBS) libmutter.la
+ 
++libexec_PROGRAMS = mutter-restart-helper
++mutter_restart_helper_SOURCES = core/restart-helper.c
++mutter_restart_helper_LDADD = $(MUTTER_LIBS)
++
+ if HAVE_INTROSPECTION
+ include $(INTROSPECTION_MAKEFILE)
+ 
+diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
+index 91b477f..539a7a6 100644
+--- a/src/compositor/compositor.c
++++ b/src/compositor/compositor.c
+@@ -86,6 +86,7 @@
+ #include "meta-window-group.h"
+ #include "window-private.h" /* to check window->hidden */
+ #include "display-private.h" /* for meta_display_lookup_x_window() */
++#include "util-private.h"
+ #include <X11/extensions/shape.h>
+ #include <X11/extensions/Xcomposite.h>
+ 
+@@ -216,6 +217,10 @@ get_output_window (MetaScreen *screen)
+   xroot = meta_screen_get_xroot (screen);
+   output = XCompositeGetOverlayWindow (xdisplay, xroot);
+ 
++  /* Now that we've gotten taken a reference count on the COW, we
++   * can close the helper that is holding on to it */
++  meta_restart_finish ();
++
+   meta_core_add_old_event_mask (xdisplay, output, &mask);
+ 
+   XISetMask (mask.mask, XI_KeyPress);
+diff --git a/src/core/display-private.h b/src/core/display-private.h
+index 3423fb1..d227492 100644
+--- a/src/core/display-private.h
++++ b/src/core/display-private.h
+@@ -470,4 +470,11 @@ gboolean meta_display_process_barrier_event (MetaDisplay    *display,
+                                              XIBarrierEvent *event);
+ #endif /* HAVE_XI23 */
+ 
++gboolean meta_display_show_restart_message (MetaDisplay *display,
++                                            const char  *message);
++gboolean meta_display_request_restart      (MetaDisplay *display);
++
++void meta_restart_init (void);
++void meta_restart_finish (void);
++
+ #endif
+diff --git a/src/core/display.c b/src/core/display.c
+index d611314..9ed0f6e 100644
+--- a/src/core/display.c
++++ b/src/core/display.c
+@@ -146,6 +146,8 @@ enum
+   WINDOW_MARKED_URGENT,
+   GRAB_OP_BEGIN,
+   GRAB_OP_END,
++  SHOW_RESTART_MESSAGE,
++  RESTART,
+   LAST_SIGNAL
+ };
+ 
+@@ -322,6 +324,59 @@ meta_display_class_init (MetaDisplayClass *klass)
+                   META_TYPE_WINDOW,
+                   META_TYPE_GRAB_OP);
+ 
++  /**
++   * MetaDisplay::show-restart-message:
++   * @display: the #MetaDisplay instance
++   * @message: (allow-none): The message to display, or %NULL
++   *  to clear a previous restart message.
++   *
++   * The ::show-restart-message signal will be emitted to indicate
++   * that the compositor should show a message during restart. This is
++   * emitted when meta_restart() is called, either by Mutter
++   * internally or by the embedding compositor.  The message should be
++   * immediately added to the Clutter stage in its final form -
++   * ::restart will be emitted to exit the application and leave the
++   * stage contents frozen as soon as the the stage is painted again.
++   *
++   * On case of failure to restart, this signal will be emitted again
++   * with %NULL for @message.
++   *
++   * Returns: %TRUE means the message was added to the stage; %FALSE
++   *   indicates that the compositor did not show the message.
++   */
++  display_signals[SHOW_RESTART_MESSAGE] =
++    g_signal_new ("show-restart-message",
++                  G_TYPE_FROM_CLASS (klass),
++                  G_SIGNAL_RUN_LAST,
++                  0,
++                  g_signal_accumulator_true_handled,
++                  NULL, NULL,
++                  G_TYPE_BOOLEAN, 1,
++                  G_TYPE_STRING);
++
++  /**
++   * MetaDisplay::restart:
++   * @display: the #MetaDisplay instance
++   *
++   * The ::restart signal is emitted to indicate that compositor
++   * should reexec the process. This is
++   * emitted when meta_restart() is called, either by Mutter
++   * internally or by the embedding compositor. See also
++   * ::show-restart-message.
++   *
++   * Returns: %FALSE to indicate that the compositor could not
++   *  be restarted. When the compositor is restarted, the signal
++   *  should not return.
++   */
++  display_signals[RESTART] =
++    g_signal_new ("restart",
++                  G_TYPE_FROM_CLASS (klass),
++                  G_SIGNAL_RUN_LAST,
++                  0,
++                  g_signal_accumulator_true_handled,
++                  NULL, NULL,
++                  G_TYPE_BOOLEAN, 0);
++
+   g_object_class_install_property (object_class,
+                                    PROP_FOCUS_WINDOW,
+                                    g_param_spec_object ("focus-window",
+@@ -5856,3 +5911,28 @@ meta_display_clear_mouse_mode (MetaDisplay *display)
+ {
+   display->mouse_mode = FALSE;
+ }
++
++gboolean
++meta_display_show_restart_message (MetaDisplay *display,
++                                   const char  *message)
++{
++  gboolean result = FALSE;
++
++  g_signal_emit (display,
++                 display_signals[SHOW_RESTART_MESSAGE], 0,
++                 message, &result);
++
++  return result;
++}
++
++gboolean
++meta_display_request_restart (MetaDisplay *display)
++{
++  gboolean result = FALSE;
++
++  g_signal_emit (display,
++                 display_signals[RESTART], 0,
++                 &result);
++
++  return result;
++}
+diff --git a/src/core/main.c b/src/core/main.c
+index 4bec3d2..d5bde44 100644
+--- a/src/core/main.c
++++ b/src/core/main.c
+@@ -53,6 +53,7 @@
+ #include <meta/errors.h>
+ #include "ui.h"
+ #include "session.h"
++#include "stereo.h"
+ #include <meta/prefs.h>
+ #include <meta/compositor.h>
+ 
+@@ -441,6 +442,8 @@ meta_init (void)
+   
+   meta_ui_init ();
+ 
++  meta_restart_init ();
++
+   /*
+    * Clutter can only be initialized after the UI.
+    */
+diff --git a/src/core/restart-helper.c b/src/core/restart-helper.c
+new file mode 100644
+index 0000000..57a19fb
+--- /dev/null
++++ b/src/core/restart-helper.c
+@@ -0,0 +1,82 @@
++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
++
++/*
++ * SECTION:restart-helper
++ * @short_description: helper program during a restart
++ *
++ * To smoothly restart Mutter, we want to keep the composite
++ * overlay window enabled during the restart. This is done by
++ * spawning this program, which keeps a reference to the the composite
++ * overlay window until Mutter picks it back up.
++ */
++
++/*
++ * Copyright (C) 2014 Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <stdlib.h>
++#include <stdio.h>
++#include <X11/Xlib.h>
++#include <X11/extensions/Xcomposite.h>
++
++int
++main (int    argc,
++      char **argv)
++{
++  Display *display = XOpenDisplay (NULL);
++  Window selection_window;
++  XSetWindowAttributes xwa;
++  unsigned long mask = 0;
++
++  xwa.override_redirect = True;
++  mask |= CWOverrideRedirect;
++
++
++  XCompositeGetOverlayWindow (display, DefaultRootWindow (display));
++
++  selection_window = XCreateWindow (display,
++				    DefaultRootWindow (display),
++				    -100, -100, 1, 1, 0,
++				    0,
++				    InputOnly,
++				    DefaultVisual (display, DefaultScreen (display)),
++				    mask, &xwa);
++
++  XSetSelectionOwner (display,
++		      XInternAtom (display, "_MUTTER_RESTART_HELPER", False),
++		      selection_window,
++		      CurrentTime);
++
++  /* Mutter looks for an (arbitrary) line printed to stdout to know that
++   * we have started and have a reference to the COW. XSync() so that
++   * everything is set on the X server before Mutter starts restarting.
++   */
++  XSync (display, False);
++
++  printf ("STARTED\n");
++  fflush (stdout);
++
++  while (True)
++    {
++      XEvent xev;
++
++      XNextEvent (display, &xev);
++      /* Mutter restarted and unset the selection to indicate that
++       * it has a reference on the COW again */
++      if (xev.xany.type == SelectionClear)
++	return 0;
++    }
++}
+diff --git a/src/core/restart.c b/src/core/restart.c
+new file mode 100644
+index 0000000..04ef7d5
+--- /dev/null
++++ b/src/core/restart.c
+@@ -0,0 +1,212 @@
++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
++
++/*
++ * Copyright (C) 2014 Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++/*
++ * SECTION:restart
++ * @short_description: Smoothly restart the compositor
++ *
++ * There are some cases where we need to restart Mutter in order
++ * to deal with changes in state - the particular case inspiring
++ * this is enabling or disabling stereo output. To make this
++ * fairly smooth for the user, we need to do two things:
++ *
++ *  - Display a message to the user and make sure that it is
++ *    actually painted before we exit.
++ *  - Use a helper program so that the Composite Overlay Window
++ *    isn't unmapped and mapped.
++ *
++ * This handles both of these.
++ */
++
++#include <config.h>
++
++#include <clutter/clutter.h>
++#include <gio/gunixinputstream.h>
++
++#include <meta/main.h>
++#include <meta/util.h>
++#include "ui.h"
++#include "display-private.h"
++
++static gboolean restart_helper_started = FALSE;
++static gboolean restart_message_shown = FALSE;
++static gboolean is_restart = FALSE;
++
++void
++meta_restart_init (void)
++{
++  Display *xdisplay = meta_ui_get_display ();
++  Atom atom_restart_helper = XInternAtom (xdisplay, "_MUTTER_RESTART_HELPER", False);
++  Window restart_helper_window = NULL;
++
++  restart_helper_window = XGetSelectionOwner (xdisplay, atom_restart_helper);
++  if (restart_helper_window)
++    is_restart = TRUE;
++}
++
++static void
++restart_check_ready (void)
++{
++  if (restart_helper_started && restart_message_shown)
++    meta_display_request_restart (meta_get_display ());
++}
++
++static void
++restart_helper_read_line_callback (GObject      *source_object,
++                                   GAsyncResult *res,
++                                   gpointer      user_data)
++{
++  GError *error = NULL;
++  gsize length;
++  char *line = g_data_input_stream_read_line_finish_utf8 (G_DATA_INPUT_STREAM (source_object),
++                                                          res,
++                                                          &length, &error);
++  if (line == NULL)
++    {
++      meta_warning ("Failed to read output from restart helper%s%s\n",
++                    error ? ": " : NULL,
++                    error ? error->message : NULL);
++    }
++  else
++    g_free (line); /* We don't actually care what the restart helper outputs */
++
++  g_object_unref (source_object);
++
++  restart_helper_started = TRUE;
++  restart_check_ready ();
++}
++
++static gboolean
++restart_message_painted (gpointer data)
++{
++  restart_message_shown = TRUE;
++  restart_check_ready ();
++
++  return FALSE;
++}
++
++/**
++ * meta_restart:
++ * @message: message to display to the user.
++ *
++ * Starts the process of restarting the compositor. Note that Mutter's
++ * involvement here is to make the restart visually smooth for the
++ * user - it cannot itself safely reexec a program that embeds libmuttter.
++ * So in order for this to work, the compositor must handle two
++ * signals -  MetaDisplay::show-restart-message, to display the
++ * message passed here on the Clutter stage, and ::restart to actually
++ * reexec the compositor.
++ */
++void
++meta_restart (const char *message)
++{
++  MetaDisplay *display = meta_get_display();
++  GInputStream *unix_stream;
++  GDataInputStream *data_stream;
++  GError *error = NULL;
++  int helper_out_fd;
++
++  static const char * const helper_argv[] = {
++    MUTTER_LIBEXECDIR "/mutter-restart-helper", NULL
++  };
++
++  if (meta_display_show_restart_message (display, message))
++    {
++      /* Wait until the stage was painted */
++      clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT,
++                                             restart_message_painted,
++                                             NULL, NULL);
++    }
++  else
++    {
++      /* Can't show the message, show the message as soon as the
++       * restart helper starts
++       */
++      restart_message_painted (NULL);
++    }
++
++  /* We also need to wait for the restart helper to get its
++   * reference to the Composite Overlay Window.
++   */
++  if (!g_spawn_async_with_pipes (NULL, /* working directory */
++                                 (char **)helper_argv,
++                                 NULL, /* envp */
++                                 0, /* G_SPAWN_DEFAULT */
++                                 NULL, NULL, /* child_setup */
++                                 NULL, /* child_pid */
++                                 NULL, /* standard_input */
++                                 &helper_out_fd,
++                                 NULL, /* standard_error */
++                                 &error))
++    {
++      meta_warning ("Failed to start restart helper: %s\n", error->message);
++      goto error;
++    }
++
++  unix_stream = g_unix_input_stream_new (helper_out_fd, TRUE);
++  data_stream = g_data_input_stream_new (unix_stream);
++  g_object_unref (unix_stream);
++
++  g_data_input_stream_read_line_async (data_stream, G_PRIORITY_DEFAULT,
++                                       NULL, restart_helper_read_line_callback,
++                                       &error);
++  if (error != NULL)
++    {
++      meta_warning ("Failed to read from restart helper: %s\n", error->message);
++      g_object_unref (data_stream);
++      goto error;
++    }
++
++  return;
++
++ error:
++  /* If starting the restart helper fails, then we just go ahead and restart
++   * immediately. We won't get a smooth transition, since the overlay window
++   * will be destroyed and recreated, but otherwise it will work fine.
++   */
++  restart_helper_started = TRUE;
++  restart_check_ready ();
++
++  return;
++}
++
++void
++meta_restart_finish (void)
++{
++  if (is_restart)
++    {
++      Display *xdisplay = meta_display_get_xdisplay (meta_get_display ());
++      Atom atom_restart_helper = XInternAtom (xdisplay, "_MUTTER_RESTART_HELPER", False);
++      XSetSelectionOwner (xdisplay, atom_restart_helper, None, CurrentTime);
++    }
++}
++
++/**
++ * meta_is_restart:
++ *
++ * Returns %TRUE if this instance of Mutter comes from Mutter
++ * restarting itself (for example to enable/disable stereo.)
++ * See meta_restart(). If this is the case, any startup visuals
++ * or animations should be suppressed.
++ */
++gboolean
++meta_is_restart (void)
++{
++  return is_restart;
++}
+diff --git a/src/meta/main.h b/src/meta/main.h
+index dd4e7f1..af7a2c9 100644
+--- a/src/meta/main.h
++++ b/src/meta/main.h
+@@ -35,6 +35,9 @@ gboolean        meta_get_replace_current_wm (void);  /* Actually defined in util
+ void            meta_set_wm_name              (const char *wm_name);
+ void            meta_set_gnome_wm_keybindings (const char *wm_keybindings);
+ 
++void            meta_restart                (const char *message);
++gboolean        meta_is_restart             (void);
++
+ /**
+  * MetaExitCode:
+  * @META_EXIT_SUCCESS: Success
+-- 
+1.9.3
+
diff --git a/SOURCES/0001-MetaTextureTower-actually-mark-revalidated-levels-as.patch b/SOURCES/0001-MetaTextureTower-actually-mark-revalidated-levels-as.patch
new file mode 100644
index 0000000..27f6e35
--- /dev/null
+++ b/SOURCES/0001-MetaTextureTower-actually-mark-revalidated-levels-as.patch
@@ -0,0 +1,13 @@
+diff -up mutter-3.8.4/src/compositor/meta-texture-tower.c.texture-tower mutter-3.8.4/src/compositor/meta-texture-tower.c
+--- mutter-3.8.4/src/compositor/meta-texture-tower.c.texture-tower	2014-09-29 15:07:00.955634201 -0400
++++ mutter-3.8.4/src/compositor/meta-texture-tower.c	2014-09-29 15:08:01.656005996 -0400
+@@ -562,6 +562,9 @@ texture_tower_revalidate (MetaTextureTow
+ {
+   if (!texture_tower_revalidate_fbo (tower, level))
+     texture_tower_revalidate_client (tower, level);
++
++  tower->invalid[level].x1 = tower->invalid[level].x2 = 0;
++  tower->invalid[level].y1 = tower->invalid[level].y2 = 0;
+ }
+ 
+ /**
diff --git a/SOURCES/0001-window-Fix-delayed-mouse-mode-on-X.patch b/SOURCES/0001-window-Fix-delayed-mouse-mode-on-X.patch
new file mode 100644
index 0000000..1b101f2
--- /dev/null
+++ b/SOURCES/0001-window-Fix-delayed-mouse-mode-on-X.patch
@@ -0,0 +1,41 @@
+From 8c4610721a117d5d50fc72fb75e41a6727d93b2d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
+Date: Wed, 7 May 2014 23:22:41 +0200
+Subject: [PATCH] window: Fix delayed mouse mode on X
+
+Using meta_stack_get_default_focus_window_at_point() is unreliable
+when used with the overlay windows or popups. Instead, we can just
+look up the MetaWindow for the client window that XIQueryPointer
+returns.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=730541
+---
+ src/core/display.c | 12 +-----------
+ 1 file changed, 1 insertion(+), 11 deletions(-)
+
+diff --git a/src/core/display.c b/src/core/display.c
+index 435d9d9..b7688e6 100644
+--- a/src/core/display.c
++++ b/src/core/display.c
+@@ -1703,17 +1703,7 @@ window_focus_on_pointer_rest_callback (gpointer data) {
+       return TRUE;
+     }
+ 
+-  /* Explicitly check for the overlay window, as get_focus_window_at_point()
+-   * may return windows that extend underneath the chrome (like
+-   * override-redirect or DESKTOP windows)
+-   */
+-  if (child == meta_get_overlay_window (screen))
+-    goto out;
+-
+-  window =
+-      meta_stack_get_default_focus_window_at_point (screen->stack,
+-                                                    screen->active_workspace,
+-                                                    None, root_x, root_y);
++  window = meta_display_lookup_x_window (display, child);
+ 
+   if (window == NULL)
+     goto out;
+-- 
+2.1.0
+
diff --git a/SOURCES/0002-Add-support-for-quad-buffer-stereo.patch b/SOURCES/0002-Add-support-for-quad-buffer-stereo.patch
new file mode 100644
index 0000000..c3d0c82
--- /dev/null
+++ b/SOURCES/0002-Add-support-for-quad-buffer-stereo.patch
@@ -0,0 +1,909 @@
+From 9ceccaf38295d73b729bc3a6777fa6b948fa4007 Mon Sep 17 00:00:00 2001
+From: "Owen W. Taylor" <otaylor@fishsoup.net>
+Date: Thu, 8 May 2014 18:44:15 -0400
+Subject: [PATCH] Add support for quad-buffer stereo
+
+Track the stereo status of windows using the new EXT_stereo_tree
+GLX extension.
+
+When stereo is enabled or disabled, a restart is triggered via
+meta_restart() after a timeout, setting a _META_ENABLE_STEREO
+property on the root window to indicate whether we should
+turn on a stereo stage for clutter. The property avoids a loop,
+since we need to enable stereo *before* initializing Clutter and GL,
+but we need GL to figure out whether we have stereo windows.
+
+Stereo windows are drawn to the stage using new functionality
+in Cogl to setup a stereo context, select which buffer to draw
+to, and draw either the left or right buffer of a stereo
+texture_from_pixmap.
+---
+ src/Makefile.am                              |   2 +
+ src/compositor/compositor-private.h          |  10 ++
+ src/compositor/compositor.c                  | 127 +++++++++++++++++++-
+ src/compositor/meta-shaped-texture-private.h |  37 ++++++
+ src/compositor/meta-shaped-texture.c         | 166 ++++++++++++++++++++-------
+ src/compositor/meta-window-actor-private.h   |   7 ++
+ src/compositor/meta-window-actor.c           |  27 ++++-
+ src/core/main.c                              |   2 +
+ src/core/stereo.c                            | 144 +++++++++++++++++++++++
+ src/core/stereo.h                            |  28 +++++
+ src/meta/meta-shaped-texture.h               |   3 +-
+ 11 files changed, 508 insertions(+), 45 deletions(-)
+ create mode 100644 src/compositor/meta-shaped-texture-private.h
+ create mode 100644 src/core/stereo.c
+ create mode 100644 src/core/stereo.h
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index d664b54..1d2422e 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -122,6 +122,8 @@ libmutter_la_SOURCES =				\
+ 	core/restart.c				\
+ 	core/session.c				\
+ 	core/session.h				\
++	core/stereo.c				\
++	core/stereo.h				\
+ 	core/stack.c				\
+ 	core/stack.h				\
+ 	core/stack-tracker.c			\
+diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h
+index acb8d3c..b4c5c16 100644
+--- a/src/compositor/compositor-private.h
++++ b/src/compositor/compositor-private.h
+@@ -28,6 +28,8 @@ struct _MetaCompositor
+   gint64          server_time_query_time;
+   gint64          server_time_offset;
+ 
++  int             glx_opcode;
++
+   guint           server_time_is_monotonic_time : 1;
+   guint           show_redraw : 1;
+   guint           debug       : 1;
+@@ -56,6 +58,9 @@ struct _MetaCompScreen
+ 
+   gint                   switch_workspace_in_progress;
+ 
++  guint                  stereo_tree_ext : 1;
++  guint                  have_stereo_windows : 1;
++
+   MetaPluginManager *plugin_mgr;
+ };
+ 
+@@ -79,4 +84,9 @@ gint64 meta_compositor_monotonic_time_to_server_time (MetaDisplay *display,
+ 
+ void meta_check_end_modal (MetaScreen *screen);
+ 
++gboolean meta_compositor_window_is_stereo     (MetaScreen *screen,
++                                               Window      xwindow);
++void     meta_compositor_select_stereo_notify (MetaScreen *screen,
++                                               Window      xwindow);
++
+ #endif /* META_COMPOSITOR_PRIVATE_H */
+diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
+index 539a7a6..fd29e48 100644
+--- a/src/compositor/compositor.c
++++ b/src/compositor/compositor.c
+@@ -86,7 +86,8 @@
+ #include "meta-window-group.h"
+ #include "window-private.h" /* to check window->hidden */
+ #include "display-private.h" /* for meta_display_lookup_x_window() */
+-#include "util-private.h"
++#include "stack-tracker.h"
++#include "stereo.h"
+ #include <X11/extensions/shape.h>
+ #include <X11/extensions/Xcomposite.h>
+ 
+@@ -579,6 +580,101 @@ redirect_windows (MetaCompositor *compositor,
+     }
+ }
+ 
++#define GLX_STEREO_TREE_EXT        0x20F5
++#define GLX_STEREO_NOTIFY_MASK_EXT 0x00000001
++#define GLX_STEREO_NOTIFY_EXT      0x00000000
++
++typedef struct {
++  int type;
++  unsigned long serial;
++  Bool send_event;
++  Display *display;
++  int extension;
++  int evtype;
++  Drawable window;
++  Bool stereo_tree;
++} StereoNotifyEvent;
++
++static gboolean
++screen_has_stereo_tree_ext (MetaScreen *screen)
++{
++#if 0
++  MetaDisplay *display = meta_screen_get_display (screen);
++  Display     *xdisplay = meta_display_get_xdisplay (display);
++  const char *extensions_string;
++
++  static const char * (*query_extensions_string) (Display *display,
++                                                  int      screen);
++
++  if (query_extensions_string == NULL)
++    query_extensions_string =
++      (const char * (*) (Display *, int))
++      cogl_get_proc_address ("glXQueryExtensionsString");
++
++  extensions_string = query_extensions_string (xdisplay,
++                                               meta_screen_get_screen_number (screen));
++
++  return strstr (extensions_string, "EXT_stereo_tree") != 0;
++#else
++  return TRUE;
++#endif
++}
++
++#include <GL/gl.h>
++
++gboolean
++meta_compositor_window_is_stereo (MetaScreen *screen,
++                                  Window      xwindow)
++{
++  MetaCompScreen *info = meta_screen_get_compositor_data (screen);
++  MetaDisplay    *display = meta_screen_get_display (screen);
++  Display        *xdisplay = meta_display_get_xdisplay (display);
++
++  static int (*query_drawable) (Display      *dpy,
++                                Drawable      draw,
++                                int           attribute,
++                                unsigned int *value);
++
++  if (info->stereo_tree_ext)
++    {
++      unsigned int stereo_tree = 0;
++
++      if (query_drawable == NULL)
++        query_drawable =
++          (int (*) (Display *, Drawable, int, unsigned int *))
++          cogl_get_proc_address ("glXQueryDrawable");
++
++      query_drawable (xdisplay, xwindow, GLX_STEREO_TREE_EXT, &stereo_tree);
++
++      return stereo_tree != 0;
++    }
++  else
++    return FALSE;
++}
++
++void
++meta_compositor_select_stereo_notify (MetaScreen *screen,
++                                      Window      xwindow)
++{
++  MetaCompScreen *info = meta_screen_get_compositor_data (screen);
++  MetaDisplay    *display = meta_screen_get_display (screen);
++  Display        *xdisplay = meta_display_get_xdisplay (display);
++
++  static void (*select_event) (Display      *dpy,
++                               Drawable      draw,
++                               unsigned long event_mask);
++
++  if (info->stereo_tree_ext)
++    {
++      if (select_event == NULL)
++        select_event =
++          (void (*) (Display *, Drawable, unsigned long))
++          cogl_get_proc_address ("glXSelectEvent");
++
++      select_event (xdisplay, xwindow, GLX_STEREO_NOTIFY_MASK_EXT);
++    }
++}
++
+ void
+ meta_compositor_manage_screen (MetaCompositor *compositor,
+                                MetaScreen     *screen)
+@@ -609,6 +705,8 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
+   info->output = None;
+   info->windows = NULL;
+ 
++  info->stereo_tree_ext = screen_has_stereo_tree_ext (screen);
++
+   meta_screen_set_cm_selection (screen);
+ 
+   info->stage = clutter_stage_new ();
+@@ -995,6 +1093,23 @@ meta_compositor_process_event (MetaCompositor *compositor,
+ 	  DEBUG_TRACE ("meta_compositor_process_event (process_damage)\n");
+           process_damage (compositor, (XDamageNotifyEvent *) event, window);
+         }
++      else if (event->type == GenericEvent &&
++               event->xcookie.extension == compositor->glx_opcode)
++        {
++          if (event->xcookie.evtype == GLX_STEREO_NOTIFY_EXT)
++            {
++              StereoNotifyEvent *stereo_event = (StereoNotifyEvent *)(event->xcookie.data);
++              window = meta_display_lookup_x_window (compositor->display, stereo_event->window);
++
++              if (window != NULL)
++                {
++                  MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
++                  meta_window_actor_stereo_notify (window_actor, stereo_event->stereo_tree);
++                  meta_stack_tracker_queue_sync_stack (window->screen->stack_tracker);
++                }
++            }
++        }
++
+       break;
+     }
+ 
+@@ -1209,6 +1324,7 @@ meta_compositor_sync_stack (MetaCompositor  *compositor,
+ {
+   GList *old_stack;
+   MetaCompScreen *info = meta_screen_get_compositor_data (screen);
++  int stereo_window_count = 0;
+ 
+   DEBUG_TRACE ("meta_compositor_sync_stack\n");
+ 
+@@ -1286,12 +1402,16 @@ meta_compositor_sync_stack (MetaCompositor  *compositor,
+        * near the front of the other.)
+        */
+       info->windows = g_list_prepend (info->windows, actor);
++      if (meta_window_actor_is_stereo (actor))
++        stereo_window_count++;
+ 
+       stack = g_list_remove (stack, window);
+       old_stack = g_list_remove (old_stack, actor);
+     }
+ 
+   sync_actor_stacking (info);
++
++  meta_stereo_set_have_stereo_windows (stereo_window_count > 0);
+ }
+ 
+ void
+@@ -1505,6 +1625,7 @@ meta_compositor_new (MetaDisplay *display)
+   Atom                   atoms[G_N_ELEMENTS(atom_names)];
+   MetaCompositor        *compositor;
+   Display               *xdisplay = meta_display_get_xdisplay (display);
++  int glx_major_opcode, glx_first_event, glx_first_error;
+ 
+   if (!composite_at_least_version (display, 0, 3))
+     return NULL;
+@@ -1531,6 +1652,10 @@ meta_compositor_new (MetaDisplay *display)
+   compositor->repaint_func_id = clutter_threads_add_repaint_func (meta_repaint_func,
+                                                                   compositor,
+                                                                   NULL);
++  if (XQueryExtension (xdisplay,
++                       "GLX",
++                       &glx_major_opcode, &glx_first_event, &glx_first_error))
++    compositor->glx_opcode = glx_major_opcode;
+ 
+   return compositor;
+ }
+diff --git a/src/compositor/meta-shaped-texture-private.h b/src/compositor/meta-shaped-texture-private.h
+new file mode 100644
+index 0000000..c70f6a8
+--- /dev/null
++++ b/src/compositor/meta-shaped-texture-private.h
+@@ -0,0 +1,37 @@
++/*
++ * shaped texture
++ *
++ * An actor to draw a texture clipped to a list of rectangles
++ *
++ * Authored By Neil Roberts  <neil@linux.intel.com>
++ *
++ * Copyright (C) 2008 Intel Corporation
++ *               2013 Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
++ * 02111-1307, USA.
++ */
++
++#ifndef __META_SHAPED_TEXTURE_PRIVATE_H__
++#define __META_SHAPED_TEXTURE_PRIVATE_H__
++
++#include <meta/meta-shaped-texture.h>
++
++ClutterActor *meta_shaped_texture_new (void);
++gboolean meta_shaped_texture_get_unobscured_bounds (MetaShapedTexture     *stex,
++                                                    cairo_rectangle_int_t *unobscured_bounds);
++gboolean meta_shaped_texture_is_obscured (MetaShapedTexture *self);
++
++#endif
+diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c
+index c6239c9..132cb09 100644
+--- a/src/compositor/meta-shaped-texture.c
++++ b/src/compositor/meta-shaped-texture.c
+@@ -65,8 +65,10 @@ G_DEFINE_TYPE (MetaShapedTexture, meta_shaped_texture,
+ struct _MetaShapedTexturePrivate
+ {
+   MetaTextureTower *paint_tower;
++  MetaTextureTower *paint_tower_right;
+   Pixmap pixmap;
+   CoglTexturePixmapX11 *texture;
++  CoglTexturePixmapX11 *texture_right;
+   CoglTexture *mask_texture;
+   CoglPipeline *pipeline;
+   CoglPipeline *pipeline_unshaped;
+@@ -75,6 +77,7 @@ struct _MetaShapedTexturePrivate
+ 
+   guint tex_width, tex_height;
+ 
++  guint stereo : 1;
+   guint create_mipmaps : 1;
+ };
+ 
+@@ -103,7 +106,9 @@ meta_shaped_texture_init (MetaShapedTexture *self)
+   priv = self->priv = META_SHAPED_TEXTURE_GET_PRIVATE (self);
+ 
+   priv->paint_tower = meta_texture_tower_new ();
++  priv->paint_tower_right = NULL; /* demand create */
+   priv->texture = NULL;
++  priv->texture_right = NULL;
+   priv->mask_texture = NULL;
+   priv->create_mipmaps = TRUE;
+ }
+@@ -114,13 +119,13 @@ meta_shaped_texture_dispose (GObject *object)
+   MetaShapedTexture *self = (MetaShapedTexture *) object;
+   MetaShapedTexturePrivate *priv = self->priv;
+ 
+-  if (priv->paint_tower)
+-    meta_texture_tower_free (priv->paint_tower);
+-  priv->paint_tower = NULL;
++  g_clear_pointer (&priv->paint_tower, meta_texture_tower_free);
++  g_clear_pointer (&priv->paint_tower_right, meta_texture_tower_free);
+ 
+   g_clear_pointer (&priv->pipeline, cogl_object_unref);
+   g_clear_pointer (&priv->pipeline_unshaped, cogl_object_unref);
+   g_clear_pointer (&priv->texture, cogl_object_unref);
++  g_clear_pointer (&priv->texture_right, cogl_object_unref);
+ 
+   meta_shaped_texture_set_mask_texture (self, NULL);
+   meta_shaped_texture_set_clip_region (self, NULL);
+@@ -129,11 +134,11 @@ meta_shaped_texture_dispose (GObject *object)
+ }
+ 
+ static void
+-meta_shaped_texture_paint (ClutterActor *actor)
++paint_texture (MetaShapedTexture *stex,
++               CoglTexture       *paint_tex)
+ {
+-  MetaShapedTexture *stex = (MetaShapedTexture *) actor;
+   MetaShapedTexturePrivate *priv = stex->priv;
+-  CoglTexture *paint_tex;
++  ClutterActor *actor = CLUTTER_ACTOR (stex);
+   guint tex_width, tex_height;
+   ClutterActorBox alloc;
+ 
+@@ -145,32 +150,6 @@ meta_shaped_texture_paint (ClutterActor *actor)
+   if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
+     return;
+ 
+-  if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex)))
+-    clutter_actor_realize (CLUTTER_ACTOR (stex));
+-
+-  /* The GL EXT_texture_from_pixmap extension does allow for it to be
+-   * used together with SGIS_generate_mipmap, however this is very
+-   * rarely supported. Also, even when it is supported there
+-   * are distinct performance implications from:
+-   *
+-   *  - Updating mipmaps that we don't need
+-   *  - Having to reallocate pixmaps on the server into larger buffers
+-   *
+-   * So, we just unconditionally use our mipmap emulation code. If we
+-   * wanted to use SGIS_generate_mipmap, we'd have to  query COGL to
+-   * see if it was supported (no API currently), and then if and only
+-   * if that was the case, set the clutter texture quality to HIGH.
+-   * Setting the texture quality to high without SGIS_generate_mipmap
+-   * support for TFP textures will result in fallbacks to XGetImage.
+-   */
+-  if (priv->create_mipmaps)
+-    paint_tex = meta_texture_tower_get_paint_texture (priv->paint_tower);
+-  else
+-    paint_tex = COGL_TEXTURE (priv->texture);
+-
+-  if (paint_tex == NULL)
+-    return;
+-
+   tex_width = priv->tex_width;
+   tex_height = priv->tex_height;
+ 
+@@ -279,6 +258,76 @@ meta_shaped_texture_paint (ClutterActor *actor)
+ }
+ 
+ static void
++meta_shaped_texture_paint (ClutterActor *actor)
++{
++  MetaShapedTexture *stex = (MetaShapedTexture *) actor;
++  MetaShapedTexturePrivate *priv = stex->priv;
++  CoglFramebuffer *fb;
++  gboolean stereo;
++  CoglTexture *paint_tex;
++  CoglTexture *paint_tex_right;
++
++  if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
++    return;
++
++  if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex)))
++    clutter_actor_realize (CLUTTER_ACTOR (stex));
++
++  /* The GL EXT_texture_from_pixmap extension does allow for it to be
++   * used together with SGIS_generate_mipmap, however this is very
++   * rarely supported. Also, even when it is supported there
++   * are distinct performance implications from:
++   *
++   *  - Updating mipmaps that we don't need
++   *  - Having to reallocate pixmaps on the server into larger buffers
++   *
++   * So, we just unconditionally use our mipmap emulation code. If we
++   * wanted to use SGIS_generate_mipmap, we'd have to  query COGL to
++   * see if it was supported (no API currently), and then if and only
++   * if that was the case, set the clutter texture quality to HIGH.
++   * Setting the texture quality to high without SGIS_generate_mipmap
++   * support for TFP textures will result in fallbacks to XGetImage.
++   */
++  if (priv->create_mipmaps)
++    paint_tex = meta_texture_tower_get_paint_texture (priv->paint_tower);
++  else
++    paint_tex = COGL_TEXTURE (priv->texture);
++
++  if (paint_tex == NULL)
++    return;
++
++  fb = cogl_get_draw_framebuffer ();
++
++  stereo = priv->stereo && cogl_framebuffer_get_is_stereo (fb);
++
++  if (stereo)
++    {
++      if (priv->create_mipmaps)
++	paint_tex_right = meta_texture_tower_get_paint_texture (priv->paint_tower_right);
++      else
++	paint_tex_right = COGL_TEXTURE (priv->texture_right);
++    }
++  else
++    paint_tex_right = NULL;
++
++  if (paint_tex != NULL)
++    {
++      if (stereo)
++	cogl_framebuffer_set_stereo_mode (fb, COGL_STEREO_LEFT);
++      paint_texture (stex, paint_tex);
++      if (stereo)
++	cogl_framebuffer_set_stereo_mode (fb, COGL_STEREO_BOTH);
++    }
++
++  if (paint_tex_right != NULL)
++    {
++      cogl_framebuffer_set_stereo_mode (fb, COGL_STEREO_RIGHT);
++      paint_texture (stex, paint_tex_right);
++      cogl_framebuffer_set_stereo_mode (fb, COGL_STEREO_BOTH);
++    }
++}
++
++static void
+ meta_shaped_texture_pick (ClutterActor       *actor,
+ 			  const ClutterColor *color)
+ {
+@@ -392,6 +441,12 @@ meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
+       base_texture = create_mipmaps ?
+         COGL_TEXTURE (priv->texture) : NULL;
+       meta_texture_tower_set_base_texture (priv->paint_tower, base_texture);
++
++      if (priv->stereo)
++	{
++	  base_texture = create_mipmaps ? COGL_TEXTURE (priv->texture_right) : NULL;
++	  meta_texture_tower_set_base_texture (priv->paint_tower_right, base_texture);
++	}
+     }
+ }
+ 
+@@ -435,13 +490,16 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
+                                        x, y, width, height);
+ 
+   meta_texture_tower_update_area (priv->paint_tower, x, y, width, height);
++  if (priv->stereo)
++    meta_texture_tower_update_area (priv->paint_tower_right, x, y, width, height);
+ 
+   clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &clip);
+ }
+ 
+ static void
+ set_cogl_texture (MetaShapedTexture    *stex,
+-                  CoglTexturePixmapX11 *cogl_tex)
++                  CoglTexturePixmapX11 *cogl_tex,
++                  gboolean              stereo)
+ {
+   MetaShapedTexturePrivate *priv;
+   guint width, height;
+@@ -452,9 +510,17 @@ set_cogl_texture (MetaShapedTexture    *stex,
+ 
+   if (priv->texture != NULL)
+     cogl_object_unref (priv->texture);
++  if (priv->texture_right != NULL)
++    cogl_object_unref (priv->texture_right);
+ 
++  priv->stereo = stereo;
+   priv->texture = cogl_tex;
+ 
++  if (priv->stereo)
++    priv->texture_right = cogl_texture_pixmap_x11_new_right ((CoglTexturePixmapX11 *)cogl_tex);
++  else
++    priv->texture_right = NULL;
++
+   if (priv->pipeline != NULL)
+     cogl_pipeline_set_layer_texture (priv->pipeline, 0, COGL_TEXTURE (cogl_tex));
+ 
+@@ -493,7 +559,8 @@ set_cogl_texture (MetaShapedTexture    *stex,
+  */
+ void
+ meta_shaped_texture_set_pixmap (MetaShapedTexture *stex,
+-                                Pixmap             pixmap)
++                                Pixmap             pixmap,
++                                gboolean           stereo)
+ {
+   MetaShapedTexturePrivate *priv;
+ 
+@@ -501,23 +568,44 @@ meta_shaped_texture_set_pixmap (MetaShapedTexture *stex,
+ 
+   priv = stex->priv;
+ 
+-  if (priv->pixmap == pixmap)
++  if (priv->pixmap == pixmap && priv->stereo == stereo)
+     return;
+ 
+   priv->pixmap = pixmap;
++  priv->stereo = stereo;
+ 
+   if (pixmap != None)
+     {
+       CoglContext *ctx =
+         clutter_backend_get_cogl_context (clutter_get_default_backend ());
+-      set_cogl_texture (stex, cogl_texture_pixmap_x11_new (ctx, pixmap, FALSE, NULL));
++      CoglTexturePixmapX11 *texture;
++      if (priv->stereo)
++        texture = cogl_texture_pixmap_x11_new_left (ctx, pixmap, FALSE, NULL);
++      else
++        texture = cogl_texture_pixmap_x11_new (ctx, pixmap, FALSE, NULL);
++      set_cogl_texture (stex, texture, stereo);
+     }
+   else
+-    set_cogl_texture (stex, NULL);
++    set_cogl_texture (stex, NULL, stereo);
++
++  if (priv->stereo)
++    {
++      if (priv->paint_tower_right == NULL)
++	priv->paint_tower_right = meta_texture_tower_new ();
++    }
++  else
++    {
++      g_clear_pointer (&priv->paint_tower_right, meta_texture_tower_free);
++    }
+ 
+   if (priv->create_mipmaps)
+-    meta_texture_tower_set_base_texture (priv->paint_tower,
+-                                         COGL_TEXTURE (priv->texture));
++    {
++      meta_texture_tower_set_base_texture (priv->paint_tower,
++                                           COGL_TEXTURE (priv->texture));
++      if (priv->stereo)
++	meta_texture_tower_set_base_texture (priv->paint_tower_right,
++					     COGL_TEXTURE (priv->texture_right));
++    }
+ }
+ 
+ /**
+diff --git a/src/compositor/meta-window-actor-private.h b/src/compositor/meta-window-actor-private.h
+index 90a9e35..914a8db 100644
+--- a/src/compositor/meta-window-actor-private.h
++++ b/src/compositor/meta-window-actor-private.h
+@@ -66,4 +66,11 @@ void meta_window_actor_reset_visible_regions      (MetaWindowActor *self);
+ void meta_window_actor_effect_completed (MetaWindowActor *actor,
+                                          gulong           event);
+ 
++void     meta_window_actor_stereo_notify (MetaWindowActor *actor,
++                                          gboolean         stereo_tree);
++
++gboolean meta_window_actor_is_stereo (MetaWindowActor *actor);
++
++void meta_window_actor_detach (MetaWindowActor *self);
++
+ #endif /* META_WINDOW_ACTOR_PRIVATE_H */
+diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
+index 42d1257..1a11d0e 100644
+--- a/src/compositor/meta-window-actor.c
++++ b/src/compositor/meta-window-actor.c
+@@ -108,6 +108,7 @@ struct _MetaWindowActorPrivate
+   guint		    visible                : 1;
+   guint		    mapped                 : 1;
+   guint		    argb32                 : 1;
++  guint		    stereo                 : 1;
+   guint		    disposed               : 1;
+   guint             redecorating           : 1;
+ 
+@@ -175,7 +176,6 @@ static gboolean meta_window_actor_get_paint_volume (ClutterActor       *actor,
+                                                     ClutterPaintVolume *volume);
+ 
+ 
+-static void     meta_window_actor_detach     (MetaWindowActor *self);
+ static gboolean meta_window_actor_has_shadow (MetaWindowActor *self);
+ 
+ static void meta_window_actor_handle_updates (MetaWindowActor *self);
+@@ -362,6 +362,9 @@ meta_window_actor_constructed (GObject *object)
+   if (format && format->type == PictTypeDirect && format->direct.alphaMask)
+     priv->argb32 = TRUE;
+ 
++  priv->stereo = meta_compositor_window_is_stereo (screen, xwindow);
++  meta_compositor_select_stereo_notify (screen, xwindow);
++
+   if (!priv->actor)
+     {
+       priv->actor = meta_shaped_texture_new ();
+@@ -1218,7 +1221,7 @@ meta_window_actor_effect_completed (MetaWindowActor *self,
+  * when the window is unmapped or when we want to update to a new
+  * pixmap for a new size.
+  */
+-static void
++void
+ meta_window_actor_detach (MetaWindowActor *self)
+ {
+   MetaWindowActorPrivate *priv     = self->priv;
+@@ -1234,7 +1237,7 @@ meta_window_actor_detach (MetaWindowActor *self)
+    * pixmap, but it certainly doesn't work with current DRI/Mesa
+    */
+   meta_shaped_texture_set_pixmap (META_SHAPED_TEXTURE (priv->actor),
+-                                  None);
++                                  None, FALSE);
+   cogl_flush();
+ 
+   XFreePixmap (xdisplay, priv->back_pixmap);
+@@ -1823,7 +1826,7 @@ check_needs_pixmap (MetaWindowActor *self)
+                                                 FALSE);
+ 
+       meta_shaped_texture_set_pixmap (META_SHAPED_TEXTURE (priv->actor),
+-                                      priv->back_pixmap);
++                                      priv->back_pixmap, priv->stereo);
+ 
+       texture = meta_shaped_texture_get_texture (META_SHAPED_TEXTURE (priv->actor));
+ 
+@@ -2575,3 +2578,19 @@ meta_window_actor_set_updates_frozen (MetaWindowActor *self,
+         meta_window_actor_thaw (self);
+     }
+ }
++
++void
++meta_window_actor_stereo_notify (MetaWindowActor *self,
++                                 gboolean         stereo_tree)
++{
++  MetaWindowActorPrivate *priv = self->priv;
++
++  priv->stereo = stereo_tree;
++  meta_window_actor_detach (self);
++}
++
++gboolean
++meta_window_actor_is_stereo (MetaWindowActor *self)
++{
++  return self->priv->stereo;
++}
+diff --git a/src/core/main.c b/src/core/main.c
+index d5bde44..8092afc 100644
+--- a/src/core/main.c
++++ b/src/core/main.c
+@@ -444,6 +444,8 @@ meta_init (void)
+ 
+   meta_restart_init ();
+ 
++  meta_stereo_init ();
++
+   /*
+    * Clutter can only be initialized after the UI.
+    */
+diff --git a/src/core/stereo.c b/src/core/stereo.c
+new file mode 100644
+index 0000000..d16a210
+--- /dev/null
++++ b/src/core/stereo.c
+@@ -0,0 +1,144 @@
++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
++
++/*
++ * Copyright (C) 2014 Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++/*
++ * SECTION:stereo
++ * @short_description: Keep track of whether we are a stereo compositor
++ *
++ * With GLX, we need to use a different GL context for stereo and
++ * non-stereo support. Support for multiple GL contexts is unfinished
++ * in Cogl and entirely lacking in Clutter, so it's by far easier
++ * to just restart Mutter when we detect a stereo window.
++ *
++ * A property _MUTTER_ENABLE_STEREO is maintained on the root window
++ * to know whether we should initialize clutter for stereo or not.
++ * When the presence or absence of stereo windows mismatches the
++ * stereo-enabled state for a sufficiently long period of time,
++ * we restart Mutter.
++ */
++
++#include <config.h>
++
++#include <clutter/x11/clutter-x11.h>
++#include <gio/gunixinputstream.h>
++#include <X11/Xatom.h>
++
++#include <meta/main.h>
++#include "ui.h"
++#include <meta/util.h>
++#include "display-private.h"
++#include "stereo.h"
++
++static guint stereo_switch_id = 0;
++static gboolean stereo_enabled = FALSE;
++/* -1 so the first time meta_stereo_set_have_stereo_windows() is called
++ * we avoid the short-circuit and set up a timeout to restart
++ * if necessary */
++static gboolean stereo_have_windows = (gboolean)-1;
++static gboolean stereo_restart = FALSE;
++
++#define STEREO_ENABLE_WAIT 1000
++#define STEREO_DISABLE_WAIT 5000
++
++void
++meta_stereo_init (void)
++{
++  Display *xdisplay = meta_ui_get_display ();
++  Window root = DefaultRootWindow (xdisplay);
++  Atom atom_enable_stereo = XInternAtom (xdisplay, "_MUTTER_ENABLE_STEREO", False);
++  Atom type;
++  int format;
++  unsigned long n_items, bytes_after;
++  guchar *data;
++
++  XGetWindowProperty (xdisplay, root, atom_enable_stereo,
++                      0, 1, False, XA_INTEGER,
++                      &type, &format, &n_items, &bytes_after, &data);
++  if (type == XA_INTEGER)
++    {
++      if (format == 32 && n_items == 1 && bytes_after == 0)
++        {
++          stereo_enabled = *(long *)data;
++        }
++      else
++        {
++          meta_warning ("Bad value for _MUTTER_ENABLE_STEREO property\n");
++        }
++
++      XFree (data);
++    }
++  else if (type != None)
++    {
++      meta_warning ("Bad type for _MUTTER_ENABLE_STEREO property\n");
++    }
++
++  meta_verbose ("On startup, _MUTTER_ENABLE_STEREO=%s",
++                stereo_enabled ? "yes" : "no");
++  clutter_x11_set_use_stereo_stage (stereo_enabled);
++}
++
++static gboolean
++meta_stereo_switch (gpointer data)
++{
++  stereo_switch_id = 0;
++  stereo_restart = TRUE;
++
++  meta_restart (stereo_have_windows ?
++                _("Enabling stereo...") :
++                _("Disabling stereo..."));
++
++  return FALSE;
++}
++
++void
++meta_stereo_set_have_stereo_windows (gboolean have_windows)
++{
++  have_windows = have_windows != FALSE;
++
++  if (!stereo_restart && have_windows != stereo_have_windows)
++    {
++      MetaDisplay *display = meta_get_display ();
++      Display *xdisplay = meta_display_get_xdisplay (display);
++      Window root = DefaultRootWindow (xdisplay);
++      Atom atom_enable_stereo = XInternAtom (xdisplay, "_MUTTER_ENABLE_STEREO", False);
++      long value;
++
++      stereo_have_windows = have_windows;
++
++      if (stereo_have_windows)
++        meta_verbose ("Detected stereo windows\n");
++      else
++        meta_verbose ("No stereo windows detected\n");
++
++      value = stereo_have_windows;
++      XChangeProperty (xdisplay, root,
++                       atom_enable_stereo, XA_INTEGER, 32,
++                       PropModeReplace, (guchar *)&value, 1);
++
++      if (stereo_switch_id != 0)
++        {
++          g_source_remove (stereo_switch_id);
++          stereo_switch_id = 0;
++        }
++
++      if (stereo_have_windows != stereo_enabled)
++        stereo_switch_id = g_timeout_add (stereo_have_windows ? STEREO_ENABLE_WAIT : STEREO_DISABLE_WAIT,
++                                          meta_stereo_switch, NULL);
++    }
++}
+diff --git a/src/core/stereo.h b/src/core/stereo.h
+new file mode 100644
+index 0000000..ccd1d70
+--- /dev/null
++++ b/src/core/stereo.h
+@@ -0,0 +1,28 @@
++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
++
++/*
++ * Copyright (C) 2014 Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef META_STEREO_H
++#define META_STEREO_H
++
++void     meta_stereo_init                    (void);
++void     meta_stereo_set_have_stereo_windows (gboolean have_windows);
++gboolean meta_stereo_is_restart              (void);
++void     meta_stereo_finish_restart          (void);
++
++#endif
+diff --git a/src/meta/meta-shaped-texture.h b/src/meta/meta-shaped-texture.h
+index 28fb5f6..fcf33c3 100644
+--- a/src/meta/meta-shaped-texture.h
++++ b/src/meta/meta-shaped-texture.h
+@@ -76,7 +76,8 @@ void meta_shaped_texture_update_area (MetaShapedTexture *stex,
+                                       int                height);
+ 
+ void meta_shaped_texture_set_pixmap (MetaShapedTexture *stex,
+-                                     Pixmap             pixmap);
++                                     Pixmap             pixmap,
++                                     gboolean           stereo);
+ 
+ CoglTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex);
+ 
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0003-Fix-windows-walking-up-the-screen-on-restart.patch b/SOURCES/0003-Fix-windows-walking-up-the-screen-on-restart.patch
new file mode 100644
index 0000000..ba6aa84
--- /dev/null
+++ b/SOURCES/0003-Fix-windows-walking-up-the-screen-on-restart.patch
@@ -0,0 +1,59 @@
+From e44f0f15e945a2132912d9763cfa3e9e326e0aea Mon Sep 17 00:00:00 2001
+From: "Owen W. Taylor" <otaylor@fishsoup.net>
+Date: Tue, 8 Jul 2014 21:08:31 -0400
+Subject: [PATCH 3/4] Fix windows walking up the screen on restart
+
+When a window is initially created, we need to save it's user rect
+after any adjustments for gravity. Otherwise, the next time the window is
+queued for a resize, it will jump back to it's initial position.
+
+We did that for newly created windows, but on restart, when windows
+were already placed, the logic skipped saving the position. Use an
+explicit flag so that we always save the position for newly created
+MetaWindows.
+---
+ src/core/constraints.h | 4 +++-
+ src/core/window.c      | 5 +++--
+ 2 files changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/src/core/constraints.h b/src/core/constraints.h
+index 5fa1e4e..1a59724 100644
+--- a/src/core/constraints.h
++++ b/src/core/constraints.h
+@@ -35,7 +35,9 @@ typedef enum
+   META_DO_GRAVITY_ADJUST    = 1 << 1,
+   META_IS_USER_ACTION       = 1 << 2,
+   META_IS_MOVE_ACTION       = 1 << 3,
+-  META_IS_RESIZE_ACTION     = 1 << 4
++  META_IS_RESIZE_ACTION     = 1 << 4,
++  META_FORCE_STATIC_GRAVITY = 1 << 5,
++  META_IS_INITIAL_RESIZE    = 1 << 6
+ } MetaMoveResizeFlags;
+ 
+ void meta_window_constrain (MetaWindow          *window,
+diff --git a/src/core/window.c b/src/core/window.c
+index 60347ef..8d221e3 100644
+--- a/src/core/window.c
++++ b/src/core/window.c
+@@ -1430,7 +1430,7 @@ meta_window_new_with_attrs (MetaDisplay       *display,
+    * initial map is handled same as configure request
+    */
+   flags =
+-    META_IS_CONFIGURE_REQUEST | META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION;
++    META_IS_CONFIGURE_REQUEST | META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION | META_IS_INITIAL_RESIZE;
+   if (!window->override_redirect)
+     meta_window_move_resize_internal (window,
+                                       flags,
+@@ -5316,7 +5316,8 @@ meta_window_move_resize_internal (MetaWindow          *window,
+   if (need_configure_notify)
+     send_configure_notify (window);
+ 
+-  if (!window->placed && window->force_save_user_rect && !window->fullscreen)
++  if (((flags & META_IS_INITIAL_RESIZE) != 0 || !window->placed) &&
++      window->force_save_user_rect && !window->fullscreen)
+     force_save_user_window_placement (window);
+   else if (is_user_action)
+     save_user_window_placement (window);
+-- 
+1.9.3
+
diff --git a/SOURCES/0004-Leave-windows-in-place-on-a-crash-respawn.patch b/SOURCES/0004-Leave-windows-in-place-on-a-crash-respawn.patch
new file mode 100644
index 0000000..def0321
--- /dev/null
+++ b/SOURCES/0004-Leave-windows-in-place-on-a-crash-respawn.patch
@@ -0,0 +1,162 @@
+From 443608282901a16565ef01e70d3fb1f66beb14f5 Mon Sep 17 00:00:00 2001
+From: "Owen W. Taylor" <otaylor@fishsoup.net>
+Date: Tue, 8 Jul 2014 21:35:47 -0400
+Subject: [PATCH 4/4] Leave windows in place on a crash respawn
+
+When Mutter is restarted and cleans up the window positions
+cleanly, we need to add gravity adjustments. We can detect
+this easily.
+
+ - Windows started before the window manager (should add
+   add gravity adjustments)
+ - Replacing a different window manager (should add gravity
+   adjustments)
+ - A crash (no adjustments needed)
+
+In GNOME the first two cases shouldn't happen in normal
+usage, so assume the third case (though that *shouldn't*
+happen in normal usage either.)
+---
+ src/core/display.c        |  4 ++--
+ src/core/screen.c         |  2 +-
+ src/core/window-private.h |  3 ++-
+ src/core/window.c         | 33 ++++++++++++++++++++++++++-------
+ 4 files changed, 31 insertions(+), 11 deletions(-)
+
+diff --git a/src/core/display.c b/src/core/display.c
+index 9ed0f6e..90888c5 100644
+--- a/src/core/display.c
++++ b/src/core/display.c
+@@ -2613,14 +2613,14 @@ event_callback (XEvent   *event,
+               && meta_display_screen_for_root (display, event->xmap.event))
+             {
+               window = meta_window_new (display, event->xmap.window,
+-                                        FALSE);
++                                        FALSE, FALSE);
+             }
+           break;
+         case MapRequest:
+           if (window == NULL)
+             {
+               window = meta_window_new (display, event->xmaprequest.window,
+-                                        FALSE);
++                                        FALSE, FALSE);
+             }
+           /* if frame was receiver it's some malicious send event or something */
+           else if (!frame_was_receiver && window)        
+diff --git a/src/core/screen.c b/src/core/screen.c
+index 6db3ea3..6d8d018 100644
+--- a/src/core/screen.c
++++ b/src/core/screen.c
+@@ -1093,7 +1093,7 @@ meta_screen_manage_all_windows (MetaScreen *screen)
+       WindowInfo *info = list->data;
+ 
+       meta_window_new_with_attrs (screen->display, info->xwindow, TRUE,
+-                                  META_COMP_EFFECT_NONE,
++                                  TRUE,
+                                   &info->attrs);
+     }
+   meta_stack_thaw (screen->stack);
+diff --git a/src/core/window-private.h b/src/core/window-private.h
+index e9f935f..cc77861 100644
+--- a/src/core/window-private.h
++++ b/src/core/window-private.h
+@@ -481,11 +481,12 @@ struct _MetaWindowClass
+ 
+ MetaWindow* meta_window_new                (MetaDisplay *display,
+                                             Window       xwindow,
++                                            gboolean     managing_screen,
+                                             gboolean     must_be_viewable);
+ MetaWindow* meta_window_new_with_attrs     (MetaDisplay       *display,
+                                             Window             xwindow,
++                                            gboolean           managing_screen,
+                                             gboolean           must_be_viewable,
+-                                            MetaCompEffect     effect,
+                                             XWindowAttributes *attrs);
+ void        meta_window_unmanage           (MetaWindow  *window,
+                                             guint32      timestamp);
+diff --git a/src/core/window.c b/src/core/window.c
+index 8d221e3..8a290f3 100644
+--- a/src/core/window.c
++++ b/src/core/window.c
+@@ -40,6 +40,7 @@
+ #include "keybindings-private.h"
+ #include "ui.h"
+ #include "place.h"
++#include <meta/main.h>
+ #include "session.h"
+ #include <meta/prefs.h>
+ #include "resizepopup.h"
+@@ -659,6 +660,7 @@ maybe_leave_show_desktop_mode (MetaWindow *window)
+ MetaWindow*
+ meta_window_new (MetaDisplay *display,
+                  Window       xwindow,
++                 gboolean     managing_screen,
+                  gboolean     must_be_viewable)
+ {
+   XWindowAttributes attrs;
+@@ -682,8 +684,8 @@ meta_window_new (MetaDisplay *display,
+           return NULL;
+        }
+       window = meta_window_new_with_attrs (display, xwindow,
++                                           managing_screen,
+                                            must_be_viewable,
+-                                           META_COMP_EFFECT_CREATE,
+                                            &attrs);
+    }
+   else
+@@ -815,8 +817,8 @@ meta_window_should_attach_to_parent (MetaWindow *window)
+ MetaWindow*
+ meta_window_new_with_attrs (MetaDisplay       *display,
+                             Window             xwindow,
++                            gboolean           managing_screen,
+                             gboolean           must_be_viewable,
+-                            MetaCompEffect     effect,
+                             XWindowAttributes *attrs)
+ {
+   MetaWindow *window;
+@@ -827,6 +829,8 @@ meta_window_new_with_attrs (MetaDisplay       *display,
+   MetaMoveResizeFlags flags;
+   gboolean has_shape;
+   MetaScreen *screen;
++  MetaCompEffect effect =
++    managing_screen ? META_COMP_EFFECT_NONE : META_COMP_EFFECT_CREATE;
+ 
+   g_assert (attrs != NULL);
+ 
+@@ -1425,12 +1429,27 @@ meta_window_new_with_attrs (MetaDisplay       *display,
+   else
+     window->layer = META_LAYER_OVERRIDE_REDIRECT; /* otherwise set by MetaStack */
+ 
+-  /* Put our state back where it should be,
+-   * passing TRUE for is_configure_request, ICCCM says
+-   * initial map is handled same as configure request
+-   */
+   flags =
+-    META_IS_CONFIGURE_REQUEST | META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION | META_IS_INITIAL_RESIZE;
++    META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION | META_IS_INITIAL_RESIZE;
++
++  /* ICCCM says initial map is handled same as configure request. When
++   * we are initially managing the screen, we distinguish two cases:
++   *
++   *  Restart: in this case, we put the windows back to the unframed
++   *   position before exiting, so we need to give them gravity
++   *   adjustments.
++   *  Something else: (perhaps a crash) if we didn't exit cleanly, then
++   *   windows will be reparented by the X server so that the client
++   *   origin stays the same, and no frame adjustment is needed.
++   *
++   * We don't have any way to distinguish replacing a different window
++   * manager from respawning on crash, so when we replace a different
++   * window manager, windows will shift onscreen, but this is expected
++   * to only happen in development.
++   */
++  if (!managing_screen || meta_is_restart())
++    flags |= META_IS_CONFIGURE_REQUEST;
++
+   if (!window->override_redirect)
+     meta_window_move_resize_internal (window,
+                                       flags,
+-- 
+1.9.3
+
diff --git a/SOURCES/preserve-monitor.patch b/SOURCES/preserve-monitor.patch
new file mode 100644
index 0000000..d75accc
--- /dev/null
+++ b/SOURCES/preserve-monitor.patch
@@ -0,0 +1,255 @@
+From abedce08727b9993e0365c9b925bbcab9110feb1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
+Date: Fri, 13 Jun 2014 22:28:26 +0200
+Subject: [PATCH 1/2] window: Keep track of preferred output
+
+Remember the last monitor a window was moved to by user action and
+try to move it back on monitor changes; this should match user
+expectations much better when a monitor is unplugged temporarily.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=731760
+---
+ src/core/window-private.h |  1 +
+ src/core/window.c         | 47 ++++++++++++++++++++++++++++++++++-------------
+ 2 files changed, 35 insertions(+), 13 deletions(-)
+
+diff --git a/src/core/window-private.h b/src/core/window-private.h
+index e9f935f..9a0c760 100644
+--- a/src/core/window-private.h
++++ b/src/core/window-private.h
+@@ -148,6 +148,7 @@ struct _MetaWindow
+    * that to toggle between normal/tiled or maximized/tiled states. */
+   guint saved_maximize : 1;
+   int tile_monitor_number;
++  XID preferred_output;
+ 
+   /* Whether we're shaded */
+   guint shaded : 1;
+diff --git a/src/core/window.c b/src/core/window.c
+index 60347ef..8b8fbe7 100644
+--- a/src/core/window.c
++++ b/src/core/window.c
+@@ -1198,6 +1198,7 @@ meta_window_new_with_attrs (MetaDisplay       *display,
+   window->compositor_private = NULL;
+ 
+   window->monitor = meta_screen_get_monitor_for_window (window->screen, window);
++  window->preferred_output = window->monitor->output;
+ 
+   window->tile_match = NULL;
+ 
+@@ -4779,13 +4780,29 @@ meta_window_get_monitor (MetaWindow *window)
+   return window->monitor->number;
+ }
+ 
++static MetaMonitorInfo *
++find_monitor_by_id (MetaWindow *window,
++                    guint       id)
++{
++  int i;
++
++  for (i = 0; i < window->screen->n_monitor_infos; i++)
++    {
++      MetaMonitorInfo *info = &window->screen->monitor_infos[i];
++
++      if (info->output != 0 && info->output == id)
++        return info;
++    }
++
++  return NULL;
++}
++
+ /* This is called when the monitor setup has changed. The window->monitor
+  * reference is still "valid", but refer to the previous monitor setup */
+ void
+ meta_window_update_for_monitors_changed (MetaWindow *window)
+ {
+   const MetaMonitorInfo *old, *new;
+-  int i;
+ 
+   if (window->type == META_WINDOW_DESKTOP)
+     return;
+@@ -4798,20 +4815,16 @@ meta_window_update_for_monitors_changed (MetaWindow *window)
+ 
+   old = window->monitor;
+ 
+-  /* Start on primary */
+-  new = &window->screen->monitor_infos[window->screen->primary_monitor_index];
++  /* Try the preferred output first */
++  new = find_monitor_by_id (window, window->preferred_output);
+ 
+-  /* But, if we can find the old output on a new monitor, use that */
+-  for (i = 0; i < window->screen->n_monitor_infos; i++)
+-    {
+-      MetaMonitorInfo *info = &window->screen->monitor_infos[i];
++  /* Otherwise, try to find the old output on a new monitor */
++  if (!new)
++    new = find_monitor_by_id (window, old->output);
+ 
+-      if (info->output == old->output)
+-        {
+-          new = info;
+-          break;
+-        }
+-    }
++  /* Fall back to primary if everything else failed */
++  if (!new)
++    new = &window->screen->monitor_infos[window->screen->primary_monitor_index];
+ 
+   if (window->tile_mode != META_TILE_NONE)
+     window->tile_monitor_number = new->number;
+@@ -4934,6 +4947,7 @@ meta_window_move_resize_internal (MetaWindow          *window,
+   int client_move_y;
+   MetaRectangle new_rect;
+   MetaRectangle old_rect;
++  guint old_output_id;
+ 
+   g_return_if_fail (!window->override_redirect);
+ 
+@@ -5332,8 +5346,14 @@ meta_window_move_resize_internal (MetaWindow          *window,
+ 
+   meta_window_refresh_resize_popup (window);
+ 
++  old_output_id = window->monitor->output;
++
+   meta_window_update_monitor (window);
+ 
++  if (old_output_id != window->monitor->output &&
++      flags & META_IS_MOVE_ACTION && flags & META_IS_USER_ACTION)
++    window->preferred_output = window->monitor->output;
++
+   /* Invariants leaving this function are:
+    *   a) window->rect and frame->rect reflect the actual
+    *      server-side size/pos of window->xwindow and frame->xwindow
+@@ -5536,6 +5556,7 @@ meta_window_move_to_monitor (MetaWindow  *window,
+     window->tile_monitor_number = monitor;
+ 
+   meta_window_move_between_rects (window, &old_area, &new_area);
++  window->preferred_output = window->monitor->output;
+ }
+ 
+ void
+-- 
+2.1.0
+
+
+From 6d39e1a72f8914d6a021d801940ab8a6c13d16f7 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
+Date: Fri, 20 Jun 2014 18:06:40 +0200
+Subject: [PATCH 2/2] window: Add user_op parameter to update_monitor()
+
+When workspaces-only-on-primary is set and a window is moved back to the
+primary, we also move it to the active workspace to avoid the confusion
+of a visible window suddenly disappearing when crossing the monitor border.
+However when the window is not actually moved by the user, preserving the
+workspace makes more sense - we already do this in some cases (e.g. when
+moving between primary monitors), but miss others (unplugging the previous
+monitor); just add an explicit user_op parameter as used elsewhere to cover
+all exceptions.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=731760
+---
+ src/core/window-private.h |  1 -
+ src/core/window.c         | 30 ++++++++++++++----------------
+ 2 files changed, 14 insertions(+), 17 deletions(-)
+
+diff --git a/src/core/window-private.h b/src/core/window-private.h
+index 9a0c760..1a39a4b 100644
+--- a/src/core/window-private.h
++++ b/src/core/window-private.h
+@@ -677,5 +677,4 @@ gboolean meta_window_can_tile_side_by_side   (MetaWindow *window);
+ void meta_window_compute_tile_match (MetaWindow *window);
+ 
+ gboolean meta_window_updates_are_frozen (MetaWindow *window);
+-
+ #endif
+diff --git a/src/core/window.c b/src/core/window.c
+index 8b8fbe7..f376ea0 100644
+--- a/src/core/window.c
++++ b/src/core/window.c
+@@ -145,7 +145,8 @@ static void meta_window_move_between_rects (MetaWindow          *window,
+ static void unmaximize_window_before_freeing (MetaWindow        *window);
+ static void unminimize_window_and_all_transient_parents (MetaWindow *window);
+ 
+-static void meta_window_update_monitor (MetaWindow *window);
++static void meta_window_update_monitor (MetaWindow *window,
++                                        gboolean    user_op);
+ 
+ /* Idle handlers for the three queues (run with meta_later_add()). The
+  * "data" parameter in each case will be a GINT_TO_POINTER of the
+@@ -4809,7 +4810,7 @@ meta_window_update_for_monitors_changed (MetaWindow *window)
+ 
+   if (window->override_redirect)
+     {
+-      meta_window_update_monitor (window);
++      meta_window_update_monitor (window, FALSE);
+       return;
+     }
+ 
+@@ -4842,7 +4843,8 @@ meta_window_update_for_monitors_changed (MetaWindow *window)
+ }
+ 
+ static void
+-meta_window_update_monitor (MetaWindow *window)
++meta_window_update_monitor (MetaWindow *window,
++                            gboolean    user_op)
+ {
+   const MetaMonitorInfo *old;
+ 
+@@ -4852,22 +4854,17 @@ meta_window_update_monitor (MetaWindow *window)
+     {
+       meta_window_update_on_all_workspaces (window);
+ 
+-      /* If workspaces only on primary and we moved back to primary, ensure that the
+-       * window is now in that workspace. We do this because while the window is on a
+-       * non-primary monitor it is always visible, so it would be very jarring if it
+-       * disappeared when it crossed the monitor border.
++      /* If workspaces only on primary and we moved back to primary due to a user action,
++       * ensure that the window is now in that workspace. We do this because while
++       * the window is on a non-primary monitor it is always visible, so it would be
++       * very jarring if it disappeared when it crossed the monitor border.
+        * The one time we want it to both change to the primary monitor and a non-active
+        * workspace is when dropping the window on some other workspace thumbnail directly.
+        * That should be handled by explicitly moving the window before changing the
+-       * workspace
+-       * Don't do this if old == NULL, because thats what happens when starting up, and
+-       * we don't want to move all windows around from a previous WM instance. Nor do
+-       * we want it when moving from one primary monitor to another (can happen during
+-       * screen reconfiguration.
++       * workspace.
+        */
+-      if (meta_prefs_get_workspaces_only_on_primary () &&
++      if (meta_prefs_get_workspaces_only_on_primary () && user_op &&
+           meta_window_is_on_primary_monitor (window)  &&
+-          old != NULL && !old->is_primary &&
+           window->screen->active_workspace != window->workspace)
+         meta_window_change_workspace (window, window->screen->active_workspace);
+ 
+@@ -4878,6 +4875,7 @@ meta_window_update_monitor (MetaWindow *window)
+       /* If we're changing monitors, we need to update the has_maximize_func flag,
+        * as the working area has changed. */
+       recalc_window_features (window);
++      meta_window_queue (window, META_QUEUE_CALC_SHOWING);
+     }
+ }
+ 
+@@ -5348,7 +5346,7 @@ meta_window_move_resize_internal (MetaWindow          *window,
+ 
+   old_output_id = window->monitor->output;
+ 
+-  meta_window_update_monitor (window);
++  meta_window_update_monitor (window, flags & META_IS_USER_ACTION);
+ 
+   if (old_output_id != window->monitor->output &&
+       flags & META_IS_MOVE_ACTION && flags & META_IS_USER_ACTION)
+@@ -5672,7 +5670,7 @@ meta_window_configure_notify (MetaWindow      *window,
+   window->rect.y = event->y;
+   window->rect.width = event->width;
+   window->rect.height = event->height;
+-  meta_window_update_monitor (window);
++  meta_window_update_monitor (window, FALSE);
+ 
+   /* Whether an override-redirect window is considered fullscreen depends
+    * on its geometry.
+-- 
+2.1.0
+
diff --git a/SOURCES/vertical-monitor-layouts.patch b/SOURCES/vertical-monitor-layouts.patch
new file mode 100644
index 0000000..ff9595f
--- /dev/null
+++ b/SOURCES/vertical-monitor-layouts.patch
@@ -0,0 +1,244 @@
+From 13603e46a07f4ece309f5b2ab3196ad306b6008c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
+Date: Fri, 6 Jun 2014 07:58:20 +0200
+Subject: [PATCH 1/3] boxes: Ignore struts that don't attach to the side they
+ claim
+
+Like the _NET_WM_STRUT/_NET_WM_STRUT_PARTIAL client properties,
+_NET_WORKAREA is defined in terms of screen geometry rather than
+taking individual monitors into account. However we do want to
+allow system chrome to be attached to a monitor edge rather than
+a screen edges under some circumstances. As not all clients can
+be assumed to deal gracefully with the resulting workarea, use
+those "struts" only internally for constraining windows, but
+ignore them when exporting _NET_WORKAREA.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=730527
+---
+ src/core/boxes.c | 29 ++++++++++++++++++++++++++---
+ 1 file changed, 26 insertions(+), 3 deletions(-)
+
+diff --git a/src/core/boxes.c b/src/core/boxes.c
+index 3c4f444..1057528 100644
+--- a/src/core/boxes.c
++++ b/src/core/boxes.c
+@@ -548,6 +548,26 @@ compare_rect_areas (gconstpointer a, gconstpointer b)
+   return b_area - a_area; /* positive ret value denotes b > a, ... */
+ }
+ 
++/* ... and another helper for get_minimal_spanning_set_for_region()... */
++static gboolean
++check_strut_align (MetaStrut *strut, const MetaRectangle *rect)
++{
++  /* Check whether @strut actually aligns to the side of @rect it claims */
++  switch (strut->side)
++    {
++    case META_SIDE_TOP:
++      return BOX_TOP (strut->rect) <= BOX_TOP (*rect);
++    case META_SIDE_BOTTOM:
++      return BOX_BOTTOM (strut->rect) >= BOX_BOTTOM (*rect);
++    case META_SIDE_LEFT:
++      return BOX_LEFT (strut->rect) <= BOX_LEFT (*rect);
++    case META_SIDE_RIGHT:
++      return BOX_RIGHT (strut->rect) >= BOX_RIGHT (*rect);
++    default:
++      return FALSE;
++    }
++}
++
+ /**
+  * meta_rectangle_get_minimal_spanning_set_for_region:
+  * @basic_rect: Input rectangle
+@@ -631,8 +651,9 @@ meta_rectangle_get_minimal_spanning_set_for_region (
+ 
+   for (strut_iter = all_struts; strut_iter; strut_iter = strut_iter->next)
+     {
+-      GList *rect_iter; 
+-      MetaRectangle *strut_rect = &((MetaStrut*)strut_iter->data)->rect;
++      GList *rect_iter;
++      MetaStrut *strut = (MetaStrut*)strut_iter->data;
++      MetaRectangle *strut_rect = &strut->rect;
+ 
+       tmp_list = ret;
+       ret = NULL;
+@@ -640,7 +661,9 @@ meta_rectangle_get_minimal_spanning_set_for_region (
+       while (rect_iter)
+         {
+           MetaRectangle *rect = (MetaRectangle*) rect_iter->data;
+-          if (!meta_rectangle_overlap (rect, strut_rect))
++
++          if (!meta_rectangle_overlap (strut_rect, rect) ||
++              !check_strut_align (strut, basic_rect))
+             ret = g_list_prepend (ret, rect);
+           else
+             {
+-- 
+2.1.0
+
+
+From 147decb30f1539b18eb8aeb1e37914d9cccac016 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
+Date: Thu, 12 Jun 2014 01:06:25 +0200
+Subject: [PATCH 2/3] testboxes: Update test cases
+
+Who cares? We do now ...
+
+https://bugzilla.gnome.org/show_bug.cgi?id=730527
+---
+ src/core/testboxes.c | 42 ++++++++++++++++++------------------------
+ 1 file changed, 18 insertions(+), 24 deletions(-)
+
+diff --git a/src/core/testboxes.c b/src/core/testboxes.c
+index 128efac..44f70b1 100644
+--- a/src/core/testboxes.c
++++ b/src/core/testboxes.c
+@@ -240,7 +240,7 @@ static GSList*
+ get_strut_list (int which)
+ {
+   GSList *ans;
+-  MetaDirection wc = 0; /* wc == who cares? ;-) */
++  MetaSide wc = 0; /* wc == who cares? ;-) */
+ 
+   ans = NULL;
+ 
+@@ -250,32 +250,32 @@ get_strut_list (int which)
+     case 0:
+       break;
+     case 1:
+-      ans = g_slist_prepend (ans, new_meta_strut (   0,    0, 1600,   20, wc));
+-      ans = g_slist_prepend (ans, new_meta_strut ( 400, 1160, 1600,   40, wc));
++      ans = g_slist_prepend (ans, new_meta_strut (   0,    0, 1600,   20, META_SIDE_TOP));
++      ans = g_slist_prepend (ans, new_meta_strut ( 400, 1160, 1600,   40, META_SIDE_BOTTOM));
+       break;
+     case 2:
+-      ans = g_slist_prepend (ans, new_meta_strut (   0,    0, 1600,   20, wc));
+-      ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100,  400,  100, wc));
+-      ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150,  150,   50, wc));
++      ans = g_slist_prepend (ans, new_meta_strut (   0,    0, 1600,   20, META_SIDE_TOP));
++      ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100,  400,  100, META_SIDE_BOTTOM));
++      ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150,  150,   50, META_SIDE_BOTTOM));
+       break;
+     case 3:
+-      ans = g_slist_prepend (ans, new_meta_strut (   0,    0, 1600,   20, wc));
+-      ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100,  400,  100, wc));
+-      ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150,   80,   50, wc));
++      ans = g_slist_prepend (ans, new_meta_strut (   0,    0, 1600,   20, META_SIDE_TOP));
++      ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100,  400,  100, META_SIDE_LEFT));
++      ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150,   80,   50, META_SIDE_BOTTOM));
+       ans = g_slist_prepend (ans, new_meta_strut ( 700,  525,  200,  150, wc));
+       break;
+     case 4:
+-      ans = g_slist_prepend (ans, new_meta_strut (   0,    0,  800, 1200, wc));
+-      ans = g_slist_prepend (ans, new_meta_strut ( 800,    0, 1600,   20, wc));
++      ans = g_slist_prepend (ans, new_meta_strut (   0,    0,  800, 1200, META_SIDE_LEFT));
++      ans = g_slist_prepend (ans, new_meta_strut ( 800,    0, 1600,   20, META_SIDE_TOP));
+       break;
+     case 5:
+-      ans = g_slist_prepend (ans, new_meta_strut ( 800,    0, 1600,   20, wc));
+-      ans = g_slist_prepend (ans, new_meta_strut (   0,    0,  800, 1200, wc));
+-      ans = g_slist_prepend (ans, new_meta_strut ( 800,   10,  800, 1200, wc));
++      ans = g_slist_prepend (ans, new_meta_strut ( 800,    0, 1600,   20, META_SIDE_TOP));
++      ans = g_slist_prepend (ans, new_meta_strut (   0,    0,  800, 1200, META_SIDE_LEFT));
++      ans = g_slist_prepend (ans, new_meta_strut ( 800,   10,  800, 1200, META_SIDE_RIGHT));
+       break;
+     case 6:
+-      ans = g_slist_prepend (ans, new_meta_strut (   0,    0, 1600,   40, wc));
+-      ans = g_slist_prepend (ans, new_meta_strut (   0,    0, 1600,   20, wc));
++      ans = g_slist_prepend (ans, new_meta_strut (   0,    0, 1600,   40, META_SIDE_TOP));
++      ans = g_slist_prepend (ans, new_meta_strut (   0,    0, 1600,   20, META_SIDE_TOP));
+       break;
+     }
+ 
+@@ -625,15 +625,9 @@ test_regions_okay ()
+   /*************************************************************/  
+   region = get_screen_region (3);
+   tmp = NULL;
+-  tmp = g_list_prepend (tmp, new_meta_rect ( 380,  675,  420,  525)); /* 220500 */
+   tmp = g_list_prepend (tmp, new_meta_rect (   0,   20,  300, 1180)); /* 354000 */
+-  tmp = g_list_prepend (tmp, new_meta_rect ( 380,   20,  320, 1180)); /* 377600 */
+-  tmp = g_list_prepend (tmp, new_meta_rect (   0,  675,  800,  475)); /* 380000 */
+-  tmp = g_list_prepend (tmp, new_meta_rect (1200,   20,  400, 1180)); /* 472000 */
+-  tmp = g_list_prepend (tmp, new_meta_rect (   0,  675, 1600,  425)); /* 680000 */
+-  tmp = g_list_prepend (tmp, new_meta_rect ( 900,   20,  700, 1080)); /* 756000 */
+-  tmp = g_list_prepend (tmp, new_meta_rect (   0,   20,  700, 1130)); /* 791000 */
+-  tmp = g_list_prepend (tmp, new_meta_rect (   0,   20, 1600,  505)); /* 808000 */
++  tmp = g_list_prepend (tmp, new_meta_rect ( 380,   20,  1220, 1180)); /* 377600 */
++  tmp = g_list_prepend (tmp, new_meta_rect (   0,   20,  1600, 1130)); /* 791000 */
+ #if 0
+   printf ("Got to here...\n");
+   char region_list[(RECT_LENGTH+2) * g_list_length (region)];
+-- 
+2.1.0
+
+
+From 0e1668ea9d4fb070480351021af44932ab04bcc2 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
+Date: Wed, 11 Jun 2014 02:16:13 +0200
+Subject: [PATCH 3/3] workspace: Extend builtin struts to screen edge when
+ possible
+
+Struts are defined in terms of screen edges, so expand the rectangles
+we get via set_builtin_struts() accordingly. However we do want to
+allow chrome on edges between monitors, in which case the expansion
+would render an entire monitor unusable - don't expand the rectangles
+in that case, which means we will only use them for constraining
+windows but ignore them for the client-visible _NET_WORKAREA property.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=730527
+---
+ src/core/workspace.c | 39 +++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 39 insertions(+)
+
+diff --git a/src/core/workspace.c b/src/core/workspace.c
+index e5da6d2..9683baf 100644
+--- a/src/core/workspace.c
++++ b/src/core/workspace.c
+@@ -1042,6 +1042,45 @@ void
+ meta_workspace_set_builtin_struts (MetaWorkspace *workspace,
+                                    GSList        *struts)
+ {
++  MetaScreen *screen = workspace->screen;
++  GSList *l;
++
++  for (l = struts; l; l = l->next)
++    {
++      MetaStrut *strut = l->data;
++      int idx = meta_screen_get_monitor_index_for_rect (screen, &strut->rect);
++
++      switch (strut->side)
++        {
++        case META_SIDE_TOP:
++          if (meta_screen_get_monitor_neighbor (screen, idx, META_SCREEN_UP))
++            continue;
++
++          strut->rect.height += strut->rect.y;
++          strut->rect.y = 0;
++          break;
++        case META_SIDE_BOTTOM:
++          if (meta_screen_get_monitor_neighbor (screen, idx, META_SCREEN_DOWN))
++            continue;
++
++          strut->rect.height = screen->rect.height - strut->rect.y;
++          break;
++        case META_SIDE_LEFT:
++          if (meta_screen_get_monitor_neighbor (screen, idx, META_SCREEN_LEFT))
++            continue;
++
++          strut->rect.width += strut->rect.x;
++          strut->rect.x = 0;
++          break;
++        case META_SIDE_RIGHT:
++          if (meta_screen_get_monitor_neighbor (screen, idx, META_SCREEN_RIGHT))
++            continue;
++
++          strut->rect.width = screen->rect.width - strut->rect.x;
++          break;
++        }
++    }
++
+   /* Reordering doesn't actually matter, so we don't catch all
+    * no-impact changes, but this is just a (possibly unnecessary
+    * anyways) optimization */
+-- 
+2.1.0
+
diff --git a/SPECS/mutter.spec b/SPECS/mutter.spec
index 1338c8a..dbd0edb 100644
--- a/SPECS/mutter.spec
+++ b/SPECS/mutter.spec
@@ -1,6 +1,6 @@
 Name:          mutter
 Version:       3.8.4
-Release:       10%{?dist}
+Release:       16%{?dist}
 Summary:       Window and compositing manager based on Clutter
 
 Group:         User Interface/Desktops
@@ -11,6 +11,7 @@ Source0:       http://download.gnome.org/sources/%{name}/3.8/%{name}-%{version}.
 Patch0: 0001-shaped-texture-Use-nearest-pixel-interpolation-if-th.patch
 # https://bugzilla.gnome.org/show_bug.cgi?id=719669
 Patch1: MetaWindowGroup-fix-paint-volume.patch
+Patch2: 0001-window-Fix-delayed-mouse-mode-on-X.patch
 
 Patch10: 0001-background-Allow-using-sliced-textures-for-file-base.patch
 
@@ -23,8 +24,22 @@ Patch40: 0001-background-don-t-save-pixbuf-in-user-data.patch
 Patch41: 0001-workspace-Add-missing-chain-up-for-finalize.patch
 
 Patch50: deal-more-gracefully-with-oversized-windows.patch
+Patch51: vertical-monitor-layouts.patch
+Patch52: preserve-monitor.patch
 
-BuildRequires: clutter-devel >= 1.13.5
+Patch61: 0001-Add-a-framework-for-restarting-the-compositor-with-n.patch
+Patch62: 0002-Add-support-for-quad-buffer-stereo.patch
+Patch63: 0003-Fix-windows-walking-up-the-screen-on-restart.patch
+Patch64: 0004-Leave-windows-in-place-on-a-crash-respawn.patch
+
+# Backport: https://bugzilla.gnome.org/show_bug.cgi?id=734400
+Patch65: 0001-MetaTextureTower-actually-mark-revalidated-levels-as.patch
+
+%define clutter_version 1.14.4-10
+%define cogl_version 1.14.0-6
+
+BuildRequires: clutter-devel >= %{clutter_version}
+BuildRequires: cogl-devel >= %{cogl_version}
 BuildRequires: pango-devel
 BuildRequires: startup-notification-devel
 BuildRequires: gtk3-devel >= 3.3.3
@@ -50,6 +65,8 @@ BuildRequires: gsettings-desktop-schemas-devel
 # an ABI change.
 Conflicts: gnome-shell < 3.7.2
 
+Requires: cogl >= %{cogl_version}
+Requires: clutter >= %{clutter_version}
 Requires: control-center-filesystem
 Requires: startup-notification
 Requires: dbus-x11
@@ -81,12 +98,22 @@ utilities for testing Metacity/Mutter themes.
 %setup -q
 %patch0 -p1 -b .software-rendering-performance
 %patch1 -p1 -b .window-group-paint-volume
+%patch2 -p1 -b .fix-delayed-mouse-mode
 %patch10 -p1 -b .sliced-backgrounds
 %patch20 -p2 -b .translation-updates
 %patch30 -p1 -b .minimal-touch-support
 %patch40 -p1 -b .dont-save-pixbuf-in-userdata
 %patch41 -p1 -b .plug-minor-memory-leak
 %patch50 -p1 -b .deal-with-oversized-windows
+%patch51 -p1 -b .improve-vertical-monitor-layouts
+%patch52 -p1 -b .preserve-monitor
+
+%patch61 -p1 -b .stereo1
+%patch62 -p1 -b .stereo2
+%patch63 -p1 -b .stereo3
+%patch64 -p1 -b .stereo4
+
+%patch65 -p1 -b .texture-tower
 
 %build
 (if ! test -x configure; then NOCONFIGURE=1 ./autogen.sh; fi;
@@ -135,6 +162,7 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || :
 %doc %{_mandir}/man1/mutter-message.1.gz
 %{_bindir}/mutter
 %{_bindir}/mutter-message
+%{_libexecdir}/mutter-restart-helper
 %{_datadir}/applications/*.desktop
 %{_datadir}/gnome/wm-properties/mutter-wm.desktop
 %{_datadir}/mutter
@@ -157,6 +185,27 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || :
 %exclude %{_datadir}/gtk-doc
 
 %changelog
+* Wed Jan 14 2015 Florian Müllner <fmuellner@redhat.com> - 3.8.4.16
+- Fix window placement regression
+  Resolves: rhbz#1153641
+
+* Thu Nov 13 2014 Florian Müllner <fmuellner@redhat.com> - 3.8.4-15
+- Fix delayed mouse mode
+  Resolves: rhbz#1149585
+
+* Thu Oct 09 2014 Florian Müllner <fmueller@redhat.com> - 3.8.4-14
+- Preserve window placement on monitor changes
+  Resolves: rhbz#1126754
+
+* Thu Oct 09 2014 Florian Müllner <fmueller@redhat.com> - 3.8.4-13
+- Improve handling of vertical monitor layouts
+  Resolves: rhbz#1108322
+
+* Thu Jul 17 2014 Owen Taylor <otaylor@redhat.com> 3.8.4-13
+- Add patches for quadbuffer stereo suppport
+  Fix a bad performance problem drawing window thumbnails
+  Resolves: rhbz#861507
+
 * Tue Mar 11 2014 Florian Müllner <fmuellner@redhat.com> - 3.8.4-10
 - Fix crash when encountering over-sized windows
   Resolves: #1027832