[mutter] backends/x11: Split up X11 backend into Cm and Nested



commit 6d6412384938b1fe2a5e93e4d793d97aa0ad6bca
Author: Jonas Ådahl <jadahl gmail com>
Date:   Fri Jan 27 23:04:02 2017 +0800

    backends/x11: Split up X11 backend into Cm and Nested
    
    Split up the X11 backend into two parts, one for running as a
    Compositing Manager, and one for running as a nested Wayland
    compositor.
    
    This commit also cleans up the compositor configuration calculation,
    attempting to make it more approachable.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=777800

 src/Makefile.am                                   |    4 +
 src/backends/x11/cm/meta-backend-x11-cm.c         |  177 +++++++++++++++
 src/backends/x11/cm/meta-backend-x11-cm.h         |   31 +++
 src/backends/x11/meta-backend-x11.c               |  245 +++------------------
 src/backends/x11/meta-backend-x11.h               |    7 +
 src/backends/x11/nested/meta-backend-x11-nested.c |  168 ++++++++++++++
 src/backends/x11/nested/meta-backend-x11-nested.h |   31 +++
 src/core/main.c                                   |   68 +++++-
 8 files changed, 511 insertions(+), 220 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index b5c0d5a..2e30596 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -135,6 +135,10 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES =     \
        backends/x11/meta-clutter-backend-x11.h         \
        backends/x11/meta-cursor-renderer-x11.c         \
        backends/x11/meta-cursor-renderer-x11.h         \
+       backends/x11/cm/meta-backend-x11-cm.c           \
+       backends/x11/cm/meta-backend-x11-cm.h           \
+       backends/x11/nested/meta-backend-x11-nested.c   \
+       backends/x11/nested/meta-backend-x11-nested.h   \
        backends/x11/nested/meta-cursor-renderer-x11-nested.c           \
        backends/x11/nested/meta-cursor-renderer-x11-nested.h           \
        backends/x11/meta-idle-monitor-xsync.c          \
