[mutter/wip/login1] Replace mutter-launch with logind integration



commit 6c7a47d32e58da6acc7d1c89451cafc674bdab63
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Tue Dec 31 17:44:45 2013 -0500

    Replace mutter-launch with logind integration
    
    This uses David Herrmann's new logind sessions interface to retrieve
    fds for input devices, rather than using a custom setuid helper to do
    the management. This vastly simplifies the interface.
    
    This does require systemd from git, as systemd v209 has not been
    released yet.

 .gitignore                         |    2 +-
 src/Makefile.am                    |   25 +-
 src/core/main.c                    |   35 ++-
 src/meta/main.h                    |    1 +
 src/mutter-wayland.desktop.in      |    2 +-
 src/org.freedesktop.login1.xml     |   42 ++
 src/wayland/meta-login1.c          |  227 +++++++++++
 src/wayland/meta-login1.h          |   35 ++
 src/wayland/meta-wayland-private.h |    6 +-
 src/wayland/meta-wayland.c         |   41 +-
 src/wayland/meta-weston-launch.c   |  401 ------------------
 src/wayland/meta-weston-launch.h   |   46 ---
 src/wayland/weston-launch.c        |  788 ------------------------------------
 src/wayland/weston-launch.h        |   69 ----
 14 files changed, 379 insertions(+), 1341 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index ba75840..6970ca4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -48,7 +48,6 @@ po/*.pot
 50-metacity-key.xml
 libmutter-wayland.pc
 mutter-wayland
-mutter-launch
 org.gnome.mutter.gschema.valid
 org.gnome.mutter.gschema.xml
 org.gnome.mutter.wayland.gschema.valid
@@ -77,6 +76,7 @@ src/mutter-marshal.[ch]
 src/stamp-mutter-marshal.h
 src/meta-dbus-xrandr.[ch]
 src/meta-dbus-idle-monitor.[ch]
+src/meta-dbus-login1.[ch]
 src/mutter-plugins.pc
 src/wayland/gtk-shell-protocol.c
 src/wayland/gtk-shell-server-protocol.h
diff --git a/src/Makefile.am b/src/Makefile.am
index ae8f7c1..a3a339b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -38,6 +38,7 @@ INCLUDES += \
 mutter_built_sources = \
        $(dbus_idle_built_sources)              \
        $(dbus_xrandr_built_sources)            \
+       $(dbus_login1_built_sources)            \
        mutter-enum-types.h                     \
        mutter-enum-types.c                     \
        wayland/gtk-shell-protocol.c            \
@@ -207,8 +208,8 @@ libmutter_wayland_la_SOURCES =                      \
        wayland/meta-wayland-surface.h          \
        wayland/meta-wayland-types.h            \
        wayland/meta-wayland-versions.h         \
-       wayland/meta-weston-launch.c            \
-       wayland/meta-weston-launch.h
+       wayland/meta-login1.c                   \
+       wayland/meta-login1.h
 
 nodist_libmutter_wayland_la_SOURCES =          \
        $(mutter_built_sources)
@@ -263,17 +264,6 @@ bin_PROGRAMS=mutter-wayland
 mutter_wayland_SOURCES = core/mutter.c
 mutter_wayland_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
 
-bin_PROGRAMS+=mutter-launch
-
-mutter_launch_SOURCES = wayland/weston-launch.c wayland/weston-launch.h
-
-mutter_launch_CFLAGS = $(MUTTER_LAUNCH_CFLAGS) -DLIBDIR=\"$(libdir)\"
-mutter_launch_LDFLAGS = $(MUTTER_LAUNCH_LIBS) -lpam
-
-install-exec-hook:
-       -chown root $(DESTDIR)$(bindir)/mutter-launch
-       -chmod u+s $(DESTDIR)$(bindir)/mutter-launch
-
 if HAVE_INTROSPECTION
 include $(INTROSPECTION_MAKEFILE)
 
@@ -409,6 +399,15 @@ $(dbus_idle_built_sources) : Makefile.am idle-monitor.xml
                --c-generate-object-manager                                             \
                $(srcdir)/idle-monitor.xml
 
+dbus_login1_built_sources = meta-dbus-login1.c meta-dbus-login1.h
+
+$(dbus_login1_built_sources) : Makefile.am org.freedesktop.login1.xml
+       $(AM_V_GEN)gdbus-codegen                                                        \
+               --interface-prefix org.freedesktop.login1                               \
+               --c-namespace Login1                                                    \
+               --generate-c-code meta-dbus-login1                                      \
+               $(srcdir)/org.freedesktop.login1.xml
+
 wayland/%-protocol.c : $(top_builddir)/protocol/%.xml
        mkdir -p wayland
        $(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
diff --git a/src/core/main.c b/src/core/main.c
index c4bdeee..2103d88 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -190,6 +190,7 @@ static gboolean  opt_replace_wm;
 static gboolean  opt_disable_sm;
 static gboolean  opt_sync;
 static gboolean  opt_wayland;
+static gboolean  opt_display_server;
 
 static GOptionEntry meta_options[] = {
   {
@@ -233,6 +234,11 @@ static GOptionEntry meta_options[] = {
     N_("Run as a wayland compositor"),
     NULL
   },
+  {
+    "display-server", 0, 0, G_OPTION_ARG_NONE,
+    &opt_display_server,
+    N_("Run as a full display server, rather than nested")
+  },
   {NULL}
 };
 
@@ -400,8 +406,7 @@ meta_init (void)
   if (g_getenv ("MUTTER_DEBUG"))
     meta_set_debugging (TRUE);
 
-  /* We consider running from mutter-launch equivalent to running from bare metal. */
-  if (getenv ("WESTON_LAUNCHER_SOCK"))
+  if (opt_display_server)
     clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL);
 
   meta_set_is_wayland_compositor (opt_wayland);
