[mutter] compositor: Move out X11 compositing code into sub type



commit 984aad4b8624a65bcb2dba7aa794d5d31de0b267
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Wed Aug 14 23:25:54 2019 +0200

    compositor: Move out X11 compositing code into sub type
    
    Introduce MetaCompositorX11, dealing with being a X11 compositor, and
    MetaCompositorServer, being a compositor while also being the display
    server itself, e.g. a Wayland display server.
    
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/727

 src/backends/meta-dnd-private.h           |   9 +-
 src/backends/x11/cm/meta-backend-x11-cm.c |  23 +-
 src/backends/x11/meta-backend-x11.c       |  26 +-
 src/compositor/compositor-private.h       |  11 +-
 src/compositor/compositor.c               | 411 ++++++-----------------------
 src/compositor/meta-compositor-server.c   |  54 ++++
 src/compositor/meta-compositor-server.h   |  30 +++
 src/compositor/meta-compositor-x11.c      | 412 ++++++++++++++++++++++++++++++
 src/compositor/meta-compositor-x11.h      |  36 +++
 src/compositor/meta-dnd.c                 |  11 +-
 src/meson.build                           |   4 +
 src/meta/compositor.h                     |   6 -
 src/x11/events.c                          |  17 +-
 13 files changed, 673 insertions(+), 377 deletions(-)
---
diff --git a/src/backends/meta-dnd-private.h b/src/backends/meta-dnd-private.h
index 6f39d43ad..0cfb3d788 100644
--- a/src/backends/meta-dnd-private.h
+++ b/src/backends/meta-dnd-private.h
@@ -24,11 +24,12 @@
 #include <X11/Xlib.h>
 
 #include "backends/meta-backend-private.h"
+#include "compositor/meta-compositor-x11.h"
 
-gboolean meta_dnd_handle_xdnd_event (MetaBackend    *backend,
-                                     MetaCompositor *compositor,
-                                     Display        *xdisplay,
-                                     XEvent         *xev);
+gboolean meta_dnd_handle_xdnd_event (MetaBackend       *backend,
+                                     MetaCompositorX11 *compositor_x11,
+                                     Display           *xdisplay,
+                                     XEvent            *xev);
 
 void meta_dnd_init_xdnd (MetaX11Display *x11_display);
 
diff --git a/src/backends/x11/cm/meta-backend-x11-cm.c b/src/backends/x11/cm/meta-backend-x11-cm.c
index 38840b37c..bb1ba4b06 100644
--- a/src/backends/x11/cm/meta-backend-x11-cm.c
+++ b/src/backends/x11/cm/meta-backend-x11-cm.c
@@ -27,11 +27,14 @@
 #include <xkbcommon/xkbcommon-x11.h>
 
 #include "backends/meta-backend-private.h"
+#include "backends/meta-dnd-private.h"
 #include "backends/x11/meta-cursor-renderer-x11.h"
 #include "backends/x11/meta-gpu-xrandr.h"
 #include "backends/x11/meta-input-settings-x11.h"
 #include "backends/x11/meta-monitor-manager-xrandr.h"
 #include "backends/x11/cm/meta-renderer-x11-cm.h"
