diff --git a/src/meson.build b/src/meson.build
index 2757c4118dbe6789e7fa70265f5d5ce08b67a0b2..62004ba9cf11d9c473b045f06fb09679951e2d30 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -54,6 +54,9 @@ phosh_sources = [
   'panel.c',
   'panel.h',
   'phosh.c',
+  'phosh.h',
+  'phosh-wayland.c',
+  'phosh-wayland.h',
   'settings.c',
   'settings.h',
   'settings/brightness.c',
diff --git a/src/monitor-manager.c b/src/monitor-manager.c
index d15bfaaa2666f600c9422c2975ad2193e61957cc..28843371aa0a89391b00c2fd9d90c63e11bf751e 100644
--- a/src/monitor-manager.c
+++ b/src/monitor-manager.c
@@ -12,6 +12,7 @@
 #include "monitor/monitor.h"
 
 #include "gamma-control-client-protocol.h"
+#include "phosh-wayland.h"
 #include "phosh.h"
 
 #include <gdk/gdkwayland.h>
@@ -238,7 +239,8 @@ phosh_monitor_manager_handle_get_crtc_gamma (
     return TRUE;
   }
 
-  gamma_control_manager = phosh_shell_get_wl_gamma_control_manager ();
+  gamma_control_manager = phosh_wayland_get_gamma_control_manager (
+    phosh_wayland_get_default ());
   if (gamma_control_manager == NULL) {
     g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
                                            G_DBUS_ERROR_NOT_SUPPORTED,
@@ -294,7 +296,8 @@ phosh_monitor_manager_handle_set_crtc_gamma (
     return TRUE;
   }
 
-  gamma_control_manager = phosh_shell_get_wl_gamma_control_manager ();
+  gamma_control_manager = phosh_wayland_get_gamma_control_manager (
+    phosh_wayland_get_default ());
   if (!gamma_control_manager) {
     g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
                                            G_DBUS_ERROR_NOT_SUPPORTED,
diff --git a/src/phosh-wayland.c b/src/phosh-wayland.c
new file mode 100644
index 0000000000000000000000000000000000000000..7b6ffe04d91548882a53fc1c652db249fd4fdac5
--- /dev/null
+++ b/src/phosh-wayland.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2018 Purism SPC
+ * SPDX-License-Identifier: GPL-3.0+
+ * Author: Guido Günther <agx@sigxcpu.org>
+ */
+
+#define G_LOG_DOMAIN "phosh-wayland"
+
+#include "config.h"
+#include "phosh-wayland.h"
+
+#include <gdk/gdkwayland.h>
+
+/**
+ * SECTION:phosh-wayland
+ * @short_description: A wayland registry listener
+ * @Title: PhoshWayland
+ *
+ * The #PhoshWayland singleton is responsible for listening to wayland
+ * registry events registering the objects that show up there to make
+ * them available to Phosh's other classes.
+ */
+
+typedef struct {
+  struct wl_display *display;
+  struct wl_registry *registry;
+  struct phosh_private *phosh_private;
+  struct zwlr_layer_shell_v1 *layer_shell;
+  struct org_kde_kwin_idle *idle_manager;
+  struct zwlr_input_inhibit_manager_v1 *input_inhibit_manager;
+  struct gamma_control_manager *gamma_control_manager;
+  struct wl_seat *wl_seat;
+  struct xdg_wm_base *xdg_wm_base;
+  GPtrArray *wl_outputs;
+} PhoshWaylandPrivate;
+
+
+typedef struct _PhoshWayland {
+  GObject parent;
+} PhoshWayland;
+
+
+G_DEFINE_TYPE_WITH_PRIVATE (PhoshWayland, phosh_wayland, G_TYPE_OBJECT)
+
+
+static void
+registry_handle_global (void *data,
+                        struct wl_registry *registry,
+                        uint32_t name,
+                        const char *interface,
+                        uint32_t version)
+{
+  PhoshWayland *self = data;
+  PhoshWaylandPrivate *priv = phosh_wayland_get_instance_private (self);
+  struct wl_output *output;
+
+  if (!strcmp (interface, "phosh_private")) {
+      priv->phosh_private = wl_registry_bind (
+        registry,
+        name,
+        &phosh_private_interface,
+        1);
+  } else  if (!strcmp (interface, zwlr_layer_shell_v1_interface.name)) {
+      priv->layer_shell = wl_registry_bind (
+        registry,
+        name,
+        &zwlr_layer_shell_v1_interface,
+        1);
+  } else if (!strcmp (interface, "wl_output")) {
+    output = wl_registry_bind (
+      registry,
+      name,
+      &wl_output_interface, 2);
+    g_ptr_array_add (priv->wl_outputs, output);
+  } else if (!strcmp (interface, "org_kde_kwin_idle")) {
+    priv->idle_manager = wl_registry_bind (
+      registry,
+      name,
+      &org_kde_kwin_idle_interface,
+      1);
+  } else if (!strcmp(interface, "wl_seat")) {
+    priv->wl_seat = wl_registry_bind(
+      registry, name, &wl_seat_interface,
+      1);
+  } else if (!strcmp(interface, zwlr_input_inhibit_manager_v1_interface.name)) {
+    priv->input_inhibit_manager = wl_registry_bind(
+      registry,
+      name,
+      &zwlr_input_inhibit_manager_v1_interface,
+      1);
+  } else if (!strcmp(interface, xdg_wm_base_interface.name)) {
+    priv->xdg_wm_base = wl_registry_bind(
+      registry,
+      name,
+      &xdg_wm_base_interface,
+      1);
+  } else if (!strcmp(interface, gamma_control_manager_interface.name)) {
+    priv->gamma_control_manager = wl_registry_bind(
+      registry,
+      name,
+      &gamma_control_manager_interface,
+      1);
+  }
+}
+
+
+static void
+registry_handle_global_remove (void *data,
+                               struct wl_registry *registry,
+                               uint32_t name)
+{
+  // TODO
+}
+
+
+static const struct wl_registry_listener registry_listener = {
+  registry_handle_global,
+  registry_handle_global_remove
+};
+
+
+static void
+phosh_wayland_constructed (GObject *object)
+{
+  PhoshWayland *self = PHOSH_WAYLAND (object);
+  PhoshWaylandPrivate *priv = phosh_wayland_get_instance_private (self);
+  guint num_outputs;
+  GdkDisplay *gdk_display;
+
+  G_OBJECT_CLASS (phosh_wayland_parent_class)->constructed (object);
+
+  gdk_set_allowed_backends ("wayland");
+  gdk_display = gdk_display_get_default ();
+  priv->display = gdk_wayland_display_get_wl_display (gdk_display);
+
+  if (priv->display == NULL) {
+      g_error ("Failed to get display: %m\n");
+  }
+
+  priv->registry = wl_display_get_registry (priv->display);
+  wl_registry_add_listener (priv->registry, &registry_listener, self);
+
+  /* Wait until we have been notified about the wayland globals we require */
+  num_outputs = priv->wl_outputs->len;
+  if (!num_outputs || !priv->layer_shell || !priv->idle_manager ||
+      !priv->input_inhibit_manager || !priv->phosh_private || !priv->xdg_wm_base)
+    wl_display_roundtrip (priv->display);
+  num_outputs = priv->wl_outputs->len;
+  if (!num_outputs || !priv->layer_shell || !priv->idle_manager ||
+      !priv->input_inhibit_manager || !priv->xdg_wm_base) {
+    g_error ("Could not find needed globals\n"
+             "outputs: %d, layer_shell: %p, seat: %p, "
+             "inhibit: %p, xdg_wm: %p\n",
+             num_outputs, priv->layer_shell, priv->idle_manager,
+             priv->input_inhibit_manager, priv->xdg_wm_base);
+  }
+  if (!priv->phosh_private) {
+    g_info ("Could not find phosh private interface, disabling some features\n");
+  }
+}
+
+
+static void
+phosh_wayland_dispose (GObject *object)
+{
+  PhoshWayland *self = PHOSH_WAYLAND (object);
+  PhoshWaylandPrivate *priv = phosh_wayland_get_instance_private (self);
+
+  g_clear_pointer (&priv->wl_outputs, g_ptr_array_unref);
+}
+
+
+static void
+phosh_wayland_class_init (PhoshWaylandClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->constructed = phosh_wayland_constructed;
+  object_class->dispose = phosh_wayland_dispose;
+}
+
+
+static void
+phosh_wayland_init (PhoshWayland *self)
+{
+  PhoshWaylandPrivate *priv = phosh_wayland_get_instance_private (self);
+  priv->wl_outputs = g_ptr_array_new ();
+}
+
+
+PhoshWayland *
+phosh_wayland_get_default ()
+{
+  static PhoshWayland *instance;
+
+  if (instance == NULL) {
+    instance = g_object_new (PHOSH_TYPE_WAYLAND, NULL);
+    g_object_add_weak_pointer (G_OBJECT (instance), (gpointer *)&instance);
+  }
+  return instance;
+}
+
+
+struct zwlr_layer_shell_v1 *
+phosh_wayland_get_zwlr_layer_shell_v1 (PhoshWayland *self)
+{
+  PhoshWaylandPrivate *priv = phosh_wayland_get_instance_private (self);
+  return priv->layer_shell;
+}
+
+
+struct gamma_control_manager*
+phosh_wayland_get_gamma_control_manager (PhoshWayland *self)
+{
+  PhoshWaylandPrivate *priv = phosh_wayland_get_instance_private (self);
+  return priv->gamma_control_manager;
+}
+
+
+struct wl_seat*
+phosh_wayland_get_wl_seat (PhoshWayland *self)
+{
+  PhoshWaylandPrivate *priv = phosh_wayland_get_instance_private (self);
+  return priv->wl_seat;
+}
+
+
+struct xdg_wm_base*
+phosh_wayland_get_xdg_wm_base (PhoshWayland *self)
+{
+  PhoshWaylandPrivate *priv = phosh_wayland_get_instance_private (self);
+  return priv->xdg_wm_base;
+}
+
+
+struct zwlr_input_inhibit_manager_v1*
+phosh_wayland_get_zwlr_input_inhibit_manager_v1 (PhoshWayland *self)
+{
+  PhoshWaylandPrivate *priv = phosh_wayland_get_instance_private (self);
+  return priv->input_inhibit_manager;
+}
+
+
+struct org_kde_kwin_idle*
+phosh_wayland_get_org_kde_kwin_idle (PhoshWayland *self)
+{
+  PhoshWaylandPrivate *priv = phosh_wayland_get_instance_private (self);
+  return priv->idle_manager;
+}
+
+
+struct phosh_private*
+phosh_wayland_get_phosh_private (PhoshWayland *self)
+{
+  PhoshWaylandPrivate *priv = phosh_wayland_get_instance_private (self);
+  return priv->phosh_private;
+}
+
+
+GPtrArray*
+phosh_wayland_get_wl_outputs (PhoshWayland *self)
+{
+  PhoshWaylandPrivate *priv = phosh_wayland_get_instance_private (self);
+  return priv->wl_outputs;
+}
diff --git a/src/phosh-wayland.h b/src/phosh-wayland.h
new file mode 100644
index 0000000000000000000000000000000000000000..4920db439d7b7e2af8750f3fd9026b50bed379c7
--- /dev/null
+++ b/src/phosh-wayland.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 Purism SPC
+ *
+ * SPDX-License-Identifier: GPL-3+
+ * Author: Guido Günther <agx@sigxcpu.org>
+ */
+#pragma once
+
+#include "idle-client-protocol.h"
+#include "phosh-private-client-protocol.h"
+#include "wlr-input-inhibitor-unstable-v1-client-protocol.h"
+#include "wlr-layer-shell-unstable-v1-client-protocol.h"
+#include "xdg-shell-client-protocol.h"
+#include "gamma-control-client-protocol.h"
+
+#include <glib-object.h>
+
+#define PHOSH_TYPE_WAYLAND phosh_wayland_get_type()
+
+G_DECLARE_FINAL_TYPE (PhoshWayland, phosh_wayland, PHOSH, WAYLAND, GObject)
+
+PhoshWayland                         *phosh_wayland_get_default (void);
+GPtrArray                            *phosh_wayland_get_wl_outputs (PhoshWayland *self);
+struct gamma_control_manager         *phosh_wayland_get_gamma_control_manager (PhoshWayland *self);
+struct org_kde_kwin_idle             *phosh_wayland_get_org_kde_kwin_idle (PhoshWayland *self);
+struct phosh_private                 *phosh_wayland_get_phosh_private (PhoshWayland *self);
+struct wl_seat                       *phosh_wayland_get_wl_seat (PhoshWayland *self);
+struct xdg_wm_base                   *phosh_wayland_get_xdg_wm_base (PhoshWayland *self);
+struct zwlr_input_inhibit_manager_v1 *phosh_wayland_get_zwlr_input_inhibit_manager_v1 (PhoshWayland *self);
+struct zwlr_layer_shell_v1           *phosh_wayland_get_zwlr_layer_shell_v1 (PhoshWayland *self);
diff --git a/src/phosh.c b/src/phosh.c
index b37d0d8beae5d5b25fc02da10f4209a9be984c0e..535e33949d03499d1321481eb588c7a5b469b4ff 100644
--- a/src/phosh.c
+++ b/src/phosh.c
@@ -8,7 +8,7 @@
  * Author: Jonny Lamb <jonny.lamb@collabora.co.uk>
  */
 
-#define G_LOG_DOMAIN "phosh-phosh"
+#define G_LOG_DOMAIN "phosh-shell"
 
 #include <stdlib.h>
 #include <string.h>
@@ -20,16 +20,10 @@
 #include <gdk/gdkwayland.h>
 
 #include "config.h"
-
-#include "idle-client-protocol.h"
-#include "phosh-private-client-protocol.h"
-#include "wlr-input-inhibitor-unstable-v1-client-protocol.h"
-#include "wlr-layer-shell-unstable-v1-client-protocol.h"
-#include "xdg-shell-client-protocol.h"
-#include "gamma-control-client-protocol.h"
 #include "phosh.h"
 
-#include "monitor/monitor.h"  /* FIXME: move upwards? */
+#include "phosh-wayland.h"
+#include "monitor/monitor.h"
 #include "background.h"
 #include "lockscreen.h"
 #include "lockshield.h"
@@ -63,18 +57,6 @@ struct popup {
 
 typedef struct
 {
-  struct wl_display *display;
-  struct wl_registry *registry;
-  struct phosh_private *mshell;
-  struct zwlr_layer_shell_v1 *layer_shell;
-  struct org_kde_kwin_idle *idle_manager;
-  struct zwlr_input_inhibit_manager_v1 *input_inhibit_manager;
-  struct zwlr_input_inhibitor_v1 *input_inhibitor;
-  struct gamma_control_manager *gamma_control_manager;
-  struct wl_seat *wl_seat;
-  struct xdg_wm_base *xdg_wm_base;
-
-  GdkDisplay *gdk_display;
   gint rotation;
 
   /* Top panel */
@@ -88,6 +70,7 @@ typedef struct
   GPtrArray *shields;        /* other outputs */
   gulong unlock_handler_id;
   struct org_kde_kwin_idle_timeout *lock_timer;
+  struct zwlr_input_inhibitor_v1 *input_inhibitor;
   gboolean locked;
 
   /* Favorites menu */
@@ -112,18 +95,6 @@ G_DEFINE_TYPE_WITH_PRIVATE (PhoshShell, phosh_shell, G_TYPE_OBJECT)
 static PhoshShell *_phosh;
 
 
-static struct wl_seat*
-get_seat (PhoshShell *self)
-{
-  PhoshShellPrivate *priv;
-
-  g_return_val_if_fail (PHOSH_IS_SHELL (self), NULL);
-  priv = phosh_shell_get_instance_private (self);
-
-  return priv->wl_seat;
-}
-
-
 static struct popup**
 get_popup_from_xdg_popup (PhoshShell *self, struct xdg_popup *xdg_popup)
 {
@@ -285,6 +256,8 @@ favorites_activated_cb (PhoshShell *self,
   struct xdg_surface *xdg_surface;
   struct xdg_positioner *xdg_positioner;
   gint width, height;
+  PhoshWayland *wl = phosh_wayland_get_default();
+  struct xdg_wm_base* xdg_wm_base = phosh_wayland_get_xdg_wm_base (wl);
 
   close_menu (&priv->settings);
   if (priv->favorites) {
@@ -299,9 +272,9 @@ favorites_activated_cb (PhoshShell *self,
   gdk_wayland_window_set_use_custom_surface (gdk_window);
   favorites->wl_surface = gdk_wayland_window_get_wl_surface (gdk_window);
 
-  xdg_surface = xdg_wm_base_get_xdg_surface(priv->xdg_wm_base, favorites->wl_surface);
+  xdg_surface = xdg_wm_base_get_xdg_surface(xdg_wm_base, favorites->wl_surface);
   g_return_if_fail (xdg_surface);
-  xdg_positioner = xdg_wm_base_create_positioner(priv->xdg_wm_base);
+  xdg_positioner = xdg_wm_base_create_positioner(xdg_wm_base);
   gtk_window_get_size (GTK_WINDOW (favorites->window), &width, &height);
   xdg_positioner_set_size(xdg_positioner, width, height);
   xdg_positioner_set_offset(xdg_positioner, 0, PHOSH_PANEL_HEIGHT-1);
@@ -314,7 +287,7 @@ favorites_activated_cb (PhoshShell *self,
   priv->favorites = favorites;
 
   /* TODO: how to get meaningful serial from gdk? */
-  xdg_popup_grab(favorites->popup, get_seat(self), 1);
+  xdg_popup_grab(favorites->popup, phosh_wayland_get_wl_seat (wl), 1);
   zwlr_layer_surface_v1_get_popup(priv->panel->layer_surface, favorites->popup);
   xdg_surface_add_listener(xdg_surface, &xdg_surface_listener, NULL);
   xdg_popup_add_listener(favorites->popup, &xdg_popup_listener, self);
@@ -354,6 +327,8 @@ settings_activated_cb (PhoshShell *self,
   struct xdg_surface *xdg_surface;
   struct xdg_positioner *xdg_positioner;
   gint width, height, panel_width;
+  PhoshWayland *wl = phosh_wayland_get_default ();
+  gpointer xdg_wm_base = phosh_wayland_get_xdg_wm_base(wl);
 
   close_menu (&priv->favorites);
   if (priv->settings) {
@@ -368,9 +343,9 @@ settings_activated_cb (PhoshShell *self,
   gdk_wayland_window_set_use_custom_surface (gdk_window);
   settings->wl_surface = gdk_wayland_window_get_wl_surface (gdk_window);
 
-  xdg_surface = xdg_wm_base_get_xdg_surface(priv->xdg_wm_base, settings->wl_surface);
+  xdg_surface = xdg_wm_base_get_xdg_surface(xdg_wm_base, settings->wl_surface);
   g_return_if_fail (xdg_surface);
-  xdg_positioner = xdg_wm_base_create_positioner(priv->xdg_wm_base);
+  xdg_positioner = xdg_wm_base_create_positioner(xdg_wm_base);
   gtk_window_get_size (GTK_WINDOW (settings->window), &width, &height);
   xdg_positioner_set_size(xdg_positioner, width, height);
   phosh_shell_get_usable_area (self, NULL, NULL, &panel_width, NULL);
@@ -384,7 +359,7 @@ settings_activated_cb (PhoshShell *self,
   priv->settings = settings;
 
   /* TODO: how to get meaningful serial from GDK? */
-  xdg_popup_grab(settings->popup, get_seat(self), 1);
+  xdg_popup_grab(settings->popup, phosh_wayland_get_wl_seat (wl), 1);
   zwlr_layer_surface_v1_get_popup(priv->panel->layer_surface, settings->popup);
   xdg_surface_add_listener(xdg_surface, &xdg_surface_listener, NULL);
   xdg_popup_add_listener(settings->popup, &xdg_popup_listener, self);
@@ -406,6 +381,7 @@ lockscreen_create (PhoshShell *self)
   GdkWindow *gdk_window;
   struct elem *lockscreen;
   PhoshMonitor *monitor;
+  PhoshWayland *wl = phosh_wayland_get_default ();
 
   monitor = phosh_shell_get_primary_monitor ();
   g_return_if_fail (monitor);
@@ -414,17 +390,19 @@ lockscreen_create (PhoshShell *self)
   lockscreen->window = phosh_lockscreen_new ();
 
   priv->input_inhibitor =
-    zwlr_input_inhibit_manager_v1_get_inhibitor(priv->input_inhibit_manager);
+    zwlr_input_inhibit_manager_v1_get_inhibitor(
+      phosh_wayland_get_zwlr_input_inhibit_manager_v1 (wl));
 
   gdk_window = gtk_widget_get_window (lockscreen->window);
   gdk_wayland_window_set_use_custom_surface (gdk_window);
 
   lockscreen->wl_surface = gdk_wayland_window_get_wl_surface (gdk_window);
-  lockscreen->layer_surface = zwlr_layer_shell_v1_get_layer_surface(priv->layer_shell,
-                                                                    lockscreen->wl_surface,
-                                                                    monitor->wl_output,
-                                                                    ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY,
-                                                                    "lockscreen");
+  lockscreen->layer_surface = zwlr_layer_shell_v1_get_layer_surface(
+    phosh_wayland_get_zwlr_layer_shell_v1(wl),
+    lockscreen->wl_surface,
+    monitor->wl_output,
+    ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY,
+    "lockscreen");
   zwlr_layer_surface_v1_set_exclusive_zone(lockscreen->layer_surface, -1);
   zwlr_layer_surface_v1_set_size(lockscreen->layer_surface, 0, 0);
   zwlr_layer_surface_v1_set_anchor(lockscreen->layer_surface,
@@ -443,7 +421,9 @@ lockscreen_create (PhoshShell *self)
     monitor = phosh_monitor_manager_get_monitor(priv->monitor_manager, i);
     if (monitor == NULL)
       continue;
-    g_ptr_array_add (priv->shields, phosh_lockshield_new (priv->layer_shell, monitor->wl_output));
+    g_ptr_array_add (priv->shields, phosh_lockshield_new (
+                       phosh_wayland_get_zwlr_layer_shell_v1 (wl),
+                       monitor->wl_output));
   }
 
   priv->unlock_handler_id = g_signal_connect_swapped (
@@ -512,17 +492,16 @@ static void
 lockscreen_prepare (PhoshShell *self)
 {
   PhoshShellPrivate *priv = phosh_shell_get_instance_private (self);
+  PhoshWayland *wl = phosh_wayland_get_default ();
 
-  g_return_if_fail(priv->idle_manager);
-  g_return_if_fail(priv->gdk_display);
+  struct org_kde_kwin_idle *idle_manager = phosh_wayland_get_org_kde_kwin_idle (wl);
 
-  priv->lock_timer = org_kde_kwin_idle_get_idle_timeout(
-    priv->idle_manager,
-    get_seat(self),
-    LOCKSCREEN_TIMEOUT);
 
+  g_return_if_fail(idle_manager);
+  priv->lock_timer = org_kde_kwin_idle_get_idle_timeout(idle_manager,
+                                                        phosh_wayland_get_wl_seat (wl),
+                                                        LOCKSCREEN_TIMEOUT);
   g_return_if_fail (priv->lock_timer);
-
   org_kde_kwin_idle_timeout_add_listener(priv->lock_timer,
                                          &idle_timer_listener,
                                          self);
@@ -553,6 +532,7 @@ panel_create (PhoshShell *self)
   GdkWindow *gdk_window;
   gint width;
   PhoshMonitor *monitor;
+  PhoshWayland *wl = phosh_wayland_get_default ();
 
   monitor = get_primary_monitor (self);
   g_return_if_fail (monitor);
@@ -565,11 +545,12 @@ panel_create (PhoshShell *self)
   gdk_window = gtk_widget_get_window (panel->window);
   gdk_wayland_window_set_use_custom_surface (gdk_window);
   panel->wl_surface = gdk_wayland_window_get_wl_surface (gdk_window);
-  panel->layer_surface = zwlr_layer_shell_v1_get_layer_surface(priv->layer_shell,
-                                                               panel->wl_surface,
-                                                               monitor->wl_output,
-                                                               ZWLR_LAYER_SHELL_V1_LAYER_TOP,
-                                                               "phosh");
+  panel->layer_surface = zwlr_layer_shell_v1_get_layer_surface(
+    phosh_wayland_get_zwlr_layer_shell_v1 (wl),
+    panel->wl_surface,
+    monitor->wl_output,
+    ZWLR_LAYER_SHELL_V1_LAYER_TOP,
+    "phosh");
   zwlr_layer_surface_v1_set_anchor(panel->layer_surface,
                                    ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
                                    ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
@@ -643,84 +624,6 @@ env_setup ()
 }
 
 
-static void
-registry_handle_global (void *data,
-                        struct wl_registry *registry,
-                        uint32_t name,
-                        const char *interface,
-                        uint32_t version)
-{
-  PhoshShell *self = data;
-  PhoshShellPrivate *priv = phosh_shell_get_instance_private (self);
-  struct wl_output *output;
-
-  if (!strcmp (interface, "phosh_private")) {
-      priv->mshell = wl_registry_bind (
-        registry,
-        name,
-        &phosh_private_interface,
-        1);
-  } else  if (!strcmp (interface, zwlr_layer_shell_v1_interface.name)) {
-      priv->layer_shell = wl_registry_bind (
-        registry,
-        name,
-        &zwlr_layer_shell_v1_interface,
-        1);
-  } else if (!strcmp (interface, "wl_output")) {
-    output = wl_registry_bind (
-      registry,
-      name,
-      &wl_output_interface, 2);
-    phosh_monitor_manager_add_monitor (
-      priv->monitor_manager,
-      phosh_monitor_new_from_wl_output(output));
-  } else if (!strcmp (interface, "org_kde_kwin_idle")) {
-    priv->idle_manager = wl_registry_bind (
-      registry,
-      name,
-      &org_kde_kwin_idle_interface,
-      1);
-  } else if (!strcmp(interface, "wl_seat")) {
-    priv->wl_seat = wl_registry_bind(
-      registry, name, &wl_seat_interface,
-      1);
-  } else if (!strcmp(interface, zwlr_input_inhibit_manager_v1_interface.name)) {
-    priv->input_inhibit_manager = wl_registry_bind(
-      registry,
-      name,
-      &zwlr_input_inhibit_manager_v1_interface,
-      1);
-  } else if (!strcmp(interface, xdg_wm_base_interface.name)) {
-    priv->xdg_wm_base = wl_registry_bind(
-      registry,
-      name,
-      &xdg_wm_base_interface,
-      1);
-  } else if (!strcmp(interface, gamma_control_manager_interface.name)) {
-    priv->gamma_control_manager = wl_registry_bind(
-      registry,
-      name,
-      &gamma_control_manager_interface,
-      1);
-  }
-}
-
-
-static void
-registry_handle_global_remove (void *data,
-    struct wl_registry *registry,
-    uint32_t name)
-{
-  // TODO
-}
-
-
-static const struct wl_registry_listener registry_listener = {
-  registry_handle_global,
-  registry_handle_global_remove
-};
-
-
 static void
 phosh_shell_set_property (GObject *object,
                           guint property_id,
@@ -791,50 +694,18 @@ phosh_shell_constructed (GObject *object)
 {
   PhoshShell *self = PHOSH_SHELL (object);
   PhoshShellPrivate *priv = phosh_shell_get_instance_private (self);
-  guint num_mon;
+  PhoshWayland *wl = phosh_wayland_get_default();
+  GPtrArray *outputs;
 
   G_OBJECT_CLASS (phosh_shell_parent_class)->constructed (object);
 
-  gdk_set_allowed_backends ("wayland");
-  priv->gdk_display = gdk_display_get_default ();
-  priv->display =
-    gdk_wayland_display_get_wl_display (priv->gdk_display);
-
-  if (priv->display == NULL) {
-      g_error ("Failed to get display: %m\n");
-  }
-
   priv->monitor_manager = phosh_monitor_manager_new ();
-  priv->registry = wl_display_get_registry (priv->display);
-  wl_registry_add_listener (priv->registry, &registry_listener, self);
-
-  /* Wait until we have been notified about the compositor,
-   * shell, and shell helper objects */
-  num_mon = phosh_monitor_manager_get_num_monitors (priv->monitor_manager);
-  if (!num_mon ||
-      !priv->layer_shell ||
-      !priv->idle_manager ||
-      !priv->input_inhibit_manager ||
-      !priv->mshell ||
-      !priv->xdg_wm_base ||
-      !priv->gamma_control_manager)
-    wl_display_roundtrip (priv->display);
-  num_mon = phosh_monitor_manager_get_num_monitors (priv->monitor_manager);
-  if (!num_mon ||
-      !priv->layer_shell ||
-      !priv->idle_manager ||
-      !priv->input_inhibit_manager ||
-      !priv->xdg_wm_base ||
-      !priv->gamma_control_manager) {
-    g_error ("Could not find needed globals\n"
-             "outputs: %d, layer_shell: %p, seat: %p, "
-             "inhibit: %p, xdg_wm: %p, gamma %p\n",
-             num_mon, priv->layer_shell, priv->idle_manager,
-             priv->input_inhibit_manager, priv->xdg_wm_base,
-             priv->gamma_control_manager);
-  }
-  if (!priv->mshell) {
-    g_info ("Could not find phosh global, disabling some features\n");
+  /* Add all initial outputs */
+  outputs = phosh_wayland_get_wl_outputs (wl);
+  for (int i = 0; i < outputs->len; i++) {
+     phosh_monitor_manager_add_monitor (
+       priv->monitor_manager,
+       phosh_monitor_new_from_wl_output(outputs->pdata[i]));
   }
 
   gtk_icon_theme_add_resource_path (gtk_icon_theme_get_default (),
@@ -896,33 +767,17 @@ phosh_shell_rotate_display (PhoshShell *self,
                             guint degree)
 {
   PhoshShellPrivate *priv = phosh_shell_get_instance_private (self);
+  PhoshWayland *wl = phosh_wayland_get_default();
 
-  g_return_if_fail (priv->mshell);
-
+  g_return_if_fail (phosh_wayland_get_phosh_private (wl));
   priv->rotation = degree;
-  phosh_private_rotate_display (priv->mshell,
+  phosh_private_rotate_display (phosh_wayland_get_phosh_private (wl),
                                 priv->panel->wl_surface,
                                 degree);
   g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_SHELL_PROP_ROTATION]);
 }
 
 
-gpointer
-phosh_shell_get_wl_layer_shell ()
-{
-  PhoshShellPrivate *priv = phosh_shell_get_instance_private (_phosh);
-  return priv->layer_shell;
-}
-
-
-gpointer
-phosh_shell_get_wl_gamma_control_manager ()
-{
-  PhoshShellPrivate *priv = phosh_shell_get_instance_private (_phosh);
-  return priv->gamma_control_manager;
-}
-
-
 PhoshMonitor *
 phosh_shell_get_primary_monitor ()
 {
@@ -982,6 +837,7 @@ int main(int argc, char *argv[])
   g_autoptr(GOptionContext) opt_context;
   GError *err = NULL;
   gboolean unlocked = FALSE;
+  g_autoptr(PhoshWayland) wl;
 
   const GOptionEntry options [] = {
     {"unlocked", 'U', 0, G_OPTION_ARG_NONE, &unlocked,
@@ -1004,6 +860,7 @@ int main(int argc, char *argv[])
   g_source_set_callback (sigterm, sigterm_cb, NULL, NULL);
   g_source_attach (sigterm, context);
 
+  wl = phosh_wayland_get_default ();
   _phosh = g_object_new (PHOSH_TYPE_SHELL, NULL);
   if (!unlocked)
     phosh_shell_lock (_phosh);
diff --git a/src/phosh.h b/src/phosh.h
index e17adb368b4bf4cad2dba9e995553a6073faaff8..3144146102d9405c84f3abd4fb28578782a969fb 100644
--- a/src/phosh.h
+++ b/src/phosh.h
@@ -16,7 +16,7 @@
 
 G_DECLARE_FINAL_TYPE (PhoshShell, phosh_shell, PHOSH, SHELL, GObject)
 
-PhoshShell         * phosh                       (void);
+PhoshShell          *phosh                       (void);
 void                 phosh_shell_rotate_display  (PhoshShell *self, guint degrees);
 int                  phosh_shell_get_rotation    (PhoshShell *self);
 void                 phosh_shell_get_usable_area (PhoshShell *self,
@@ -28,8 +28,4 @@ void                 phosh_shell_set_locked      (PhoshShell *self, gboolean loc
 void                 phosh_shell_lock            (PhoshShell *self);
 void                 phosh_shell_unlock          (PhoshShell *self);
 PhoshMonitor        *phosh_shell_get_primary_monitor ();
-
-/* Phosh keeps track of the wayland globals */
-gpointer             phosh_shell_get_wl_layer_shell  ();
-gpointer             phosh_shell_get_wl_gamma_control_manager ();
 #endif /* PHOSH_H */