diff --git a/src/backends/x11/cm/meta-backend-x11-cm.c b/src/backends/x11/cm/meta-backend-x11-cm.c
new file mode 100644
index 0000000..ac9fc25
--- /dev/null
+++ b/src/backends/x11/cm/meta-backend-x11-cm.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2017 Red Hat
+ *
+ * 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 "backends/x11/cm/meta-backend-x11-cm.h"
+
+#include "backends/meta-backend-private.h"
+#include "backends/x11/meta-cursor-renderer-x11.h"
+#include "backends/x11/meta-monitor-manager-xrandr.h"
+
+struct _MetaBackendX11Cm
+{
+  MetaBackendX11 parent;
+};
+
+G_DEFINE_TYPE (MetaBackendX11Cm, meta_backend_x11_cm, META_TYPE_BACKEND_X11)
+
+static void
+take_touch_grab (MetaBackend *backend)
+{
+  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
+  Display *xdisplay = meta_backend_x11_get_xdisplay (x11);
+  unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
+  XIEventMask mask = { META_VIRTUAL_CORE_POINTER_ID, sizeof (mask_bits), mask_bits };
+  XIGrabModifiers mods = { XIAnyModifier, 0 };
+
+  XISetMask (mask.mask, XI_TouchBegin);
+  XISetMask (mask.mask, XI_TouchUpdate);
+  XISetMask (mask.mask, XI_TouchEnd);
+
+  XIGrabTouchBegin (xdisplay, META_VIRTUAL_CORE_POINTER_ID,
+                    DefaultRootWindow (xdisplay),
+                    False, &mask, 1, &mods);
+}
+
+static void
+meta_backend_x11_cm_post_init (MetaBackend *backend)
+{
+  MetaBackendClass *parent_backend_class =
+    META_BACKEND_CLASS (meta_backend_x11_cm_parent_class);
+
+  parent_backend_class->post_init (backend);
+
+  take_touch_grab (backend);
+}
+
+static MetaMonitorManager *
+meta_backend_x11_cm_create_monitor_manager (MetaBackend *backend)
+{
+  return g_object_new (META_TYPE_MONITOR_MANAGER_XRANDR, NULL);
+}
+
+static MetaCursorRenderer *
+meta_backend_x11_cm_create_cursor_renderer (MetaBackend *backend)
+{
+  return g_object_new (META_TYPE_CURSOR_RENDERER_X11, NULL);
+}
+
+static void
+meta_backend_x11_cm_update_screen_size (MetaBackend *backend,
+                                        int          width,
+                                        int          height)
+{
+  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
+  Display *xdisplay = meta_backend_x11_get_xdisplay (x11);
+  Window xwin = meta_backend_x11_get_xwindow (x11);
+
+  XResizeWindow (xdisplay, xwin, width, height);
+}
+
+static void
+meta_backend_x11_cm_select_stage_events (MetaBackend *backend)
+{
+  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
+  Display *xdisplay = meta_backend_x11_get_xdisplay (x11);
+  Window xwin = meta_backend_x11_get_xwindow (x11);
+  unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
+  XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
+
+  XISetMask (mask.mask, XI_KeyPress);
+  XISetMask (mask.mask, XI_KeyRelease);
+  XISetMask (mask.mask, XI_ButtonPress);
+  XISetMask (mask.mask, XI_ButtonRelease);
+  XISetMask (mask.mask, XI_Enter);
+  XISetMask (mask.mask, XI_Leave);
+  XISetMask (mask.mask, XI_FocusIn);
+  XISetMask (mask.mask, XI_FocusOut);
+  XISetMask (mask.mask, XI_Motion);
+
+  XISelectEvents (xdisplay, xwin, &mask, 1);
+}
+
+static gboolean
+meta_backend_x11_cm_handle_host_xevent (MetaBackendX11 *backend_x11,
+                                        XEvent         *event)
+{
+  MetaBackend *backend = META_BACKEND (backend_x11);
+  MetaMonitorManager *monitor_manager =
+    meta_backend_get_monitor_manager (backend);
+  MetaMonitorManagerXrandr *monitor_manager_xrandr =
+    META_MONITOR_MANAGER_XRANDR (monitor_manager);
+
+  return meta_monitor_manager_xrandr_handle_xevent (monitor_manager_xrandr,
+                                                    event);
+}
+
+static void
+meta_backend_x11_cm_translate_device_event (MetaBackendX11 *x11,
+                                            XIDeviceEvent  *device_event)
+{
+  Window stage_window = meta_backend_x11_get_xwindow (x11);
+
+  if (device_event->event != stage_window)
+    {
+      device_event->event = stage_window;
+
+      /* As an X11 compositor, the stage window is always at 0,0, so
+       * using root coordinates will give us correct stage coordinates
+       * as well... */
+      device_event->event_x = device_event->root_x;
+      device_event->event_y = device_event->root_y;
+    }
+}
+
+static void
+meta_backend_x11_cm_translate_crossing_event (MetaBackendX11 *x11,
+                                              XIEnterEvent   *enter_event)
+{
+  Window stage_window = meta_backend_x11_get_xwindow (x11);
+
+  if (enter_event->event != stage_window)
+    {
+      enter_event->event = stage_window;
+      enter_event->event_x = enter_event->root_x;
+      enter_event->event_y = enter_event->root_y;
+    }
+}
+
+static void
+meta_backend_x11_cm_init (MetaBackendX11Cm *backend_x11_cm)
+{
+}
+
+static void
+meta_backend_x11_cm_class_init (MetaBackendX11CmClass *klass)
+{
+  MetaBackendClass *backend_class = META_BACKEND_CLASS (klass);
+  MetaBackendX11Class *backend_x11_class = META_BACKEND_X11_CLASS (klass);
+
+  backend_class->post_init = meta_backend_x11_cm_post_init;
+  backend_class->create_monitor_manager = meta_backend_x11_cm_create_monitor_manager;
+  backend_class->create_cursor_renderer = meta_backend_x11_cm_create_cursor_renderer;
+  backend_class->update_screen_size = meta_backend_x11_cm_update_screen_size;
+  backend_class->select_stage_events = meta_backend_x11_cm_select_stage_events;
+
+  backend_x11_class->handle_host_xevent = meta_backend_x11_cm_handle_host_xevent;
+  backend_x11_class->translate_device_event = meta_backend_x11_cm_translate_device_event;
+  backend_x11_class->translate_crossing_event = meta_backend_x11_cm_translate_crossing_event;
+}
+
diff --git a/src/backends/x11/cm/meta-backend-x11-cm.h b/src/backends/x11/cm/meta-backend-x11-cm.h
new file mode 100644
index 0000000..5332da1
--- /dev/null
+++ b/src/backends/x11/cm/meta-backend-x11-cm.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 Red Hat
+ *
+ * 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_BACKEND_X11_CM_H
+#define META_BACKEND_X11_CM_H
+
+#include <glib-object.h>
+
+#include "backends/x11/meta-backend-x11.h"
+
+#define META_TYPE_BACKEND_X11_CM (meta_backend_x11_cm_get_type ())
+G_DECLARE_FINAL_TYPE (MetaBackendX11Cm, meta_backend_x11_cm,
+                      META, BACKEND_X11_CM, MetaBackendX11)
+
+#endif /* META_BACKEND_X11_CM_H */
diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c
index 9237f27..92a13dc 100644
--- a/src/backends/x11/meta-backend-x11.c
+++ b/src/backends/x11/meta-backend-x11.c
@@ -39,30 +39,15 @@
 #include <xkbcommon/xkbcommon-x11.h>
 
 #include "meta-idle-monitor-xsync.h"