+#include "compositor/meta-compositor-x11.h"
+#include "core/display-private.h"
 
 struct _MetaBackendX11Cm
 {
@@ -328,6 +331,20 @@ meta_backend_x11_cm_handle_host_xevent (MetaBackendX11 *backend_x11,
   MetaMonitorManagerXrandr *monitor_manager_xrandr =
     META_MONITOR_MANAGER_XRANDR (monitor_manager);
   Display *xdisplay = meta_backend_x11_get_xdisplay (x11);
+  gboolean bypass_clutter = FALSE;
+  MetaDisplay *display;
+
+  display = meta_get_display ();
+  if (display)
+    {
+      MetaCompositor *compositor = display->compositor;
+      MetaCompositorX11 *compositor_x11 = META_COMPOSITOR_X11 (compositor);
+      Display *xdisplay = meta_backend_x11_get_xdisplay (x11);
+
+      if (meta_dnd_handle_xdnd_event (backend, compositor_x11,
+                                      xdisplay, event))
+        bypass_clutter = TRUE;
+    }
 
   if (event->type == meta_backend_x11_get_xkb_event_base (x11))
     {
@@ -351,8 +368,10 @@ meta_backend_x11_cm_handle_host_xevent (MetaBackendX11 *backend_x11,
         }
     }
 
-  return meta_monitor_manager_xrandr_handle_xevent (monitor_manager_xrandr,
-                                                    event);
+  bypass_clutter |=
+    meta_monitor_manager_xrandr_handle_xevent (monitor_manager_xrandr, event);
+
+  return bypass_clutter;
 }
 
 static void
diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c
index dcdbadef3..75fb1341f 100644
--- a/src/backends/x11/meta-backend-x11.c
+++ b/src/backends/x11/meta-backend-x11.c
@@ -42,7 +42,6 @@
 #include <string.h>
 #include <xkbcommon/xkbcommon-x11.h>
 
-#include "backends/meta-dnd-private.h"
 #include "backends/meta-idle-monitor-private.h"
 #include "backends/meta-stage-private.h"
 #include "backends/x11/meta-clutter-backend-x11.h"
@@ -326,25 +325,20 @@ handle_host_xevent (MetaBackend *backend,
   MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
   MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
   gboolean bypass_clutter = FALSE;
+  MetaDisplay *display;
 
   XGetEventData (priv->xdisplay, &event->xcookie);
 
-  {
-    MetaDisplay *display = meta_get_display ();
-
-    if (display)
-      {
-        MetaCompositor *compositor = display->compositor;
-        MetaPluginManager *plugin_mgr =
-          meta_compositor_get_plugin_manager (compositor);
-
-        if (meta_plugin_manager_xevent_filter (plugin_mgr, event))
-          bypass_clutter = TRUE;
+  display = meta_get_display ();
+  if (display)
+    {
+      MetaCompositor *compositor = display->compositor;
+      MetaPluginManager *plugin_mgr =
+        meta_compositor_get_plugin_manager (compositor);
 
-        if (meta_dnd_handle_xdnd_event (backend, compositor, priv->xdisplay, event))
-          bypass_clutter = TRUE;
-      }
-  }
+      if (meta_plugin_manager_xevent_filter (plugin_mgr, event))
+        bypass_clutter = TRUE;
+    }
 
   bypass_clutter = (meta_backend_x11_handle_host_xevent (x11, event) ||
                     bypass_clutter);
diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h
index 6968469ba..8935732ba 100644
--- a/src/compositor/compositor-private.h
+++ b/src/compositor/compositor-private.h
@@ -17,6 +17,13 @@
 struct _MetaCompositorClass
 {
   GObjectClass parent_class;
+
+  void (* manage) (MetaCompositor *compositor);
+  void (* unmanage) (MetaCompositor *compositor);
+  void (* pre_paint) (MetaCompositor *compositor);
+  void (* post_paint) (MetaCompositor *compositor);
+  void (* remove_window) (MetaCompositor *compositor,
+                          MetaWindow     *window);
 };
 
 void meta_compositor_remove_window_actor (MetaCompositor  *compositor,
@@ -50,9 +57,11 @@ void meta_compositor_locate_pointer (MetaCompositor *compositor);
 
 void meta_compositor_redirect_x11_windows (MetaCompositor *compositor);
 
+gboolean meta_compositor_is_unredirect_inhibited (MetaCompositor *compositor);
+
 MetaDisplay * meta_compositor_get_display (MetaCompositor *compositor);
 
-Window meta_compositor_get_output_xwindow (MetaCompositor *compositor);
+MetaWindowActor * meta_compositor_get_top_window_actor (MetaCompositor *compositor);
 
 ClutterStage * meta_compositor_get_stage (MetaCompositor *compositor);
 
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
index c787a00f4..c8b3e303d 100644
--- a/src/compositor/compositor.c
+++ b/src/compositor/compositor.c
@@ -54,14 +54,11 @@
 
 #include "compositor/compositor-private.h"
 
-#include <X11/extensions/shape.h>
 #include <X11/extensions/Xcomposite.h>
 
 #include "backends/meta-dnd-private.h"
-#include "backends/x11/meta-backend-x11.h"
 #include "clutter/clutter-mutter.h"
-#include "clutter/x11/clutter-x11.h"
-#include "compositor/meta-sync-ring.h"
+#include "compositor/meta-compositor-x11.h"
 #include "compositor/meta-window-actor-x11.h"
 #include "compositor/meta-window-actor-wayland.h"
 #include "compositor/meta-window-actor-private.h"
@@ -83,6 +80,7 @@
 #include "x11/meta-x11-display-private.h"
 
 #ifdef HAVE_WAYLAND
+#include "compositor/meta-compositor-server.h"
 #include "wayland/meta-wayland-private.h"
 #endif
 
@@ -110,26 +108,21 @@ typedef struct _MetaCompositorPrivate
   ClutterActor *feedback_group;
 
   GList *windows;
-  Window output;
 
   CoglContext *context;
 
   MetaWindowActor *top_window_actor;
   gulong top_window_actor_destroy_id;
 
-  /* Used for unredirecting fullscreen windows */
   int disable_unredirect_count;
-  MetaWindow *unredirected_window;
 
   int switch_workspace_in_progress;
 
   MetaPluginManager *plugin_mgr;
-
-  gboolean frame_has_updated_xsurfaces;
-  gboolean have_x11_sync_object;
 } MetaCompositorPrivate;
 
-G_DEFINE_TYPE_WITH_PRIVATE (MetaCompositor, meta_compositor, G_TYPE_OBJECT)
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaCompositor, meta_compositor,
+                                     G_TYPE_OBJECT)
 
 static void
 on_presented (ClutterStage     *stage,
@@ -189,20 +182,6 @@ meta_compositor_destroy (MetaCompositor *compositor)
   g_object_unref (compositor);
 }
 
-static void
-process_damage (MetaCompositor     *compositor,
-                XDamageNotifyEvent *event,
-                MetaWindow         *window)
-{
-  MetaCompositorPrivate *priv =
-    meta_compositor_get_instance_private (compositor);
-  MetaWindowActor *window_actor = meta_window_actor_from_window (window);
-
-  meta_window_actor_process_x11_damage (window_actor, event);
-
-  priv->frame_has_updated_xsurfaces = TRUE;
-}
-
 /* compat helper */
 static MetaCompositor *
 get_compositor_for_display (MetaDisplay *display)
@@ -290,50 +269,6 @@ meta_get_window_actors (MetaDisplay *display)
   return priv->windows;
 }
 
-void
-meta_set_stage_input_region (MetaDisplay  *display,
-                             XserverRegion region)
-{
-  /* As a wayland compositor we can simply ignore all this trickery
-   * for setting an input region on the stage for capturing events in
-   * clutter since all input comes to us first and we get to choose
-   * who else sees them.
-   */
-  if (!meta_is_wayland_compositor ())
-    {
-      MetaCompositor *compositor = display->compositor;
-      MetaCompositorPrivate *priv =
-        meta_compositor_get_instance_private (compositor);
-      Display *xdpy = meta_x11_display_get_xdisplay (display->x11_display);
-      Window xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (priv->stage));
-
-      XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region);
-
-      /* It's generally a good heuristic that when a crossing event is generated because
-       * we reshape the overlay, we don't want it to affect focus-follows-mouse focus -
-       * it's not the user doing something, it's the environment changing under the user.
-       */
-      meta_display_add_ignored_crossing_serial (display, XNextRequest (xdpy));
-      XFixesSetWindowShapeRegion (xdpy, priv->output, ShapeInput, 0, 0, region);
-    }
-}
-
-void
-meta_empty_stage_input_region (MetaDisplay *display)
-{
-  /* Using a static region here is a bit hacky, but Metacity never opens more than
-   * one XDisplay, so it works fine. */
-  static XserverRegion region = None;
-
-  if (region == None)
-    {
-      Display *xdpy = meta_x11_display_get_xdisplay (display->x11_display);
-      region = XFixesCreateRegion (xdpy, NULL, 0);
-    }
-
-  meta_set_stage_input_region (display, region);
-}
-
 void
 meta_focus_stage_window (MetaDisplay *display,
                          guint32      timestamp)