@@ -497,6 +502,32 @@ meta_register_with_session (void)
 }
 
 /**
+ * meta_activate_session:
+ *
+ * Tells mutter to activate the session. When mutter is a
+ * Wayland compositor, this tells logind to switch over to
+ * the new session.
+ */
+gboolean
+meta_activate_session (void)
+{
+  if (meta_is_wayland_compositor ())
+    {
+      MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
+      GError *error = NULL;
+
+      if (!meta_wayland_compositor_activate_session (compositor, &error))
+        {
+          g_warning ("Could not activate session: %s\n", error->message);
+          g_error_free (error);
+          return FALSE;
+        }
+    }
+
+  return TRUE;
+}
+
+/**
  * meta_run: (skip)
  *
  * Runs mutter. Call this after completing initialization that doesn't require
diff --git a/src/meta/main.h b/src/meta/main.h
index 35eb73d..9a74809 100644
--- a/src/meta/main.h
+++ b/src/meta/main.h
@@ -28,6 +28,7 @@ GOptionContext *meta_get_option_context     (void);
 void            meta_init                   (void);
 int             meta_run                    (void);
 void            meta_register_with_session  (void);
+gboolean        meta_activate_session       (void);
 gboolean        meta_get_replace_current_wm (void);  /* Actually defined in util.c */
 
 void            meta_set_wm_name              (const char *wm_name);
diff --git a/src/mutter-wayland.desktop.in b/src/mutter-wayland.desktop.in
index ebf1447..3bf5f23 100644
--- a/src/mutter-wayland.desktop.in
+++ b/src/mutter-wayland.desktop.in
@@ -1,7 +1,7 @@
 [Desktop Entry]
 Type=Application
 _Name=Mutter (wayland compositor)
-Exec=mutter-launch -- mutter --wayland
+Exec=mutter --wayland --display-server
 NoDisplay=true
 # name of loadable control center module
 X-GNOME-WMSettingsModule=metacity