-#include "meta-monitor-manager-xrandr.h"
-#include "backends/meta-monitor-manager-dummy.h"
 #include "backends/meta-stage.h"
-#include "backends/x11/nested/meta-cursor-renderer-x11-nested.h"
 #include "backends/x11/meta-clutter-backend-x11.h"
 #include "backends/x11/meta-renderer-x11.h"
 #include "meta/meta-cursor-tracker.h"
-#include "meta-cursor-renderer-x11.h"
-#ifdef HAVE_WAYLAND
-#include "wayland/meta-wayland.h"
-#endif
 
 #include <meta/util.h>
 #include "display-private.h"
 #include "compositor/compositor-private.h"
 
-typedef enum {
-  /* We're a traditional CM running under the host. */
-  META_BACKEND_X11_MODE_COMPOSITOR,
-
-  /* We're a nested X11 client */
-  META_BACKEND_X11_MODE_NESTED,
-} MetaBackendX11Mode;
-
 struct _MetaBackendX11Private
 {
   /* The host X11 display */
@@ -70,8 +55,6 @@ struct _MetaBackendX11Private
   xcb_connection_t *xcb;
   GSource *source;
 
-  MetaBackendX11Mode mode;
-
   int xsync_event_base;
   int xsync_error_base;
 
@@ -107,27 +90,22 @@ handle_alarm_notify (MetaBackend *backend,
 }
 
 static void
+meta_backend_x11_translate_device_event (MetaBackendX11 *x11,
+                                         XIDeviceEvent  *device_event)
+{
+  MetaBackendX11Class *backend_x11_class =
+    META_BACKEND_X11_GET_CLASS (x11);
+
+  backend_x11_class->translate_device_event (x11, device_event);
+}
+
+static void
 translate_device_event (MetaBackendX11 *x11,
                         XIDeviceEvent  *device_event)
 {
   MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
-  Window stage_window = meta_backend_x11_get_xwindow (x11);
 
-  if (device_event->event != stage_window)
-    {
-      /* This codepath should only ever trigger as an X11 compositor,
-       * and never under nested, as under nested all backend events
-       * should be reported with respect to the stage window. */
-      g_assert (priv->mode == META_BACKEND_X11_MODE_COMPOSITOR);
-
-      device_event->event = stage_window;
-
-      /* As an X11 compositor, the stage window is always at 0,0, so
-       * using root coordinates will give us correct stage coordinates
-       * as well... */
-      device_event->event_x = device_event->root_x;
-      device_event->event_y = device_event->root_y;
-    }
+  meta_backend_x11_translate_device_event (x11, device_event);
 
   if (!device_event->send_event && device_event->time != CurrentTime)
     {
@@ -146,11 +124,20 @@ translate_device_event (MetaBackendX11 *x11,
 }
 
 static void
+meta_backend_x11_translate_crossing_event (MetaBackendX11 *x11,
+                                           XIEnterEvent   *enter_event)
+{
+  MetaBackendX11Class *backend_x11_class =
+    META_BACKEND_X11_GET_CLASS (x11);
+
+  if (backend_x11_class->translate_crossing_event)
+    backend_x11_class->translate_crossing_event (x11, enter_event);
+}
+
+static void
 translate_crossing_event (MetaBackendX11 *x11,
                           XIEnterEvent   *enter_event)
 {
-  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
-
   /* Throw out weird events generated by grabs. */
   if (enter_event->mode == XINotifyGrab ||
       enter_event->mode == XINotifyUngrab)
@@ -159,14 +146,7 @@ translate_crossing_event (MetaBackendX11 *x11,
       return;
     }
 
-  Window stage_window = meta_backend_x11_get_xwindow (x11);
-  if (enter_event->event != stage_window &&
-      priv->mode == META_BACKEND_X11_MODE_COMPOSITOR)
-    {
-      enter_event->event = meta_backend_x11_get_xwindow (x11);
-      enter_event->event_x = enter_event->root_x;
-      enter_event->event_y = enter_event->root_y;
-    }
+  meta_backend_x11_translate_crossing_event (x11, enter_event);
 }
 
 static void
@@ -254,6 +234,16 @@ keymap_changed (MetaBackend *backend)
   g_signal_emit_by_name (backend, "keymap-changed", 0);
 }
 
+static gboolean
+meta_backend_x11_handle_host_xevent (MetaBackendX11 *backend_x11,
+                                     XEvent         *event)
+{
+  MetaBackendX11Class *backend_x11_class =
+    META_BACKEND_X11_GET_CLASS (backend_x11);
+
+  return backend_x11_class->handle_host_xevent (backend_x11, event);
+}
+
 static void
 handle_host_xevent (MetaBackend *backend,
                     XEvent      *event)
@@ -275,24 +265,8 @@ handle_host_xevent (MetaBackend *backend,
       }
   }
 
-  if (priv->mode == META_BACKEND_X11_MODE_NESTED && event->type == FocusIn)
-    {
-#ifdef HAVE_WAYLAND
-      Window xwin = meta_backend_x11_get_xwindow(x11);
-      XEvent xev;
-
-      if (event->xfocus.window == xwin)
-        {
-          /* Since we've selected for KeymapStateMask, every FocusIn is followed immediately
-           * by a KeymapNotify event */
-          XMaskEvent(priv->xdisplay, KeymapStateMask, &xev);
-          MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
-          meta_wayland_compositor_update_key_state (compositor, xev.xkeymap.key_vector, 32, 8);
-        }
-#else
-      g_assert_not_reached ();
-#endif
-    }
+  bypass_clutter = (meta_backend_x11_handle_host_xevent (x11, event) ||
+                    bypass_clutter);
 
   if (event->type == (priv->xsync_event_base + XSyncAlarmNotify))
     handle_alarm_notify (backend, event);
@@ -322,13 +296,6 @@ handle_host_xevent (MetaBackend *backend,
         }
     }
 