@@ -584,14 +519,10 @@ meta_compositor_manage (MetaCompositor *compositor)
   MetaCompositorPrivate *priv =
     meta_compositor_get_instance_private (compositor);
   MetaDisplay *display = priv->display;
-  Display *xdisplay = NULL;
   MetaBackend *backend = meta_get_backend ();
 
   if (display->x11_display)
-    {
-      xdisplay = display->x11_display->xdisplay;
-      meta_x11_display_set_cm_selection (display->x11_display);
-    }
+    meta_x11_display_set_cm_selection (display->x11_display);
 
   priv->stage = meta_backend_get_stage (backend);
 
@@ -622,42 +553,7 @@ meta_compositor_manage (MetaCompositor *compositor)
   clutter_actor_add_child (priv->stage, priv->top_window_group);
   clutter_actor_add_child (priv->stage, priv->feedback_group);
 
-  if (meta_is_wayland_compositor ())
-    {
-      /* NB: When running as a wayland compositor we don't need an X
-       * composite overlay window, and we don't need to play any input
-       * region tricks to redirect events into clutter. */
-      priv->output = None;
-    }
-  else
-    {
-      Window xwin;
-
-      priv->output = display->x11_display->composite_overlay_window;
-
-      xwin = meta_backend_x11_get_xwindow (META_BACKEND_X11 (backend));
-
-      XReparentWindow (xdisplay, xwin, priv->output, 0, 0);
-
-      meta_empty_stage_input_region (display);
-
-      /* Make sure there isn't any left-over output shape on the
-       * overlay window by setting the whole screen to be an
-       * output region.
-       *
-       * Note: there doesn't seem to be any real chance of that
-       *  because the X server will destroy the overlay window
-       *  when the last client using it exits.
-       */
-      XFixesSetWindowShapeRegion (xdisplay, priv->output, ShapeBounding, 0, 0, None);
-
-      /* Map overlay window before redirecting windows offscreen so we catch their
-       * contents until we show the stage.
-       */
-      XMapWindow (xdisplay, priv->output);
-
-      priv->have_x11_sync_object = meta_sync_ring_init (xdisplay);
-    }
+  META_COMPOSITOR_GET_CLASS (compositor)->manage (compositor);
 
   meta_compositor_redirect_x11_windows (compositor);
 
@@ -667,103 +563,7 @@ meta_compositor_manage (MetaCompositor *compositor)
 void
 meta_compositor_unmanage (MetaCompositor *compositor)
 {
-  if (!meta_is_wayland_compositor ())
-    {
-      MetaCompositorPrivate *priv =
-        meta_compositor_get_instance_private (compositor);
-      MetaX11Display *display = priv->display->x11_display;
-      Display *xdisplay = display->xdisplay;
-      Window xroot = display->xroot;
-
-      /* This is the most important part of cleanup - we have to do this
-       * before giving up the window manager selection or the next
-       * window manager won't be able to redirect subwindows */
-      XCompositeUnredirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
-    }
-}
-
-/**
- * meta_shape_cow_for_window:
- * @compositor: A #MetaCompositor
- * @window: (nullable): A #MetaWindow to shape the COW for
- *
- * Sets an bounding shape on the COW so that the given window
- * is exposed. If @window is %NULL it clears the shape again.
- *
- * Used so we can unredirect windows, by shaping away the part
- * of the COW, letting the raw window be seen through below.
- */
-static void
-meta_shape_cow_for_window (MetaCompositor *compositor,
-                           MetaWindow *window)
-{
-  MetaCompositorPrivate *priv =
-    meta_compositor_get_instance_private (compositor);
-  MetaDisplay *display = priv->display;
-  Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display);
-
-  if (window == NULL)
-    {
-      XFixesSetWindowShapeRegion (xdisplay, priv->output,
-                                  ShapeBounding, 0, 0, None);
-    }
-  else
-    {
-      XserverRegion output_region;
-      XRectangle screen_rect, window_bounds;
-      int width, height;
-      MetaRectangle rect;
-
-      meta_window_get_frame_rect (window, &rect);
-
-      window_bounds.x = rect.x;
-      window_bounds.y = rect.y;
-      window_bounds.width = rect.width;
-      window_bounds.height = rect.height;
-
-      meta_display_get_size (display, &width, &height);
-      screen_rect.x = 0;
-      screen_rect.y = 0;
-      screen_rect.width = width;
-      screen_rect.height = height;
-
-      output_region = XFixesCreateRegion (xdisplay, &window_bounds, 1);
-
-      XFixesInvertRegion (xdisplay, output_region, &screen_rect, output_region);
-      XFixesSetWindowShapeRegion (xdisplay, priv->output,
-                                  ShapeBounding, 0, 0, output_region);
-      XFixesDestroyRegion (xdisplay, output_region);
-    }
-}
-
-static void
-set_unredirected_window (MetaCompositor *compositor,
-                         MetaWindow     *window)
-{
-  MetaCompositorPrivate *priv =
-    meta_compositor_get_instance_private (compositor);
-
-  if (priv->unredirected_window == window)
-    return;
-
-  if (priv->unredirected_window != NULL)
-    {
-      MetaWindowActor *window_actor;
-
-      window_actor = meta_window_actor_from_window (priv->unredirected_window);
-      meta_window_actor_set_unredirected (window_actor, FALSE);
-    }
-
-  meta_shape_cow_for_window (compositor, window);
-  priv->unredirected_window = window;
-
-  if (priv->unredirected_window != NULL)
-    {
-      MetaWindowActor *window_actor;
-
-      window_actor = meta_window_actor_from_window (priv->unredirected_window);
-      meta_window_actor_set_unredirected (window_actor, TRUE);
-    }
+  META_COMPOSITOR_GET_CLASS (compositor)->unmanage (compositor);
 }
 
 void
@@ -805,20 +605,22 @@ meta_compositor_add_window (MetaCompositor    *compositor,
   sync_actor_stacking (compositor);
 }
 
-void
-meta_compositor_remove_window (MetaCompositor *compositor,
-                               MetaWindow     *window)
+static void
+meta_compositor_real_remove_window (MetaCompositor *compositor,
+                                    MetaWindow     *window)
 {
-  MetaCompositorPrivate *priv =
-    meta_compositor_get_instance_private (compositor);
   MetaWindowActor *window_actor = meta_window_actor_from_window (window);
 
-  if (priv->unredirected_window == window)
-    set_unredirected_window (compositor, NULL);
-
   meta_window_actor_queue_destroy (window_actor);
 }
 