diff --git a/src/org.freedesktop.login1.xml b/src/org.freedesktop.login1.xml
new file mode 100644
index 0000000..9aad8ca
--- /dev/null
+++ b/src/org.freedesktop.login1.xml
@@ -0,0 +1,42 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd";>
+<node>
+  <interface name="org.freedesktop.login1.Session">
+    <property name="Active" type="b" access="read" />
+
+    <method name="Activate">
+    </method>
+    <method name="TakeControl">
+      <arg name="force" type="b"/>
+    </method>
+    <method name="TakeDevice">
+      <annotation name="org.gtk.GDBus.C.UnixFD" value="true"/>
+      <arg name="major" type="u" direction="in"/>
+      <arg name="minor" type="u" direction="in"/>
+      <arg name="fd" type="h" direction="out"/>
+      <arg name="paused" type="b" direction="out"/>
+    </method>
+    <method name="ReleaseDevice">
+      <arg name="major" type="u"/>
+      <arg name="minor" type="u"/>
+    </method>
+    <method name="PauseDeviceComplete">
+      <arg name="major" type="u"/>
+      <arg name="minor" type="u"/>
+    </method>
+    <signal name="PauseDevice">
+      <arg name="major" type="u"/>
+      <arg name="minor" type="u"/>
+      <arg name="type" type="s"/>
+    </signal>
+    <signal name="ResumeDevice">
+      <arg name="major" type="u"/>
+      <arg name="minor" type="u"/>
+      <arg name="fd" type="h"/>
+    </signal>
+
+    <method name="SwitchTo">
+      <arg name="vt" type="u"/>
+    </method>
+  </interface>
+</node>
diff --git a/src/wayland/meta-login1.c b/src/wayland/meta-login1.c
new file mode 100644
index 0000000..6fd0dc0
--- /dev/null
+++ b/src/wayland/meta-login1.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "meta-login1.h"
+
+#include "meta-dbus-login1.h"
+
+#include <gio/gunixfdlist.h>
+
+#include <clutter/clutter.h>
+#include <clutter/evdev/clutter-evdev.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+struct _MetaLogin1
+{
+  Login1Session *session_proxy;
+};
+
+static Login1Session *
+get_session_proxy (GCancellable *cancellable)
+{
+  return login1_session_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+                                                G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+                                                "org.freedesktop.login1",
+                                                "/org/freedesktop/login1/session/self",
+                                                cancellable, NULL);
+}
+
+static void
+session_enter (void)
+{
+  ClutterBackend *backend;
+  CoglContext *cogl_context;
+  CoglDisplay *cogl_display;
+
+  backend = clutter_get_default_backend ();
+  cogl_context = clutter_backend_get_cogl_context (backend);
+  cogl_display = cogl_context_get_display (cogl_context);
+  cogl_kms_display_queue_modes_reset (cogl_display);
+
+  clutter_evdev_reclaim_devices ();
+}
+
+static void
+session_leave (void)
+{
+  clutter_evdev_release_devices ();
+}
+
+static void
+sync_active (MetaLogin1 *self)
+{
+  gboolean active = login1_session_get_active (LOGIN1_SESSION (self->session_proxy));
+
+  if (active)
+    session_enter ();
+  else
+    session_leave ();
+}
+
+static void
+on_active_changed (Login1Session *session,
+                   GParamSpec    *pspec,
+                   gpointer       user_data)
+{
+  MetaLogin1 *self = user_data;
+  sync_active (self);
+}
+
+static gboolean
+meta_login1_take_device (MetaLogin1    *self,
+                         int            dev_major,
+                         int            dev_minor,
+                         int           *out_fd,
+                         GCancellable  *cancellable,
+                         GError       **error)
+{
+  gboolean ret = FALSE;
+  GVariant *fd_variant = NULL;
+  int fd = -1;
+  GUnixFDList *fd_list;
+
+  if (!login1_session_call_take_device_sync (self->session_proxy,
+                                             dev_major,
+                                             dev_minor,
+                                             NULL,
+                                             &fd_variant,
+                                             NULL, /* paused */
+                                             &fd_list,
+                                             cancellable,
+                                             error))
+    goto out;
+
+  fd = g_unix_fd_list_get (fd_list, g_variant_get_handle (fd_variant), error);
+  if (fd == -1)
+    goto out;
+
+  *out_fd = fd;
+  ret = TRUE;
+
+ out:
+  if (fd_variant)
+    g_variant_unref (fd_variant);
+  if (fd_list)
+    g_object_unref (fd_list);
+  return ret;
+}
+
+static gboolean
+get_device_info (const char *path,
+                 int        *out_major,
+                 int        *out_minor)
+{
+  gboolean ret = FALSE;
+  int r;
+  struct stat st;
+
+  r = stat (path, &st);
+  if (r < 0)
+    goto out;
+  if (!S_ISCHR (st.st_mode))
+    goto out;
+
+  *out_major = major (st.st_rdev);
+  *out_minor = minor (st.st_rdev);
+  ret = TRUE;
+
+ out:
+  return ret;
+}
+
+static int
+on_evdev_device_open (const char  *path,
+                     int          flags,
+                     gpointer     user_data,
+                     GError     **error)
+{
+  MetaLogin1 *self = user_data;
+  int fd;
+  int major, minor;
+
+  if (!get_device_info (path, &major, &minor))
+    {
+      g_set_error (error,
+                   G_IO_ERROR,
+                   G_IO_ERROR_NOT_FOUND,
+                   "Could not get device info for path: %s", path);
+      return -1;
+    }
+
+  if (!meta_login1_take_device (self, major, minor, &fd, NULL, error))
+    return -1;
+
+  return fd;
+}
+
+MetaLogin1 *
+meta_login1_new (void)
+{
+  MetaLogin1 *self;
+  Login1Session *session_proxy;
+  GError *error = NULL;
+
+  session_proxy = get_session_proxy (NULL);
+  if (!login1_session_call_take_control_sync (session_proxy, FALSE, NULL, &error))
+    {
+      g_warning ("Could not take control: %s", error->message);
+      g_error_free (error);
+      return NULL;
+    }
+
+  self = g_slice_new0 (MetaLogin1);
+  self->session_proxy = session_proxy;
+
+  clutter_evdev_set_open_callback (on_evdev_device_open, self);
+
+  g_signal_connect (self->session_proxy, "notify::active", G_CALLBACK (on_active_changed), self);
+
+  return self;
+}
+
+void
+meta_login1_free (MetaLogin1 *self)
+{
+  g_object_unref (self->session_proxy);
+  g_slice_free (MetaLogin1, self);
+}
+
+gboolean
+meta_login1_activate_session (MetaLogin1  *self,
+                              GError     **error)
+{
+  if (!login1_session_call_activate_sync (self->session_proxy, NULL, error))
+    return FALSE;
+
+  sync_active (self);
+  return TRUE;
+}
+
+gboolean
+meta_login1_activate_vt (MetaLogin1  *self,
+                         int          vt,
+                         GError     **error)
+{
+  return login1_session_call_switch_to_sync (self->session_proxy, vt, NULL, error);
+}
diff --git a/src/wayland/meta-login1.h b/src/wayland/meta-login1.h
new file mode 100644
index 0000000..0fed205
--- /dev/null
+++ b/src/wayland/meta-login1.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef META_LOGIN1_H
+#define META_LOGIN1_H
+
+#include <glib-object.h>
+
+typedef struct _MetaLogin1 MetaLogin1;
+
+MetaLogin1 *meta_login1_new              (void);
+void        meta_login1_free             (MetaLogin1  *self);
+gboolean    meta_login1_activate_session (MetaLogin1  *self,
+                                          GError     **error);
+gboolean    meta_login1_activate_vt      (MetaLogin1  *self,
+                                          int          vt,
+                                          GError     **error);
+
+#endif
diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h
index 69de1b8..201f3ac 100644
--- a/src/wayland/meta-wayland-private.h
+++ b/src/wayland/meta-wayland-private.h
@@ -28,7 +28,7 @@
 #include <cairo.h>
 
 #include "window-private.h"
