diff --git a/SOURCES/0001-monitor-config-manager-Handle-multiple-builtin-panel.patch b/SOURCES/0001-monitor-config-manager-Handle-multiple-builtin-panel.patch
new file mode 100644
index 0000000..73fcb7b
--- /dev/null
+++ b/SOURCES/0001-monitor-config-manager-Handle-multiple-builtin-panel.patch
@@ -0,0 +1,211 @@
+From 19024a5b2eff02b22cdb3fc90142f522dd361996 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
+Date: Fri, 27 Nov 2020 09:03:38 +0100
+Subject: [PATCH] monitor-config-manager: Handle multiple builtin panels
+ gracefully
+
+While multiple built-in panels isn't actually supported in any
+meaningful manner, if we would ever end up with such a situation, e.g.
+due to kernel bugs[0], we shouldn't crash when trying to set an
+'external only' without any external monitors.
+
+While we could handle this with more degraded functionality (e.g. don't
+support the 'switch' method of monitor configuration at all), handle it
+by simply not trying to switch to external-only when there are no,
+according to the kernel, external monitors available. This would e.g.
+still allow betwene 'mirror-all', and 'linear' switches.
+
+The crash itself was disguised as an arbitrary X11 BadValue error, due
+to mutter trying to resize the root window to 0x0, as the monitor
+configuration that was applied consisted of zero logical monitors, thus
+was effectively empty.
+
+[0] https://bugzilla.redhat.com/show_bug.cgi?id=1896904
+
+Related: https://bugzilla.redhat.com/show_bug.cgi?id=1899260
+Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1607>
+---
+ src/backends/meta-monitor-config-manager.c |   3 +
+ src/tests/monitor-unit-tests.c             | 145 +++++++++++++++++++++
+ 2 files changed, 148 insertions(+)
+
+diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c
+index bc1a39db8..d62bad52d 100644
+--- a/src/backends/meta-monitor-config-manager.c
++++ b/src/backends/meta-monitor-config-manager.c
+@@ -1157,6 +1157,9 @@ create_for_switch_config_external (MetaMonitorConfigManager *config_manager)
+       x += logical_monitor_config->layout.width;
+     }
+ 
++  if (!logical_monitor_configs)
++    return NULL;
++
+   return meta_monitors_config_new (monitor_manager,
+                                    logical_monitor_configs,
+                                    layout_mode,
+diff --git a/src/tests/monitor-unit-tests.c b/src/tests/monitor-unit-tests.c
+index f47544b03..725f84173 100644
+--- a/src/tests/monitor-unit-tests.c
++++ b/src/tests/monitor-unit-tests.c
+@@ -3175,6 +3175,149 @@ meta_test_monitor_non_upright_panel (void)
+   check_monitor_configuration (&test_case);
+ }
+ 
++static void
++meta_test_monitor_switch_external_without_external (void)
++{
++  MonitorTestCase test_case = {
++    .setup = {
++      .modes = {
++        {
++          .width = 1024,
++          .height = 768,
++          .refresh_rate = 60.0
++        }
++      },
++      .n_modes = 1,
++      .outputs = {
++        {
++          .crtc = 0,
++          .modes = { 0 },
++          .n_modes = 1,
++          .preferred_mode = 0,
++          .possible_crtcs = { 0 },
++          .n_possible_crtcs = 1,
++          .width_mm = 222,
++          .height_mm = 125,
++          .is_laptop_panel = TRUE
++        },
++        {
++          .crtc = 1,
++          .modes = { 0 },
++          .n_modes = 1,
++          .preferred_mode = 0,
++          .possible_crtcs = { 1 },
++          .n_possible_crtcs = 1,
++          .width_mm = 222,
++          .height_mm = 125,
++          .is_laptop_panel = TRUE
++        }
++      },
++      .n_outputs = 2,
++      .crtcs = {
++        {
++          .current_mode = 0
++        },
++        {
++          .current_mode = 0
++        }
++      },
++      .n_crtcs = 2
++    },
++
++    .expect = {
++      .monitors = {
++        {
++          .outputs = { 0 },
++          .n_outputs = 1,
++          .modes = {
++            {
++              .width = 1024,
++              .height = 768,
++              .refresh_rate = 60.0,
++              .crtc_modes = {
++                {
++                  .output = 0,
++                  .crtc_mode = 0
++                }
++              }
++            }
++          },
++          .n_modes = 1,
++          .current_mode = 0,
++          .width_mm = 222,
++          .height_mm = 125
++        },
++        {
++          .outputs = { 1 },
++          .n_outputs = 1,
++          .modes = {
++            {
++              .width = 1024,
++              .height = 768,
++              .refresh_rate = 60.0,
++              .crtc_modes = {
++                {
++                  .output = 1,
++                  .crtc_mode = 0
++                }
++              }
++            }
++          },
++          .n_modes = 1,
++          .current_mode = 0,
++          .width_mm = 222,
++          .height_mm = 125
++        }
++      },
++      .n_monitors = 2,
++      .logical_monitors = {
++        {
++          .monitors = { 0 },
++          .n_monitors = 1,
++          .layout = { .x = 0, .y = 0, .width = 1024, .height = 768 },
++          .scale = 1
++        },
++        {
++          .monitors = { 1 },
++          .n_monitors = 1,
++          .layout = { .x = 1024, .y = 0, .width = 1024, .height = 768 },
++          .scale = 1
++        }
++      },
++      .n_logical_monitors = 2,
++      .primary_logical_monitor = 0,
++      .n_outputs = 2,
++      .crtcs = {
++        {
++          .current_mode = 0,
++        },
++        {
++          .current_mode = 0,
++        },
++      },
++      .n_crtcs = 2,
++      .n_tiled_monitors = 0,
++      .screen_width = 2048,
++      .screen_height = 768
++    }
++  };
++  MetaMonitorTestSetup *test_setup;
++  MetaBackend *backend = meta_get_backend ();
++  MetaMonitorManager *monitor_manager =
++    meta_backend_get_monitor_manager (backend);
++
++  test_setup = create_monitor_test_setup (&test_case.setup,
++                                          MONITOR_TEST_FLAG_NO_STORED);
++  emulate_hotplug (test_setup);
++  check_monitor_configuration (&test_case);
++
++  meta_monitor_manager_switch_config (monitor_manager,
++                                      META_MONITOR_SWITCH_CONFIG_EXTERNAL);
++  check_monitor_configuration (&test_case);
++
++  check_monitor_test_clients_state ();
++}
++
+ static void
+ meta_test_monitor_custom_vertical_config (void)
+ {
+@@ -5969,6 +6112,8 @@ init_monitor_tests (void)
+                     meta_test_monitor_preferred_non_first_mode);
+   add_monitor_test ("/backends/monitor/non-upright-panel",
+                     meta_test_monitor_non_upright_panel);
++  add_monitor_test ("/backends/monitor/switch-external-without-external",
++                    meta_test_monitor_switch_external_without_external);
+ 
+   add_monitor_test ("/backends/monitor/custom/vertical-config",
+                     meta_test_monitor_custom_vertical_config);
+-- 
+2.29.2
+
diff --git a/SOURCES/0001-xwayland-Don-t-spew-warnings-when-looking-for-X11-di.patch b/SOURCES/0001-xwayland-Don-t-spew-warnings-when-looking-for-X11-di.patch
new file mode 100644
index 0000000..d5e0856
--- /dev/null
+++ b/SOURCES/0001-xwayland-Don-t-spew-warnings-when-looking-for-X11-di.patch
@@ -0,0 +1,304 @@
+From 1128c46af94e3928d5dc7fc77c44023faf01ab64 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
+Date: Wed, 9 Dec 2020 11:23:37 +0100
+Subject: [PATCH 1/2] xwayland: Don't spew warnings when looking for X11
+ displays
+
+It's not important, so only show it when doing MUTTER_DEBUG=wayland.
+Instead report what display numbers were eventually found.
+---
+ src/wayland/meta-xwayland.c | 123 +++++++++++++++++++++++++++---------
+ 1 file changed, 92 insertions(+), 31 deletions(-)
+
+diff --git a/src/wayland/meta-xwayland.c b/src/wayland/meta-xwayland.c
+index 15c85df697..699d5561c7 100644
+--- a/src/wayland/meta-xwayland.c
++++ b/src/wayland/meta-xwayland.c
+@@ -146,9 +146,10 @@ meta_xwayland_is_xwayland_surface (MetaWaylandSurface *surface)
+ }
+ 
+ static gboolean
+-try_display (int    display,
+-             char **filename_out,
+-             int   *fd_out)
++try_display (int      display,
++             char   **filename_out,
++             int     *fd_out,
++             GError **error)
+ {
+   gboolean ret = FALSE;
+   char *filename;
+@@ -164,11 +165,32 @@ try_display (int    display,
+       char pid[11];
+       char *end;
+       pid_t other;
++      int read_bytes;
+ 
+       fd = open (filename, O_CLOEXEC, O_RDONLY);
+-      if (fd < 0 || read (fd, pid, 11) != 11)
++      if (fd < 0)
+         {
+-          g_warning ("can't read lock file %s: %m", filename);
++          g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
++                       "Failed to open lock file %s: %s",
++                       filename, g_strerror (errno));
++          goto out;
++        }
++
++      read_bytes = read (fd, pid, 11);
++      if (read_bytes != 11)
++        {
++          if (read_bytes < 0)
++            {
++              g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
++                           "Failed to read lock file %s: %s",
++                           filename, g_strerror (errno));
++            }
++          else
++            {
++              g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
++                           "Failed to read lock file %s",
++                           filename);
++            }
+           goto out;
+         }
+       close (fd);
+@@ -178,7 +200,8 @@ try_display (int    display,
+       other = strtol (pid, &end, 0);
+       if (end != pid + 10)
+         {
+-          g_warning ("can't parse lock file %s", filename);
++          g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
++                       "Can't parse lock file %s", filename);
+           goto out;
+         }
+ 
+@@ -187,18 +210,23 @@ try_display (int    display,
+           /* Process is dead. Try unlinking the lock file and trying again. */
+           if (unlink (filename) < 0)
+             {
+-              g_warning ("failed to unlink stale lock file %s: %m", filename);
++              g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
++                           "Failed to unlink stale lock file %s: %m", filename);
+               goto out;
+             }
+ 
+           goto again;
+         }
+ 
++      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
++                   "Lock file %s already occupied", filename);
+       goto out;
+     }
+   else if (fd < 0)
+     {
+-      g_warning ("failed to create lock file %s: %m", filename);
++      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
++                   "Failed to create lock file %s: %s",
++                   filename, g_strerror (errno));
+       goto out;
+     }
+ 
+@@ -223,24 +251,34 @@ try_display (int    display,
+ }
+ 
+ static char *
+-create_lock_file (int display, int *display_out)
++create_lock_file (int      display,
++                  int     *display_out,
++                  GError **error)
+ {
++  g_autoptr (GError) local_error = NULL;
+   char *filename;
+   int fd;
+-
+   char pid[12];
+   int size;
+   int number_of_tries = 0;
+ 
+-  while (!try_display (display, &filename, &fd))
++  while (!try_display (display, &filename, &fd, &local_error))
+     {
++      meta_verbose ("Failed to open display %d: %s\n",
++                    display, local_error->message);
++      g_clear_error (&local_error);
++
+       display++;
+       number_of_tries++;
+ 
+       /* If we can't get a display after 50 times, then something's wrong. Just
+        * abort in this case. */
+       if (number_of_tries >= 50)
+-        return NULL;
++        {
++          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
++                       "Tried to bind 50 display numbers, giving up");
++          return NULL;
++        }
+     }
+ 
+   /* Subtle detail: we use the pid of the wayland compositor, not the xserver
+@@ -248,11 +286,22 @@ create_lock_file (int display, int *display_out)
+    * it _would've_ written without either the NUL or the size clamping, hence
+    * the disparity in size. */
+   size = snprintf (pid, 12, "%10d\n", getpid ());
++  errno = 0;
+   if (size != 11 || write (fd, pid, 11) != 11)
+     {
++      if (errno != 0)
++        {
++          g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
++                       "Failed to write pid to lock file: %s",
++                       g_strerror (errno));
++        }
++      else
++        {
++          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
++                       "Failed to write pid to lock file");
++        }
+       unlink (filename);
+       close (fd);
+-      g_warning ("failed to write pid to lock file %s", filename);
+       g_free (filename);
+       return NULL;
+     }
+@@ -264,8 +313,8 @@ create_lock_file (int display, int *display_out)
+ }
+ 
+ static int
+-bind_to_abstract_socket (int       display,
+-                         gboolean *fatal)
++bind_to_abstract_socket (int        display,
++                         GError   **error)
+ {
+   struct sockaddr_un addr;
+   socklen_t size, name_size;
+@@ -274,8 +323,8 @@ bind_to_abstract_socket (int       display,
+   fd = socket (PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
+   if (fd < 0)
+     {
+-      *fatal = TRUE;
+-      g_warning ("Failed to create socket: %m");
++      g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
++                   "Failed to create socket: %s", g_strerror (errno));
+       return -1;
+     }
+ 
+@@ -285,17 +334,18 @@ bind_to_abstract_socket (int       display,
+   size = offsetof (struct sockaddr_un, sun_path) + name_size;
+   if (bind (fd, (struct sockaddr *) &addr, size) < 0)
+     {
+-      *fatal = errno != EADDRINUSE;
+-      g_warning ("failed to bind to @%s: %m", addr.sun_path + 1);
++      g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
++                   "Failed to bind to @%s: %s",
++                   addr.sun_path + 1, g_strerror (errno));
+       close (fd);
+       return -1;
+     }
+ 
+   if (listen (fd, 1) < 0)
+     {
+-      *fatal = errno != EADDRINUSE;
+-      g_warning ("Failed to listen on abstract socket @%s: %m",
+-                 addr.sun_path + 1);
++      g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
++                   "Failed to listen on abstract socket @%s: %s",
++                   addr.sun_path + 1, g_strerror (errno));
+       close (fd);
+       return -1;
+     }
+@@ -304,7 +354,8 @@ bind_to_abstract_socket (int       display,
+ }
+ 
+ static int
+-bind_to_unix_socket (int display)
++bind_to_unix_socket (int      display,
++                     GError **error)
+ {
+   struct sockaddr_un addr;
+   socklen_t size, name_size;
+@@ -321,13 +372,18 @@ bind_to_unix_socket (int display)
+   unlink (addr.sun_path);
+   if (bind (fd, (struct sockaddr *) &addr, size) < 0)
+     {
+-      g_warning ("failed to bind to %s: %m\n", addr.sun_path);
++      g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
++                   "Failed to bind to %s: %s",
++                   addr.sun_path, g_strerror (errno));
+       close (fd);
+       return -1;
+     }
+ 
+   if (listen (fd, 1) < 0)
+     {
++      g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
++                   "Failed to listen on %s: %s",
++                   addr.sun_path, g_strerror (errno));
+       unlink (addr.sun_path);
+       close (fd);
+       return -1;
+@@ -385,7 +441,6 @@ choose_xdisplay (MetaXWaylandManager *manager)
+ {
+   int display = 0;
+   char *lock_file = NULL;
+-  gboolean fatal = FALSE;
+ 
+   if (display_number_override != -1)
+     display = display_number_override;
+@@ -394,33 +449,37 @@ choose_xdisplay (MetaXWaylandManager *manager)
+ 
+   do
+     {
+-      lock_file = create_lock_file (display, &display);
++      g_autoptr (GError) error = NULL;
++
++      lock_file = create_lock_file (display, &display, &error);
+       if (!lock_file)
+         {
+-          g_warning ("Failed to create an X lock file");
++          g_warning ("Failed to create an X lock file: %s", error->message);
+           return FALSE;
+         }
+ 
+-      manager->abstract_fd = bind_to_abstract_socket (display, &fatal);
++      manager->abstract_fd = bind_to_abstract_socket (display, &error);
+       if (manager->abstract_fd < 0)
+         {
+           unlink (lock_file);
+ 
+-          if (!fatal)
++          if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_ADDRESS_IN_USE))
+             {
++              meta_verbose ("Failed to bind abstract socket: %s\n", error->message);
+               display++;
+               continue;
+             }
+           else
+             {
+-              g_warning ("Failed to bind abstract socket");
++              g_warning ("Failed to bind abstract socket: %s", error->message);
+               return FALSE;
+             }
+         }
+ 
+-      manager->unix_fd = bind_to_unix_socket (display);
++      manager->unix_fd = bind_to_unix_socket (display, &error);
+       if (manager->unix_fd < 0)
+         {
++          meta_verbose ("Failed to bind unix socket: %s\n", error->message);
+           unlink (lock_file);
+           close (manager->abstract_fd);
+           display++;
+@@ -435,6 +494,8 @@ choose_xdisplay (MetaXWaylandManager *manager)
+   manager->display_name = g_strdup_printf (":%d", manager->display_index);
+   manager->lock_file = lock_file;
+ 
++  g_message ("Using X11 display %s for Xwayland", manager->display_name);
++
+   return TRUE;
+ }
+ 
+-- 
+2.28.0
+
diff --git a/SOURCES/0002-xwayland-Make-sure-tmp-.X11-unix-exists.patch b/SOURCES/0002-xwayland-Make-sure-tmp-.X11-unix-exists.patch
new file mode 100644
index 0000000..720c4de
--- /dev/null
+++ b/SOURCES/0002-xwayland-Make-sure-tmp-.X11-unix-exists.patch
@@ -0,0 +1,82 @@
+From 04202ca080b49f9e71ccf837854fa03c9e572d54 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
+Date: Wed, 9 Dec 2020 15:18:29 +0100
+Subject: [PATCH 2/2] xwayland: Make sure /tmp/.X11-unix/ exists
+
+When we're running under a polyinstantiated SELinux environment, we'll
+likely start with an isolated and empty /tmp, meannig no /tmp/.X11-unix
+directory to add things to. To make it possible to still function in
+this kind of setup, make sure said directory exists.
+---
+ src/wayland/meta-xwayland.c | 29 +++++++++++++++++++++++++++--
+ 1 file changed, 27 insertions(+), 2 deletions(-)
+
+diff --git a/src/wayland/meta-xwayland.c b/src/wayland/meta-xwayland.c
+index 699d5561c7..f6f1010b12 100644
+--- a/src/wayland/meta-xwayland.c
++++ b/src/wayland/meta-xwayland.c
+@@ -436,9 +436,27 @@ meta_xwayland_override_display_number (int number)
+   display_number_override = number;
+ }
+ 
++static gboolean
++ensure_x11_unix_dir (GError **error)
++{
++  if (mkdir ("/tmp/.X11-unix", 01777) != 0)
++    {
++      if (errno == EEXIST)
++        return TRUE;
++
++      g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
++                   "Failed to create directory \"/tmp/.X11-unix\": %s",
++                   g_strerror (errno));
++      return FALSE;
++    }
++
++  return TRUE;
++}
++
+ static gboolean
+ choose_xdisplay (MetaXWaylandManager *manager)
+ {
++  g_autoptr (GError) error = NULL;
+   int display = 0;
+   char *lock_file = NULL;
+ 
+@@ -447,10 +465,15 @@ choose_xdisplay (MetaXWaylandManager *manager)
+   else if (g_getenv ("RUNNING_UNDER_GDM"))
+     display = 1024;
+ 
+-  do
++  if (!ensure_x11_unix_dir (error))
+     {
+-      g_autoptr (GError) error = NULL;
++      g_warning ("Failed to ensure X11 socket directory: %s",
++                 error->message);
++      return FALSE;
++    }
+ 
++  do
++    {
+       lock_file = create_lock_file (display, &display, &error);
+       if (!lock_file)
+         {
+@@ -466,6 +489,7 @@ choose_xdisplay (MetaXWaylandManager *manager)
+           if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_ADDRESS_IN_USE))
+             {
+               meta_verbose ("Failed to bind abstract socket: %s\n", error->message);
++              g_clear_error (error);
+               display++;
+               continue;
+             }
+@@ -480,6 +504,7 @@ choose_xdisplay (MetaXWaylandManager *manager)
+       if (manager->unix_fd < 0)
+         {
+           meta_verbose ("Failed to bind unix socket: %s\n", error->message);
++          g_clear_error (error);
+           unlink (lock_file);
+           close (manager->abstract_fd);
+           display++;
+-- 
+2.28.0
+
diff --git a/SPECS/mutter.spec b/SPECS/mutter.spec
index bca01b2..b631c48 100644
--- a/SPECS/mutter.spec
+++ b/SPECS/mutter.spec
@@ -8,7 +8,7 @@
 
 Name:          mutter
 Version:       3.32.2
-Release:       51%{?dist}
+Release:       53%{?dist}
 Summary:       Window and compositing manager based on Clutter
 
 License:       GPLv2+
@@ -165,6 +165,13 @@ Patch504: shadow-buffer-tile-damage.patch
 # Add PING_TIMEOUT_DELAY to mutter MetaPreferences (#1886034)
 Patch505: 0001-display-Make-check-alive-timeout-configureable.patch
 
+# Polyinstantiation (#1861769)
+Patch506: 0001-xwayland-Don-t-spew-warnings-when-looking-for-X11-di.patch
+Patch507: 0002-xwayland-Make-sure-tmp-.X11-unix-exists.patch
+
+# Mitigate nouveau misidentifying connectors (#1786496)
+Patch508: 0001-monitor-config-manager-Handle-multiple-builtin-panel.patch
+
 BuildRequires: chrpath
 BuildRequires: pango-devel
 BuildRequires: startup-notification-devel
@@ -306,6 +313,16 @@ desktop-file-validate %{buildroot}/%{_datadir}/applications/%{name}.desktop
 %{_datadir}/mutter-%{mutter_api_version}/tests
 
 %changelog
+* Thu Dec 17 2020 Jonas Ådahl <jadahl@redhat.com> - 3.32.2-53
+- Fix test case backport
+  Related: #1786496
+
+* Thu Dec 17 2020 Jonas Ådahl <jadahl@redhat.com> - 3.32.2-52
+- Support polyinstantiation
+  Resolves: #1861769
+- Mitigate nouveau misidentifying connectors
+  Resolves: #1786496
+
 * Mon Dec 07 2020 Jonas Ådahl <jadahl@redhat.com> - 3.32.2-51
 - Add PING_TIMEOUT_DELAY to mutter MetaPreferences
   Resolves: #1886034