+void
+meta_compositor_remove_window (MetaCompositor *compositor,
+                               MetaWindow     *window)
+{
+  META_COMPOSITOR_GET_CLASS (compositor)->remove_window (compositor, window);
+}
+
 void
 meta_compositor_remove_window_actor (MetaCompositor  *compositor,
                                      MetaWindowActor *window_actor)
@@ -874,53 +676,6 @@ meta_compositor_window_opacity_changed (MetaCompositor *compositor,
   meta_window_actor_update_opacity (window_actor);
 }
 
-/**
- * meta_compositor_process_event: (skip)
- * @compositor:
- * @event:
- * @window:
- *
- */
-gboolean
-meta_compositor_process_event (MetaCompositor *compositor,
-                               XEvent         *event,
-                               MetaWindow     *window)
-{
-  MetaCompositorPrivate *priv =
-    meta_compositor_get_instance_private (compositor);
-  MetaX11Display *x11_display = priv->display->x11_display;
-
-  if (!meta_is_wayland_compositor () &&
-      event->type == meta_x11_display_get_damage_event_base (x11_display) + XDamageNotify)
-    {
-      /* Core code doesn't handle damage events, so we need to extract the MetaWindow
-       * ourselves
-       */
-      if (window == NULL)
-        {
-          Window xwin = ((XDamageNotifyEvent *) event)->drawable;
-          window = meta_x11_display_lookup_x_window (x11_display, xwin);
-        }
-
-      if (window)
-        process_damage (compositor, (XDamageNotifyEvent *) event, window);
-    }
-
-  if (priv->have_x11_sync_object)
-    meta_sync_ring_handle_event (event);
-
-  /* Clutter needs to know about MapNotify events otherwise it will
-     think the stage is invisible */
-  if (!meta_is_wayland_compositor () && event->type == MapNotify)
-    clutter_x11_handle_event (event);
-
-  /* The above handling is basically just "observing" the events, so we return
-   * FALSE to indicate that the event should not be filtered out; if we have
-   * GTK+ windows in the same process, GTK+ needs the ConfigureNotify event, for example.
-   */
-  return FALSE;
-}
-
 gboolean
 meta_compositor_filter_keybinding (MetaCompositor *compositor,
                                    MetaKeyBinding *binding)
@@ -1299,85 +1054,40 @@ on_presented (ClutterStage     *stage,
     }
 }
 
-static gboolean
-meta_pre_paint_func (gpointer data)
+static void
+meta_compositor_real_pre_paint (MetaCompositor *compositor)
 {
-  MetaCompositor *compositor = data;
   MetaCompositorPrivate *priv =
     meta_compositor_get_instance_private (compositor);
   GList *l;
-  MetaWindowActor *top_window_actor;
-
-  if (priv->windows == NULL)
-    return TRUE;
-
-  top_window_actor = priv->top_window_actor;
-  if (top_window_actor &&
-      meta_window_actor_should_unredirect (top_window_actor) &&
-      priv->disable_unredirect_count == 0)
-    {
-      MetaWindow *top_window;
-
-      top_window = meta_window_actor_get_meta_window (top_window_actor);
-      set_unredirected_window (compositor, top_window);
-    }
-  else
-    {
-      set_unredirected_window (compositor, NULL);
-    }
 
   for (l = priv->windows; l; l = l->next)
     meta_window_actor_pre_paint (l->data);
+}
 
-  if (priv->frame_has_updated_xsurfaces)
-    {
-      /* We need to make sure that any X drawing that happens before
-       * the XDamageSubtract() for each window above is visible to
-       * subsequent GL rendering; the standardized way to do this is
-       * GL_EXT_X11_sync_object. Since this isn't implemented yet in
-       * mesa, we also have a path that relies on the implementation
-       * of the open source drivers.
-       *
-       * Anything else, we just hope for the best.
-       *
-       * Xorg and open source driver specifics:
-       *
-       * The X server makes sure to flush drawing to the kernel before
-       * sending out damage events, but since we use
-       * DamageReportBoundingBox there may be drawing between the last
-       * damage event and the XDamageSubtract() that needs to be
-       * flushed as well.
-       *
-       * Xorg always makes sure that drawing is flushed to the kernel
-       * before writing events or responses to the client, so any
-       * round trip request at this point is sufficient to flush the
-       * GLX buffers.
-       */
-      if (priv->have_x11_sync_object)
-        priv->have_x11_sync_object = meta_sync_ring_insert_wait ();
-      else
-        XSync (priv->display->x11_display->xdisplay, False);
-    }
-
-  return TRUE;
+static void
+meta_compositor_pre_paint (MetaCompositor *compositor)
+{
+  META_COMPOSITOR_GET_CLASS (compositor)->pre_paint (compositor);
 }
 
 static gboolean
-meta_post_paint_func (gpointer data)
+meta_pre_paint_func (gpointer data)
 {
   MetaCompositor *compositor = data;
+
+  meta_compositor_pre_paint (compositor);
+
+  return TRUE;
+}
+
+static void
+meta_compositor_real_post_paint (MetaCompositor *compositor)
+{
   MetaCompositorPrivate *priv =
     meta_compositor_get_instance_private (compositor);
   CoglGraphicsResetStatus status;
 
-  if (priv->frame_has_updated_xsurfaces)
-    {
-      if (priv->have_x11_sync_object)
-        priv->have_x11_sync_object = meta_sync_ring_after_frame ();
-
-      priv->frame_has_updated_xsurfaces = FALSE;
-    }
-
   status = cogl_get_graphics_reset_status (priv->context);
   switch (status)
     {
@@ -1400,6 +1110,20 @@ meta_post_paint_func (gpointer data)
       meta_restart (NULL);
       break;
     }
+}
+
+static void
+meta_compositor_post_paint (MetaCompositor *compositor)
+{
+  META_COMPOSITOR_GET_CLASS (compositor)->post_paint (compositor);
+}
+
+static gboolean
+meta_post_paint_func (gpointer data)
+{
+  MetaCompositor *compositor = data;
+
+  meta_compositor_post_paint (compositor);
 
   return TRUE;
 }