-  {
-    MetaMonitorManager *manager = meta_backend_get_monitor_manager (backend);
-    if (META_IS_MONITOR_MANAGER_XRANDR (manager) &&
-        meta_monitor_manager_xrandr_handle_xevent (META_MONITOR_MANAGER_XRANDR (manager), event))
-      bypass_clutter = TRUE;
-  }
-
   if (!bypass_clutter)
     {
       handle_input_event (x11, event);
@@ -417,24 +384,6 @@ x_event_source_new (MetaBackend *backend)
 }
 
 static void
-take_touch_grab (MetaBackend *backend)
-{
-  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
-  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
-  unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
-  XIEventMask mask = { META_VIRTUAL_CORE_POINTER_ID, sizeof (mask_bits), mask_bits };
-  XIGrabModifiers mods = { XIAnyModifier, 0 };
-
-  XISetMask (mask.mask, XI_TouchBegin);
-  XISetMask (mask.mask, XI_TouchUpdate);
-  XISetMask (mask.mask, XI_TouchEnd);
-
-  XIGrabTouchBegin (priv->xdisplay, META_VIRTUAL_CORE_POINTER_ID,
-                    DefaultRootWindow (priv->xdisplay),
-                    False, &mask, 1, &mods);
-}
-
-static void
 on_device_added (ClutterDeviceManager *device_manager,
                  ClutterInputDevice   *device,
                  gpointer              user_data)
@@ -490,10 +439,6 @@ meta_backend_x11_post_init (MetaBackend *backend)
   if (!has_xi)
     meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n");
 