-#include "meta-weston-launch.h"
+#include "meta-login1.h"
 #include <meta/meta-cursor-tracker.h>
 
 #include "meta-wayland-types.h"
@@ -86,7 +86,7 @@ struct _MetaWaylandCompositor
 
   MetaXWaylandManager xwayland_manager;
 
-  MetaLauncher *launcher;
+  MetaLogin1 *login1;
 
   MetaWaylandSeat *seat;
 };
@@ -116,5 +116,7 @@ void                    meta_wayland_compositor_paint_finished  (MetaWaylandComp
 gboolean                meta_wayland_compositor_activate_vt     (MetaWaylandCompositor  *compositor,
                                                                  int                     vt,
                                                                  GError                **error);
+gboolean                meta_wayland_compositor_activate_session (MetaWaylandCompositor  *compositor,
+                                                                  GError                **error);
 
 #endif /* META_WAYLAND_PRIVATE_H */
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index 3a32dee..4edf5d5 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -52,7 +52,7 @@
 #include <meta/main.h>
 #include "frame.h"
 #include "meta-idle-monitor-private.h"
-#include "meta-weston-launch.h"
+#include "meta-login1.h"
 #include "monitor-private.h"
 
 static MetaWaylandCompositor _meta_wayland_compositor;
@@ -643,25 +643,16 @@ meta_wayland_init (void)
 
   clutter_wayland_set_compositor_display (compositor->wayland_display);
 
+  /* If we're running on bare metal, we're a display server,
+   * so start talking to logind. */
 #if defined(CLUTTER_WINDOWING_EGL)
   if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
-    compositor->launcher = meta_launcher_new ();
+    compositor->login1 = meta_login1_new ();
 #endif
 
   if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
     g_error ("Failed to initialize Clutter");
 
-#if defined(CLUTTER_WINDOWING_EGL)
-  if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
-    {
-      ClutterBackend *backend = clutter_get_default_backend ();
-      CoglContext *cogl_context = clutter_backend_get_cogl_context (backend);
-      CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (cogl_context));
-      int drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
-      meta_launcher_set_drm_fd (compositor->launcher, drm_fd, NULL);
-    }
-#endif
-
   meta_monitor_manager_initialize ();
   monitors = meta_monitor_manager_get ();
   g_signal_connect (monitors, "monitors-changed",
@@ -713,8 +704,7 @@ meta_wayland_finalize (void)
 
   meta_xwayland_stop (&compositor->xwayland_manager);
 
-  if (compositor->launcher)
-    meta_launcher_free (compositor->launcher);
+  meta_login1_free (compositor->login1);
 }
 
 gboolean
@@ -722,13 +712,28 @@ meta_wayland_compositor_activate_vt (MetaWaylandCompositor  *compositor,
                                      int                     vt,
                                      GError                **error)
 {
-  if (compositor->launcher)
+  if (compositor->login1)
+    {
+      return meta_login1_activate_vt (compositor->login1, vt, error);
+    }
+  else
+    {
+      g_debug ("Ignoring VT switch keybinding, not running as display server");
+      return TRUE;
+    }
+}
+
+gboolean
+meta_wayland_compositor_activate_session (MetaWaylandCompositor  *compositor,
+                                          GError                **error)
+{
+  if (compositor->login1)
     {
-      return meta_launcher_activate_vt (compositor->launcher, vt, error);
+      return meta_login1_activate_session (compositor->login1, error);
     }
   else
     {
-      g_debug ("Ignoring VT switch keybinding, not running as VT manager");
+      g_debug ("Ignoring activate_session, not running as display server");
       return TRUE;
     }
 }


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