@@ -1427,7 +1151,13 @@ meta_compositor_new (MetaDisplay *display)
   MetaCompositor *compositor;
   MetaCompositorPrivate *priv;
 
-  compositor = g_object_new (META_TYPE_COMPOSITOR, NULL);
+#ifdef HAVE_WAYLAND
+  if (meta_is_wayland_compositor ())
+    compositor = g_object_new (META_TYPE_COMPOSITOR_SERVER, NULL);
+  else
+#endif
+    compositor = g_object_new (META_TYPE_COMPOSITOR_X11, NULL);
+
   priv = meta_compositor_get_instance_private (compositor);
   priv->display = display;
 
@@ -1484,12 +1214,6 @@ meta_compositor_dispose (GObject *object)
   g_clear_pointer (&priv->feedback_group, clutter_actor_destroy);
   g_clear_pointer (&priv->windows, g_list_free);
 
-  if (priv->have_x11_sync_object)
-    {
-      meta_sync_ring_destroy ();
-      priv->have_x11_sync_object = FALSE;
-    }
-
   G_OBJECT_CLASS (meta_compositor_parent_class)->dispose (object);
 }
 
@@ -1499,6 +1223,10 @@ meta_compositor_class_init (MetaCompositorClass *klass)
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
   object_class->dispose = meta_compositor_dispose;