-  /* We only take the passive touch grab if we are a X11 compositor */
-  if (priv->mode == META_BACKEND_X11_MODE_COMPOSITOR)
-    take_touch_grab (backend);
-
   priv->xcb = XGetXCBConnection (priv->xdisplay);
   if (!xkb_x11_setup_xkb_extension (priv->xcb,
                                     XKB_X11_MIN_MAJOR_XKB_VERSION,
@@ -530,42 +475,6 @@ meta_backend_x11_create_idle_monitor (MetaBackend *backend,
                        NULL);
 }
 
-static MetaMonitorManager *
-meta_backend_x11_create_monitor_manager (MetaBackend *backend)
-{
-  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
-  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
-
-  switch (priv->mode)
-    {
-    case META_BACKEND_X11_MODE_COMPOSITOR:
-      return g_object_new (META_TYPE_MONITOR_MANAGER_XRANDR, NULL);
-    case META_BACKEND_X11_MODE_NESTED:
-      return g_object_new (META_TYPE_MONITOR_MANAGER_DUMMY, NULL);
-    default:
-      g_assert_not_reached ();
-    }
-}
-
-static MetaCursorRenderer *
-meta_backend_x11_create_cursor_renderer (MetaBackend *backend)
-{
-  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
-  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
-
-  switch (priv->mode)
-    {
-    case META_BACKEND_X11_MODE_COMPOSITOR:
-      return g_object_new (META_TYPE_CURSOR_RENDERER_X11, NULL);
-      break;
-    case META_BACKEND_X11_MODE_NESTED:
-      return g_object_new (META_TYPE_CURSOR_RENDERER_X11_NESTED, NULL);
-      break;
-    default:
-      g_assert_not_reached ();
-    }
-}
-
 static MetaRenderer *
 meta_backend_x11_create_renderer (MetaBackend *backend)
 {
@@ -857,79 +766,6 @@ meta_backend_x11_handle_event (MetaBackendX11 *x11,
 }
 
 static void
-meta_backend_x11_update_screen_size (MetaBackend *backend,
-                                     int width, int height)
-{
-  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
-  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
-
-  if (priv->mode == META_BACKEND_X11_MODE_NESTED)
-    {
-      ClutterActor *stage = meta_backend_get_stage (backend);
-      MetaRenderer *renderer = meta_backend_get_renderer (backend);
-
-      if (meta_is_stage_views_enabled ())
-        meta_renderer_rebuild_views (renderer);
-      clutter_actor_set_size (stage, width, height);
-    }
-  else
-    {
-      Window xwin = meta_backend_x11_get_xwindow (x11);
-      XResizeWindow (priv->xdisplay, xwin, width, height);
-    }
-}
-
-static void
-meta_backend_x11_select_stage_events (MetaBackend *backend)
-{
-  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
-  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
-  Window xwin = meta_backend_x11_get_xwindow (x11);
-  unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
-  XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
-
-  XISetMask (mask.mask, XI_KeyPress);
-  XISetMask (mask.mask, XI_KeyRelease);
-  XISetMask (mask.mask, XI_ButtonPress);
-  XISetMask (mask.mask, XI_ButtonRelease);
-  XISetMask (mask.mask, XI_Enter);
-  XISetMask (mask.mask, XI_Leave);
-  XISetMask (mask.mask, XI_FocusIn);
-  XISetMask (mask.mask, XI_FocusOut);
-  XISetMask (mask.mask, XI_Motion);
-
-  if (priv->mode == META_BACKEND_X11_MODE_NESTED)
-    {
-      /* When we're an X11 compositor, we can't take these events or else
-       * replaying events from our passive root window grab will cause
-       * them to come back to us.
-       *
-       * When we're a nested application, we want to behave like any other
-       * application, so select these events like normal apps do.
-       */
-      XISetMask (mask.mask, XI_TouchBegin);
-      XISetMask (mask.mask, XI_TouchEnd);
-      XISetMask (mask.mask, XI_TouchUpdate);
-    }
-
-  XISelectEvents (priv->xdisplay, xwin, &mask, 1);
-
-  if (priv->mode == META_BACKEND_X11_MODE_NESTED)
-    {
-      /* We have no way of tracking key changes when the stage doesn't have
-       * focus, so we select for KeymapStateMask so that we get a complete
-       * dump of the keyboard state in a KeymapNotify event that immediately
-       * follows each FocusIn (and EnterNotify, but we ignore that.)
-       */
-      XWindowAttributes xwa;
-
-      XGetWindowAttributes(priv->xdisplay, xwin, &xwa);
-      XSelectInput(priv->xdisplay, xwin,
-                   xwa.your_event_mask | FocusChangeMask | KeymapStateMask);
-    }
-}
-
-static void
 meta_backend_x11_class_init (MetaBackendX11Class *klass)
 {
   MetaBackendClass *backend_class = META_BACKEND_CLASS (klass);
@@ -937,8 +773,6 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
   backend_class->create_clutter_backend = meta_backend_x11_create_clutter_backend;
   backend_class->post_init = meta_backend_x11_post_init;
   backend_class->create_idle_monitor = meta_backend_x11_create_idle_monitor;
-  backend_class->create_monitor_manager = meta_backend_x11_create_monitor_manager;
-  backend_class->create_cursor_renderer = meta_backend_x11_create_cursor_renderer;
   backend_class->create_renderer = meta_backend_x11_create_renderer;
   backend_class->grab_device = meta_backend_x11_grab_device;
   backend_class->ungrab_device = meta_backend_x11_ungrab_device;
@@ -947,25 +781,16 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
   backend_class->set_keymap = meta_backend_x11_set_keymap;
   backend_class->get_keymap = meta_backend_x11_get_keymap;
   backend_class->lock_layout_group = meta_backend_x11_lock_layout_group;
-  backend_class->update_screen_size = meta_backend_x11_update_screen_size;
-  backend_class->select_stage_events = meta_backend_x11_select_stage_events;
   backend_class->set_numlock = meta_backend_x11_set_numlock;
 }
 
 static void
 meta_backend_x11_init (MetaBackendX11 *x11)
 {
-  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
-
   clutter_x11_request_reset_on_video_memory_purge ();
 
   /* We do X11 event retrieval ourselves */
   clutter_x11_disable_event_retrieval ();
-
-  if (meta_is_wayland_compositor ())
-    priv->mode = META_BACKEND_X11_MODE_NESTED;
-  else
-    priv->mode = META_BACKEND_X11_MODE_COMPOSITOR;
 }
 
 Display *
diff --git a/src/backends/x11/meta-backend-x11.h b/src/backends/x11/meta-backend-x11.h
index 8bb3388..9c163eb 100644
--- a/src/backends/x11/meta-backend-x11.h
+++ b/src/backends/x11/meta-backend-x11.h
@@ -38,6 +38,13 @@ G_DECLARE_DERIVABLE_TYPE (MetaBackendX11, meta_backend_x11,
 struct _MetaBackendX11Class
 {
   MetaBackendClass parent_class;
+
+  gboolean (* handle_host_xevent) (MetaBackendX11 *x11,
+                                   XEvent         *event);
+  void (* translate_device_event) (MetaBackendX11 *x11,
+                                   XIDeviceEvent  *device_event);
+  void (* translate_crossing_event) (MetaBackendX11 *x11,
+                                     XIEnterEvent   *enter_event);
 };
 
 Display * meta_backend_x11_get_xdisplay (MetaBackendX11 *backend);
diff --git a/src/backends/x11/nested/meta-backend-x11-nested.c 
b/src/backends/x11/nested/meta-backend-x11-nested.c
new file mode 100644
index 0000000..cf9cea7
--- /dev/null
+++ b/src/backends/x11/nested/meta-backend-x11-nested.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2017 Red Hat
+ *
+ * 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 "backends/x11/nested/meta-backend-x11-nested.h"
+
+#include "backends/meta-monitor-manager-dummy.h"
+#include "backends/x11/nested/meta-backend-x11-nested.h"
+#include "backends/x11/nested/meta-cursor-renderer-x11-nested.h"
+
+#include "wayland/meta-wayland.h"
+
+struct _MetaBackendX11Nested
+{
+  MetaBackendX11 parent;
+};
+
+G_DEFINE_TYPE (MetaBackendX11Nested, meta_backend_x11_nested,
+               META_TYPE_BACKEND_X11)
+
+static MetaMonitorManager *
+meta_backend_x11_nested_create_monitor_manager (MetaBackend *backend)
+{
+  return g_object_new (META_TYPE_MONITOR_MANAGER_DUMMY, NULL);
+}
+
+static MetaCursorRenderer *
+meta_backend_x11_nested_create_cursor_renderer (MetaBackend *backend)
+{
+  return g_object_new (META_TYPE_CURSOR_RENDERER_X11_NESTED, NULL);
+}
+
+static void
+meta_backend_x11_nested_update_screen_size (MetaBackend *backend,
+                                            int          width,
+                                            int          height)
+{
+  ClutterActor *stage = meta_backend_get_stage (backend);
+  MetaRenderer *renderer = meta_backend_get_renderer (backend);
+
+  if (meta_is_stage_views_enabled ())
+    meta_renderer_rebuild_views (renderer);
+  clutter_actor_set_size (stage, width, height);
+}
+
+static void
+meta_backend_x11_nested_select_stage_events (MetaBackend *backend)
+{
+  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
+  Display *xdisplay = meta_backend_x11_get_xdisplay (x11);
+  Window xwin = meta_backend_x11_get_xwindow (x11);
+  unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
+  XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
+
+  XISetMask (mask.mask, XI_KeyPress);
+  XISetMask (mask.mask, XI_KeyRelease);
+  XISetMask (mask.mask, XI_ButtonPress);
+  XISetMask (mask.mask, XI_ButtonRelease);
+  XISetMask (mask.mask, XI_Enter);
+  XISetMask (mask.mask, XI_Leave);
+  XISetMask (mask.mask, XI_FocusIn);
+  XISetMask (mask.mask, XI_FocusOut);
+  XISetMask (mask.mask, XI_Motion);
+
+  /*
+   * When we're an X11 compositor, we can't take these events or else replaying
+   * events from our passive root window grab will cause them to come back to
+   * us.
+   *
+   * When we're a nested application, we want to behave like any other
+   * application, so select these events like normal apps do.
+   */
+  XISetMask (mask.mask, XI_TouchBegin); XISetMask (mask.mask, XI_TouchEnd);
+  XISetMask (mask.mask, XI_TouchUpdate);
+
+  XISelectEvents (xdisplay, xwin, &mask, 1);
+
+  /*
+   * We have no way of tracking key changes when the stage doesn't have focus,
+   * so we select for KeymapStateMask so that we get a complete dump of the
+   * keyboard state in a KeymapNotify event that immediately follows each
+   * FocusIn (and EnterNotify, but we ignore that.)
+   */
+  XWindowAttributes xwa;
+
+  XGetWindowAttributes(xdisplay, xwin, &xwa);
+  XSelectInput(xdisplay, xwin,
+               xwa.your_event_mask | FocusChangeMask | KeymapStateMask);
+}
+
+static gboolean
+meta_backend_x11_nested_handle_host_xevent (MetaBackendX11 *x11,
+                                            XEvent         *event)
+{
+#ifdef HAVE_WAYLAND
+  if (event->type == FocusIn)
+    {
+      Window xwin = meta_backend_x11_get_xwindow (x11);
+      XEvent xev;
+
+      if (event->xfocus.window == xwin)
+        {
+          MetaWaylandCompositor *compositor =
+            meta_wayland_compositor_get_default ();
+          Display *xdisplay = meta_backend_x11_get_xdisplay (x11);
+
+          /*
+           * Since we've selected for KeymapStateMask, every FocusIn is
+           * followed immediately by a KeymapNotify event.
+           */
+          XMaskEvent (xdisplay, KeymapStateMask, &xev);
+          meta_wayland_compositor_update_key_state (compositor,
+                                                    xev.xkeymap.key_vector,
+                                                    32, 8);
+        }
+    }
+#endif
+
+  return FALSE;
+}
+
+static void
+meta_backend_x11_nested_translate_device_event (MetaBackendX11 *x11,
+                                                XIDeviceEvent  *device_event)
+{
+  /* This codepath should only ever trigger as an X11 compositor,
+   * and never under nested, as under nested all backend events
+   * should be reported with respect to the stage window.
+   */
+  g_assert (device_event->event == meta_backend_x11_get_xwindow (x11));
+}
+
+static void
+meta_backend_x11_nested_init (MetaBackendX11Nested *backend_x11_nested)
+{
+}
+
+static void
+meta_backend_x11_nested_class_init (MetaBackendX11NestedClass *klass)
+{
+  MetaBackendClass *backend_class = META_BACKEND_CLASS (klass);
+  MetaBackendX11Class *backend_x11_class = META_BACKEND_X11_CLASS (klass);
+
+  backend_class->create_monitor_manager = meta_backend_x11_nested_create_monitor_manager;
+  backend_class->create_cursor_renderer = meta_backend_x11_nested_create_cursor_renderer;
+  backend_class->update_screen_size = meta_backend_x11_nested_update_screen_size;
+  backend_class->select_stage_events = meta_backend_x11_nested_select_stage_events;
+
+  backend_x11_class->handle_host_xevent = meta_backend_x11_nested_handle_host_xevent;
+  backend_x11_class->translate_device_event = meta_backend_x11_nested_translate_device_event;
+}
diff --git a/src/backends/x11/nested/meta-backend-x11-nested.h 
b/src/backends/x11/nested/meta-backend-x11-nested.h
new file mode 100644
index 0000000..31ae96f
--- /dev/null
+++ b/src/backends/x11/nested/meta-backend-x11-nested.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 Red Hat
+ *
+ * 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_BACKEND_X11_NESTED_H
+#define META_BACKEND_X11_NESTED_H
+
+#include <glib-object.h>
+
+#include "backends/x11/meta-backend-x11.h"
+
+#define META_TYPE_BACKEND_X11_NESTED (meta_backend_x11_nested_get_type ())
+G_DECLARE_FINAL_TYPE (MetaBackendX11Nested, meta_backend_x11_nested,
+                      META, BACKEND_X11_NESTED, MetaBackendX11)
+
+#endif /* META_BACKEND_X11_NESTED_H */
diff --git a/src/core/main.c b/src/core/main.c
index dc40f6e..9b82ca7 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -80,10 +80,12 @@
 
 #ifdef HAVE_WAYLAND
 #include "wayland/meta-wayland.h"
+#include "backends/x11/nested/meta-backend-x11-nested.h"
 # endif
 
 #include "backends/meta-backend-private.h"
 #include "backends/x11/meta-backend-x11.h"
+#include "backends/x11/cm/meta-backend-x11-cm.h"
 
 #ifdef HAVE_NATIVE_BACKEND
 #include "backends/native/meta-backend-native.h"
@@ -397,6 +399,26 @@ check_for_wayland_session_type (void)
 }
 #endif
 
+/*
+ * Determine the compositor configuration, i.e. whether to run as a Wayland
+ * compositor, as well as what backend to use.
+ *
+ * There are various different flags affecting this:
+ *
+ *    --nested always forces the use of the nested X11 backend
+ *    --display-server always forces the use of the native backend
+ *    --wayland always forces the compositor type to be a Wayland compositor
+ *
+ * If no flag is passed that forces the compositor type, the compositor type
+ * is determined first from the logind session type, or if that fails, from the
+ * XDG_SESSION_TYPE enviornment variable.
+ *
+ * If no flag is passed that forces the backend type, the backend type is
+ * determined given the compositor type. If the compositor is a Wayland
+ * compositor, then the native backend is used, or the nested backend, would
+ * the native backend not be enabled at build time. If the compositor is not a
+ * Wayland compositor, then the X11 Compositing Manager backend is used.
+ */
 static void
 calculate_compositor_configuration (MetaCompositorType *compositor_type,
                                     GType              *backend_gtype)
@@ -413,22 +435,48 @@ calculate_compositor_configuration (MetaCompositorType *compositor_type,
 
   if (!run_as_wayland_compositor)
     run_as_wayland_compositor = check_for_wayland_session_type ();
+#endif /* HAVE_NATIVE_BACKEND */
 
-#ifdef CLUTTER_WINDOWING_EGL
-  if (opt_display_server || (run_as_wayland_compositor && !opt_nested))
-    *backend_gtype = META_TYPE_BACKEND_NATIVE;
+  if (run_as_wayland_compositor)
+    *compositor_type = META_COMPOSITOR_TYPE_WAYLAND;
   else
-#endif
-#endif
-#endif
-    *backend_gtype = META_TYPE_BACKEND_X11;
+#endif /* HAVE_WAYLAND */
+    *compositor_type = META_COMPOSITOR_TYPE_X11;
+
+  if (opt_nested)
+    {
+      *backend_gtype = META_TYPE_BACKEND_X11_NESTED;
+      return;
+    }
+
+#ifdef HAVE_NATIVE_BACKEND
+  if (opt_display_server)
+    {
+      *backend_gtype = META_TYPE_BACKEND_NATIVE;
+      return;
+    }
 
 #ifdef HAVE_WAYLAND
   if (run_as_wayland_compositor)
-    *compositor_type = META_COMPOSITOR_TYPE_WAYLAND;
+    {
+      *backend_gtype = META_TYPE_BACKEND_NATIVE;
+      return;
+    }
+#endif /* HAVE_WAYLAND */
+#endif /* HAVE_NATIVE_BACKEND */
+
+#ifdef HAVE_WAYLAND
+  if (run_as_wayland_compositor)
+    {
+      *backend_gtype = META_TYPE_BACKEND_X11_NESTED;
+      return;
+    }
   else
-#endif
-    *compositor_type = META_COMPOSITOR_TYPE_X11;
+#endif /* HAVE_WAYLAND */
+    {
+      *backend_gtype = META_TYPE_BACKEND_X11_CM;
+      return;
+    }
 }
 
 static gboolean _compositor_configuration_overridden = FALSE;


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