+
+  klass->remove_window = meta_compositor_real_remove_window;
+  klass->pre_paint = meta_compositor_real_pre_paint;
+  klass->post_paint = meta_compositor_real_post_paint;
 }
 
 /**
@@ -1539,6 +1267,15 @@ meta_enable_unredirect_for_display (MetaDisplay *display)
     priv->disable_unredirect_count--;
 }
 
+gboolean
+meta_compositor_is_unredirect_inhibited (MetaCompositor *compositor)
+{
+  MetaCompositorPrivate *priv =
+    meta_compositor_get_instance_private (compositor);
+
+  return priv->disable_unredirect_count > 0;
+}
+
 #define FLASH_TIME_MS 50
 
 static void
@@ -1771,22 +1508,22 @@ meta_compositor_get_display (MetaCompositor *compositor)
   return priv->display;
 }
 
-Window
-meta_compositor_get_output_xwindow (MetaCompositor *compositor)
+ClutterStage *
+meta_compositor_get_stage (MetaCompositor *compositor)
 {
   MetaCompositorPrivate *priv =
     meta_compositor_get_instance_private (compositor);
 
-  return priv->output;
+  return CLUTTER_STAGE (priv->stage);
 }
 
-ClutterStage *
-meta_compositor_get_stage (MetaCompositor *compositor)
+MetaWindowActor *
+meta_compositor_get_top_window_actor (MetaCompositor *compositor)
 {
   MetaCompositorPrivate *priv =
     meta_compositor_get_instance_private (compositor);
 
-  return CLUTTER_STAGE (priv->stage);
+  return priv->top_window_actor;
 }
 
 gboolean
diff --git a/src/compositor/meta-compositor-server.c b/src/compositor/meta-compositor-server.c
new file mode 100644
index 000000000..206586c06
--- /dev/null
+++ b/src/compositor/meta-compositor-server.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2019 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.
+ *
+ */
+
+#include "config.h"
+
+#include "compositor/meta-compositor-server.h"
+
+struct _MetaCompositorServer
+{
+  MetaCompositor parent;
+};
+
+G_DEFINE_TYPE (MetaCompositorServer, meta_compositor_server, META_TYPE_COMPOSITOR)
+
+static void
+meta_compositor_server_manage (MetaCompositor *compositor)
+{
+}
+
+static void
+meta_compositor_server_unmanage (MetaCompositor *compositor)
+{
+}
+
+static void
+meta_compositor_server_init (MetaCompositorServer *compositor_server)
+{
+}
+
+static void
+meta_compositor_server_class_init (MetaCompositorServerClass *klass)
+{
+  MetaCompositorClass *compositor_class = META_COMPOSITOR_CLASS (klass);
+
+  compositor_class->manage = meta_compositor_server_manage;
+  compositor_class->unmanage = meta_compositor_server_unmanage;
+}
diff --git a/src/compositor/meta-compositor-server.h b/src/compositor/meta-compositor-server.h
new file mode 100644
index 000000000..b16971ae3
--- /dev/null
+++ b/src/compositor/meta-compositor-server.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 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_COMPOSITOR_SERVER_H
+#define META_COMPOSITOR_SERVER_H
+
+#include "compositor/compositor-private.h"
+
+#define META_TYPE_COMPOSITOR_SERVER (meta_compositor_server_get_type ())
+G_DECLARE_FINAL_TYPE (MetaCompositorServer, meta_compositor_server,
+                      META, COMPOSITOR_SERVER, MetaCompositor)
+
+#endif /* META_COMPOSITOR_SERVER_H */
diff --git a/src/compositor/meta-compositor-x11.c b/src/compositor/meta-compositor-x11.c
new file mode 100644
index 000000000..de10628d1
--- /dev/null
+++ b/src/compositor/meta-compositor-x11.c
@@ -0,0 +1,412 @@
+/*
+ * Copyright (C) 2019 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.
+ *
+ */
+
+#include "config.h"
+
+#include "compositor/meta-compositor-x11.h"
+
+#include <X11/extensions/shape.h>
+#include <X11/extensions/Xcomposite.h>
+
+#include "backends/x11/meta-backend-x11.h"
+#include "clutter/x11/clutter-x11.h"
+#include "compositor/meta-sync-ring.h"
+#include "core/display-private.h"
+#include "x11/meta-x11-display-private.h"
+
+struct _MetaCompositorX11
+{
+  MetaCompositor parent;
+
+  Window output;
+
+  gboolean frame_has_updated_xsurfaces;
+  gboolean have_x11_sync_object;
+
+  MetaWindow *unredirected_window;
+};
+
+G_DEFINE_TYPE (MetaCompositorX11, meta_compositor_x11, META_TYPE_COMPOSITOR)
+
+static void
+process_damage (MetaCompositorX11  *compositor_x11,
+                XDamageNotifyEvent *damage_xevent,
+                MetaWindow         *window)
+{
+  MetaWindowActor *window_actor = meta_window_actor_from_window (window);
+
+  meta_window_actor_process_x11_damage (window_actor, damage_xevent);
+
+  compositor_x11->frame_has_updated_xsurfaces = TRUE;
+}
+
+void
+meta_compositor_x11_process_xevent (MetaCompositorX11 *compositor_x11,
+                                    XEvent            *xevent,
+                                    MetaWindow        *window)
+{
+  MetaCompositor *compositor = META_COMPOSITOR (compositor_x11);
+  MetaDisplay *display = meta_compositor_get_display (compositor);
+  MetaX11Display *x11_display = display->x11_display;
+  int damage_event_base;
+
+  damage_event_base = meta_x11_display_get_damage_event_base (x11_display);
+  if (xevent->type == damage_event_base + XDamageNotify)
+    {
+      /*
+       * Core code doesn't handle damage events, so we need to extract the
+       * MetaWindow ourselves.
+       */
+      if (!window)
+        {
+          Window xwindow;
+
+          xwindow = ((XDamageNotifyEvent *) xevent)->drawable;
+          window = meta_x11_display_lookup_x_window (x11_display, xwindow);
+        }
+
+      if (window)
+        process_damage (compositor_x11, (XDamageNotifyEvent *) xevent, window);
+    }
+
+  if (compositor_x11->have_x11_sync_object)
+    meta_sync_ring_handle_event (xevent);
+
+  /*
+   * Clutter needs to know about MapNotify events otherwise it will think the
+   * stage is invisible
+   */
+  if (xevent->type == MapNotify)
+    clutter_x11_handle_event (xevent);
+}
+
+void
+meta_set_stage_input_region (MetaDisplay  *display,
+                             XserverRegion region)
+{
+  MetaCompositor *compositor = display->compositor;
+  MetaCompositorX11 *compositor_x11 = META_COMPOSITOR_X11 (display->compositor);
+  Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display);
+  ClutterStage *stage = meta_compositor_get_stage (compositor);
+  Window xstage;
+
+  /*
+   * As a wayland compositor we can simply ignore all this trickery
+   * for setting an input region on the stage for capturing events in
+   * clutter since all input comes to us first and we get to choose
+   * who else sees them.
+   */
+  if (meta_is_wayland_compositor ())
+    return;
+
+  xstage = clutter_x11_get_stage_window (stage);
+  XFixesSetWindowShapeRegion (xdisplay, xstage, ShapeInput, 0, 0, region);
+
+  /*
+   * It's generally a good heuristic that when a crossing event is generated
+   * because we reshape the overlay, we don't want it to affect
+   * focus-follows-mouse focus - it's not the user doing something, it's the
+   * environment changing under the user.
+   */
+  meta_display_add_ignored_crossing_serial (display, XNextRequest (xdisplay));
+  XFixesSetWindowShapeRegion (xdisplay, compositor_x11->output,
+                              ShapeInput, 0, 0, region);
+}
+
+void
+meta_empty_stage_input_region (MetaDisplay *display)
+{
+  /*
+   * Using a static region here is a bit hacky, but when running as X11
+   * compositing manager we only ever open a single XDisplay.
+   */
+  static XserverRegion region = None;
+
+  if (meta_is_wayland_compositor ())
+    return;
+
+  if (region == None)
+    {
+      Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display);
+
+      region = XFixesCreateRegion (xdisplay, NULL, 0);
+    }
+
+  meta_set_stage_input_region (display, region);
+}
+
+static void
+meta_compositor_x11_manage (MetaCompositor *compositor)
+{
+  MetaCompositorX11 *compositor_x11 = META_COMPOSITOR_X11 (compositor);
+  MetaDisplay *display = meta_compositor_get_display (compositor);
+  Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display);
+  MetaBackend *backend = meta_get_backend ();
+  Window xwindow;
+
+  compositor_x11->output = display->x11_display->composite_overlay_window;
+
+  xwindow = meta_backend_x11_get_xwindow (META_BACKEND_X11 (backend));
+
+  XReparentWindow (xdisplay, xwindow, compositor_x11->output, 0, 0);
+
+  meta_empty_stage_input_region (display);
+
+  /*
+   * Make sure there isn't any left-over output shape on the overlay window by
+   * setting the whole screen to be an output region.
+   *
+   * Note: there doesn't seem to be any real chance of that because the X
+   * server will destroy the overlay window when the last client using it
+   * exits.
+   */
+  XFixesSetWindowShapeRegion (xdisplay, compositor_x11->output,
+                              ShapeBounding, 0, 0, None);
+
+  /*
+   * Map overlay window before redirecting windows offscreen so we catch their
+   * contents until we show the stage.
+   */
+  XMapWindow (xdisplay, compositor_x11->output);
+
+  compositor_x11->have_x11_sync_object = meta_sync_ring_init (xdisplay);
+}
+
+static void
+meta_compositor_x11_unmanage (MetaCompositor *compositor)
+{
+  MetaDisplay *display = meta_compositor_get_display (compositor);
+  MetaX11Display *x11_display = display->x11_display;
+  Display *xdisplay = x11_display->xdisplay;
+  Window xroot = x11_display->xroot;
+
+  /*
+   * This is the most important part of cleanup - we have to do this before
+   * giving up the window manager selection or the next window manager won't be
+   * able to redirect subwindows
+   */
+  XCompositeUnredirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
+}
+
+/*
+ * Sets an bounding shape on the COW so that the given window
+ * is exposed. If window is %NULL it clears the shape again.
+ *
+ * Used so we can unredirect windows, by shaping away the part
+ * of the COW, letting the raw window be seen through below.
+ */
+static void
+shape_cow_for_window (MetaCompositorX11 *compositor_x11,
+                      MetaWindow        *window)
+{
+  MetaCompositor *compositor = META_COMPOSITOR (compositor_x11);
+  MetaDisplay *display = meta_compositor_get_display (compositor);
+  Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display);
+
+  if (!window)
+    {
+      XFixesSetWindowShapeRegion (xdisplay, compositor_x11->output,
+                                  ShapeBounding, 0, 0, None);
+    }
+  else
+    {
+      XserverRegion output_region;
+      XRectangle screen_rect, window_bounds;
+      int width, height;
+      MetaRectangle rect;
+
+      meta_window_get_frame_rect (window, &rect);
+
+      window_bounds.x = rect.x;
+      window_bounds.y = rect.y;
+      window_bounds.width = rect.width;
+      window_bounds.height = rect.height;
+
+      meta_display_get_size (display, &width, &height);
+      screen_rect.x = 0;
+      screen_rect.y = 0;
+      screen_rect.width = width;
+      screen_rect.height = height;
+
+      output_region = XFixesCreateRegion (xdisplay, &window_bounds, 1);
+
+      XFixesInvertRegion (xdisplay, output_region, &screen_rect, output_region);
+      XFixesSetWindowShapeRegion (xdisplay, compositor_x11->output,
+                                  ShapeBounding, 0, 0, output_region);
+      XFixesDestroyRegion (xdisplay, output_region);
+    }
+}
+
+static void
+set_unredirected_window (MetaCompositorX11 *compositor_x11,
+                         MetaWindow        *window)
+{
+  MetaWindow *prev_unredirected_window = compositor_x11->unredirected_window;
+
+  if (prev_unredirected_window == window)
+    return;
+
+  if (prev_unredirected_window)
+    {
+      MetaWindowActor *window_actor;
+
+      window_actor = meta_window_actor_from_window (prev_unredirected_window);
+      meta_window_actor_set_unredirected (window_actor, FALSE);
+    }
+
+  shape_cow_for_window (compositor_x11, window);
+  compositor_x11->unredirected_window = window;
+
+  if (window)
+    {
+      MetaWindowActor *window_actor;
+
+      window_actor = meta_window_actor_from_window (window);
+      meta_window_actor_set_unredirected (window_actor, TRUE);
+    }
+}
+
+static void
+meta_compositor_x11_pre_paint (MetaCompositor *compositor)
+{
+  MetaCompositorX11 *compositor_x11 = META_COMPOSITOR_X11 (compositor);
+  MetaWindowActor *top_window_actor;
+  MetaCompositorClass *parent_class;
+
+  top_window_actor = meta_compositor_get_top_window_actor (compositor);
+  if (!meta_compositor_is_unredirect_inhibited (compositor) &&
+      top_window_actor &&
+      meta_window_actor_should_unredirect (top_window_actor))
+    {
+      MetaWindow *top_window;
+
+      top_window = meta_window_actor_get_meta_window (top_window_actor);
+      set_unredirected_window (compositor_x11, top_window);
+    }
+  else
+    {
+      set_unredirected_window (compositor_x11, NULL);
+    }
+
+  parent_class = META_COMPOSITOR_CLASS (meta_compositor_x11_parent_class);
+  parent_class->pre_paint (compositor);
+
+  if (compositor_x11->frame_has_updated_xsurfaces)
+    {
+      MetaDisplay *display = meta_compositor_get_display (compositor);
+
+      /*
+       * We need to make sure that any X drawing that happens before the
+       * XDamageSubtract() for each window above is visible to subsequent GL
+       * rendering; the standardized way to do this is GL_EXT_X11_sync_object.
+       * Since this isn't implemented yet in mesa, we also have a path that
+       * relies on the implementation of the open source drivers.
+       *
+       * Anything else, we just hope for the best.
+       *
+       * Xorg and open source driver specifics:
+       *
+       * The X server makes sure to flush drawing to the kernel before sending
+       * out damage events, but since we use DamageReportBoundingBox there may
+       * be drawing between the last damage event and the XDamageSubtract()
+       * that needs to be flushed as well.
+       *
+       * Xorg always makes sure that drawing is flushed to the kernel before
+       * writing events or responses to the client, so any round trip request
+       * at this point is sufficient to flush the GLX buffers.
+       */
+      if (compositor_x11->have_x11_sync_object)
+        compositor_x11->have_x11_sync_object = meta_sync_ring_insert_wait ();
+      else
+        XSync (display->x11_display->xdisplay, False);
+    }
+}
+
+static void
+meta_compositor_x11_post_paint (MetaCompositor *compositor)
+{
+  MetaCompositorX11 *compositor_x11 = META_COMPOSITOR_X11 (compositor);
+  MetaCompositorClass *parent_class;
+
+  if (compositor_x11->frame_has_updated_xsurfaces)
+    {
+      if (compositor_x11->have_x11_sync_object)
+        compositor_x11->have_x11_sync_object = meta_sync_ring_after_frame ();
+
+      compositor_x11->frame_has_updated_xsurfaces = FALSE;
+    }
+
+  parent_class = META_COMPOSITOR_CLASS (meta_compositor_x11_parent_class);
+  parent_class->post_paint (compositor);
+}
+
+static void
+meta_compositor_x11_remove_window (MetaCompositor *compositor,
+                                   MetaWindow     *window)
+{
+  MetaCompositorX11 *compositor_x11 = META_COMPOSITOR_X11 (compositor);
+  MetaCompositorClass *parent_class;
+
+  if (compositor_x11->unredirected_window == window)
+    set_unredirected_window (compositor_x11, NULL);
+
+  parent_class = META_COMPOSITOR_CLASS (meta_compositor_x11_parent_class);
+  parent_class->remove_window (compositor, window);
+}
+
+Window
+meta_compositor_x11_get_output_xwindow (MetaCompositorX11 *compositor_x11)
+{
+  return compositor_x11->output;
+}
+
+static void
+meta_compositor_x11_dispose (GObject *object)
+{
+  MetaCompositorX11 *compositor_x11 = META_COMPOSITOR_X11 (object);
+
+  if (compositor_x11->have_x11_sync_object)
+    {
+      meta_sync_ring_destroy ();
+      compositor_x11->have_x11_sync_object = FALSE;
+    }
+
+  G_OBJECT_CLASS (meta_compositor_x11_parent_class)->dispose (object);
+}
+
+static void
+meta_compositor_x11_init (MetaCompositorX11 *compositor_x11)
+{
+}
+
+static void
+meta_compositor_x11_class_init (MetaCompositorX11Class *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  MetaCompositorClass *compositor_class = META_COMPOSITOR_CLASS (klass);
+
+  object_class->dispose = meta_compositor_x11_dispose;
+
+  compositor_class->manage = meta_compositor_x11_manage;
+  compositor_class->unmanage = meta_compositor_x11_unmanage;
+  compositor_class->pre_paint = meta_compositor_x11_pre_paint;
+  compositor_class->post_paint = meta_compositor_x11_post_paint;
+  compositor_class->remove_window = meta_compositor_x11_remove_window;
+}
diff --git a/src/compositor/meta-compositor-x11.h b/src/compositor/meta-compositor-x11.h
new file mode 100644
index 000000000..f577f73e0
--- /dev/null
+++ b/src/compositor/meta-compositor-x11.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2019 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_COMPOSITOR_X11_H
+#define META_COMPOSITOR_X11_H
+
+#include "compositor/compositor-private.h"
+
+#define META_TYPE_COMPOSITOR_X11 (meta_compositor_x11_get_type ())
+G_DECLARE_FINAL_TYPE (MetaCompositorX11, meta_compositor_x11,
+                      META, COMPOSITOR_X11, MetaCompositor)
+
+void meta_compositor_x11_process_xevent (MetaCompositorX11 *compositor_x11,
+                                         XEvent            *xevent,
+                                         MetaWindow        *window);
+
+Window meta_compositor_x11_get_output_xwindow (MetaCompositorX11 *compositor_x11);
+
+#endif /* META_COMPOSITOR_X11_H */
diff --git a/src/compositor/meta-dnd.c b/src/compositor/meta-dnd.c
index 456a17dad..4139d9504 100644
--- a/src/compositor/meta-dnd.c
+++ b/src/compositor/meta-dnd.c
@@ -168,19 +168,20 @@ meta_dnd_notify_dnd_leave (MetaDnd *dnd)
  * http://www.freedesktop.org/wiki/Specifications/XDND
  */
 gboolean
-meta_dnd_handle_xdnd_event (MetaBackend    *backend,
-                            MetaCompositor *compositor,
-                            Display        *xdisplay,
-                            XEvent         *xev)
+meta_dnd_handle_xdnd_event (MetaBackend       *backend,
+                            MetaCompositorX11 *compositor_x11,
+                            Display           *xdisplay,
+                            XEvent            *xev)
 {
   MetaDnd *dnd = meta_backend_get_dnd (backend);
+  MetaCompositor *compositor = META_COMPOSITOR (compositor_x11);
   Window output_window;
   ClutterStage *stage;
 
   if (xev->xany.type != ClientMessage)
     return FALSE;
 
-  output_window = meta_compositor_get_output_xwindow (compositor);
+  output_window = meta_compositor_x11_get_output_xwindow (compositor_x11);
   stage = meta_compositor_get_stage (compositor);
   if (xev->xany.window != output_window &&
       xev->xany.window != clutter_x11_get_stage_window (stage))
diff --git a/src/meson.build b/src/meson.build
index e682aa4fd..c6c360169 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -271,6 +271,8 @@ mutter_sources = [
   'compositor/meta-background-group.c',
   'compositor/meta-background-image.c',
   'compositor/meta-background-private.h',
+  'compositor/meta-compositor-x11.c',
+  'compositor/meta-compositor-x11.h',
   'compositor/meta-cullable.c',
   'compositor/meta-cullable.h',
   'compositor/meta-dnd-actor.c',
@@ -454,6 +456,8 @@ if have_wayland
   mutter_sources += [
     'compositor/meta-surface-actor-wayland.c',
     'compositor/meta-surface-actor-wayland.h',
+    'compositor/meta-compositor-server.c',
+    'compositor/meta-compositor-server.h',
     'wayland/meta-cursor-sprite-wayland.c',
     'wayland/meta-cursor-sprite-wayland.h',
     'wayland/meta-pointer-confinement-wayland.c',
diff --git a/src/meta/compositor.h b/src/meta/compositor.h
index 0b4df93f7..1a028b90e 100644
--- a/src/meta/compositor.h
+++ b/src/meta/compositor.h
@@ -21,7 +21,6 @@
 #define META_COMPOSITOR_H
 
 #include <glib.h>
-#include <X11/Xlib.h>
 
 #include <meta/types.h>
 #include <meta/boxes.h>
@@ -87,11 +86,6 @@ META_EXPORT
 void meta_compositor_window_opacity_changed (MetaCompositor *compositor,
                                              MetaWindow     *window);
 
-META_EXPORT
-gboolean meta_compositor_process_event (MetaCompositor *compositor,
-                                        XEvent         *event,
-                                        MetaWindow     *window);
-
 META_EXPORT
 gboolean meta_compositor_filter_keybinding (MetaCompositor *compositor,
                                             MetaKeyBinding *binding);
diff --git a/src/x11/events.c b/src/x11/events.c
index cc4bde684..31a9b7151 100644
--- a/src/x11/events.c
+++ b/src/x11/events.c
@@ -31,6 +31,7 @@
 
 #include "backends/meta-cursor-tracker-private.h"
 #include "backends/x11/meta-backend-x11.h"
+#include "compositor/meta-compositor-x11.h"
 #include "core/bell.h"
 #include "core/display-private.h"
 #include "core/meta-workspace-manager-private.h"
@@ -1862,14 +1863,18 @@ meta_x11_display_handle_xevent (MetaX11Display *x11_display,
     }
 
  out:
-  if (!bypass_compositor)
+  if (!bypass_compositor && META_IS_COMPOSITOR_X11 (display->compositor))
     {
-      MetaWindow *window = modified != None ?
-                           meta_x11_display_lookup_x_window (x11_display, modified) :
-                           NULL;
+      MetaCompositorX11 *compositor_x11 =
+        META_COMPOSITOR_X11 (display->compositor);
+      MetaWindow *window;
 
-      if (meta_compositor_process_event (display->compositor, event, window))
-        bypass_gtk = TRUE;
+      if (modified != None)
+        window = meta_x11_display_lookup_x_window (x11_display, modified);
+      else
+        window = NULL;
+
+      meta_compositor_x11_process_xevent (compositor_x11, event, window);
     }
 
   display->current_time = META_CURRENT_TIME;



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