[mutter] launcher: Replace mutter-launch with logind integration



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

    launcher: 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 requires systemd v210, at least.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=724604

 .gitignore                          |    2 +-
 configure.ac                        |    3 +-
 src/Makefile.am                     |   25 +-
 src/backends/native/dbus-utils.c    |  107 ++++++
 src/backends/native/dbus-utils.h    |   32 ++
 src/backends/native/meta-launcher.c |  433 ++++++++++-----------
 src/backends/native/weston-launch.c |  711 -----------------------------------
 src/backends/native/weston-launch.h |   68 ----
 src/mutter-wayland.desktop.in       |    2 +-
 src/org.freedesktop.login1.xml      |   44 +++
 10 files changed, 406 insertions(+), 1021 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 1b238e1..446c092 100644
--- a/.gitignore
+++ b/.gitignore
@@ -48,7 +48,6 @@ po/*.pot
 50-metacity-key.xml
 libmutter.pc
 mutter
-mutter-launch
 org.gnome.mutter.gschema.valid
 org.gnome.mutter.gschema.xml
 org.gnome.mutter.wayland.gschema.valid
@@ -78,6 +77,7 @@ src/mutter-marshal.[ch]
 src/stamp-mutter-marshal.h
 src/meta-dbus-display-config.[ch]
 src/meta-dbus-idle-monitor.[ch]
+src/meta-dbus-login1.[ch]
 src/gtk-shell-protocol.c
 src/gtk-shell-server-protocol.h
 src/xdg-shell-protocol.c
diff --git a/configure.ac b/configure.ac
index 7a8d1b9..c8c92f3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -127,7 +127,6 @@ AM_GLIB_GNU_GETTEXT
 ## here we get the flags we'll actually use
 # GRegex requires Glib-2.14.0
 PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0)
-PKG_CHECK_MODULES(MUTTER_LAUNCH, libdrm libsystemd-login)
 
 # Unconditionally use this dir to avoid a circular dep with gnomecc
 GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
@@ -200,7 +199,7 @@ AS_IF([test "x$WAYLAND_SCANNER" = "xno"],
 AC_SUBST([WAYLAND_SCANNER])
 AC_SUBST(XWAYLAND_PATH)
 
-MUTTER_PC_MODULES="$MUTTER_PC_MODULES clutter-wayland-1.0 clutter-wayland-compositor-1.0 clutter-egl-1.0 
wayland-server >= 1.4.93 libdrm"
+MUTTER_PC_MODULES="$MUTTER_PC_MODULES clutter-wayland-1.0 clutter-wayland-compositor-1.0 clutter-egl-1.0 
wayland-server >= 1.4.93 libdrm libsystemd"
 PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
 
 PKG_CHECK_EXISTS([xi >= 1.6.99.1],
diff --git a/src/Makefile.am b/src/Makefile.am
index 5e6b710..c71697f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -35,6 +35,7 @@ INCLUDES=                                                             \
 mutter_built_sources = \
        $(dbus_idle_built_sources)              \
        $(dbus_display_config_built_sources)    \
+       $(dbus_login1_built_sources)            \
        mutter-enum-types.h                     \
        mutter-enum-types.c                     \
        gtk-shell-protocol.c                    \
@@ -80,6 +81,8 @@ libmutter_la_SOURCES =                                \
        backends/native/meta-monitor-manager-kms.h      \
        backends/native/meta-launcher.c                 \
        backends/native/meta-launcher.h                 \
+       backends/native/dbus-utils.c                    \
+       backends/native/dbus-utils.h                    \
        backends/x11/meta-backend-x11.c                 \
        backends/x11/meta-backend-x11.h                 \
        backends/x11/meta-cursor-renderer-x11.c         \
@@ -293,19 +296,6 @@ bin_PROGRAMS=mutter
 mutter_SOURCES = core/mutter.c
 mutter_LDADD = $(MUTTER_LIBS) libmutter.la
 
-bin_PROGRAMS+=mutter-launch
-
-mutter_launch_SOURCES =                        \
-       backends/native/weston-launch.c         \
-       backends/native/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)
 
@@ -442,6 +432,15 @@ $(dbus_idle_built_sources) : Makefile.am org.gnome.Mutter.IdleMonitor.xml
                --c-generate-object-manager                                             \
                $(srcdir)/org.gnome.Mutter.IdleMonitor.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
+
 %-protocol.c : $(srcdir)/wayland/protocol/%.xml
        $(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
 %-server-protocol.h : $(srcdir)/wayland/protocol/%.xml
diff --git a/src/backends/native/dbus-utils.c b/src/backends/native/dbus-utils.c
new file mode 100644
index 0000000..6a63b92
--- /dev/null
+++ b/src/backends/native/dbus-utils.c
@@ -0,0 +1,107 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/*
+ * Copyright (C) 2014 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.
+ *
+ * Written by:
+ *     Jasper St. Pierre <jstpierre mecheye net>
+ */
+
+#include "config.h"
+
+#include "dbus-utils.h"
+
+#include <glib.h>
+
+/* Stolen from tp_escape_as_identifier, from tp-glib,
+ * which follows the same escaping convention as systemd.
+ */
+static inline gboolean
+_esc_ident_bad (gchar c, gboolean is_first)
+{
+  return ((c < 'a' || c > 'z') &&
+          (c < 'A' || c > 'Z') &&
+          (c < '0' || c > '9' || is_first));
+}
+
+static gchar *
+escape_dbus_component (const gchar *name)
+{
+  gboolean bad = FALSE;
+  size_t len = 0;
+  GString *op;
+  const gchar *ptr, *first_ok;
+
+  g_return_val_if_fail (name != NULL, NULL);
+
+  /* fast path for empty name */
+  if (name[0] == '\0')
+    return g_strdup ("_");
+
+  for (ptr = name; *ptr; ptr++)
+    {
+      if (_esc_ident_bad (*ptr, ptr == name))
+        {
+          bad = TRUE;
+          len += 3;
+        }
+      else
+        len++;
+    }
+
+  /* fast path if it's clean */
+  if (!bad)
+    return g_strdup (name);
+
+  /* If strictly less than ptr, first_ok is the first uncopied safe character.
+   */
+  first_ok = name;
+  op = g_string_sized_new (len);
+  for (ptr = name; *ptr; ptr++)
+    {
+      if (_esc_ident_bad (*ptr, ptr == name))
+        {
+          /* copy preceding safe characters if any */
+          if (first_ok < ptr)
+            {
+              g_string_append_len (op, first_ok, ptr - first_ok);
+            }
+          /* escape the unsafe character */
+          g_string_append_printf (op, "_%02x", (unsigned char)(*ptr));
+          /* restart after it */
+          first_ok = ptr + 1;
+        }
+    }
+  /* copy trailing safe characters if any */
+  if (first_ok < ptr)
+    {
+      g_string_append_len (op, first_ok, ptr - first_ok);
+    }
+  return g_string_free (op, FALSE);
+}
+
+char *
+get_escaped_dbus_path (const char *prefix,
+                       const char *component)
+{
+  char *escaped_component = escape_dbus_component (component);
+  char *path = g_strconcat (prefix, "/", escaped_component, NULL);
+
+  g_free (escaped_component);
+  return path;
+}
diff --git a/src/backends/native/dbus-utils.h b/src/backends/native/dbus-utils.h
new file mode 100644
index 0000000..ee56c45
--- /dev/null
+++ b/src/backends/native/dbus-utils.h
@@ -0,0 +1,32 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/*
+ * Copyright (C) 2014 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.
+ *
+ * Written by:
+ *     Jasper St. Pierre <jstpierre mecheye net>
+ */
+
+#ifndef DBUS_UTILS_H
+#define DBUS_UTILS_H
+
+char *
+get_escaped_dbus_path (const char *prefix,
+                       const char *component);
+
+#endif /* DBUS_UTILS_H */
diff --git a/src/backends/native/meta-launcher.c b/src/backends/native/meta-launcher.c
index 6675508..7519194 100644
--- a/src/backends/native/meta-launcher.c
+++ b/src/backends/native/meta-launcher.c
@@ -20,9 +20,8 @@
 #include "config.h"
 
 #include "meta-launcher.h"
-#include "weston-launch.h"
 
-#include <gio/gunixfdmessage.h>
+#include <gio/gunixfdlist.h>
 
 #include <clutter/clutter.h>
 #include <clutter/egl/clutter-egl.h>
@@ -30,10 +29,17 @@
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <malloc.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
+
+#include <systemd/sd-login.h>
+
+#include "dbus-utils.h"
+#include "meta-dbus-login1.h"
 
 #include "wayland/meta-wayland-private.h"
 #include "backends/meta-backend.h"
@@ -41,153 +47,44 @@
 
 struct _MetaLauncher
 {
-  GSocket *weston_launch;
-  GSource *weston_launch_source;
+  Login1Session *session_proxy;
+  Login1Seat *seat_proxy;
 
-  gboolean vt_switched;
+  gboolean session_active;
 };
 
 /* AAA BBB CCC */
 
-static void handle_request_vt_switch (MetaLauncher *self);
-
-static gboolean
-request_vt_switch_idle (gpointer user_data)
+static Login1Session *
+get_session_proxy (GCancellable *cancellable)
 {
-  handle_request_vt_switch (user_data);
+  char *proxy_path;
+  char *session_id;
+  Login1Session *session_proxy;
 
-  return FALSE;
-}
+  if (sd_pid_get_session (getpid (), &session_id) < 0)
+    return NULL;
 
-static gboolean
-send_message_to_wl (MetaLauncher           *self,
-                    void                   *message,
-                    gsize                   size,
-                    GSocketControlMessage  *out_cmsg,
-                    GSocketControlMessage **in_cmsg,
-                    GError                **error)
-{
-  struct weston_launcher_reply reply;
-  GInputVector in_iov = { &reply, sizeof (reply) };
-  GOutputVector out_iov = { message, size };
-  GSocketControlMessage *out_all_cmsg[2];
-  GSocketControlMessage **in_all_cmsg;
-  int flags = 0;
-  int i;
-
-  out_all_cmsg[0] = out_cmsg;
-  out_all_cmsg[1] = NULL;
-  if (g_socket_send_message (self->weston_launch, NULL,
-                             &out_iov, 1,
-                             out_all_cmsg, -1,
-                             flags, NULL, error) != (gssize)size)
-    return FALSE;
-
-  if (g_socket_receive_message (self->weston_launch, NULL,
-                                &in_iov, 1,
-                                &in_all_cmsg, NULL,
-                                &flags, NULL, error) != sizeof (reply))
-    return FALSE;
+  proxy_path = get_escaped_dbus_path ("/org/freedesktop/login1/session", session_id);
 
-  while (reply.header.opcode != ((struct weston_launcher_message*)message)->opcode)
-    {
-      guint id;
-
-      /* There were events queued */
-      g_assert ((reply.header.opcode & WESTON_LAUNCHER_EVENT) == WESTON_LAUNCHER_EVENT);
-
-      /* This can never happen, because the only time mutter-launch can queue
-         this event is after confirming a VT switch, and we don't make requests
-         during that time.
-
-         Note that getting this event would be really bad, because we would be
-         in the wrong loop/context.
-      */
-      g_assert (reply.header.opcode != WESTON_LAUNCHER_SERVER_VT_ENTER);
-
-      switch (reply.header.opcode)
-        {
-        case WESTON_LAUNCHER_SERVER_REQUEST_VT_SWITCH:
-          id = g_idle_add (request_vt_switch_idle, self);
-          g_source_set_name_by_id (id, "[mutter] request_vt_switch_idle");
-          break;
-
-        default:
-          g_assert_not_reached ();
-        }
-
-      if (g_socket_receive_message (self->weston_launch, NULL,
-                                    &in_iov, 1,
-                                    NULL, NULL,
-                                    &flags, NULL, error) != sizeof (reply))
-        return FALSE;
-    }
+  session_proxy = login1_session_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+                                                         G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+                                                         "org.freedesktop.login1",
+                                                         proxy_path,
+                                                         cancellable, NULL);
+  free (proxy_path);
 
-  if (reply.ret != 0)
-    {
-      if (reply.ret == -1)
-        g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                     "Got failure from weston-launch");
-      else
-        g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-reply.ret),
-                     "Got failure from weston-launch: %s", strerror (-reply.ret));
-
-      for (i = 0; in_all_cmsg && in_all_cmsg[i]; i++)
-        g_object_unref (in_all_cmsg[i]);
-      g_free (in_all_cmsg);
-
-      return FALSE;
-    }
-
-  if (in_all_cmsg && in_all_cmsg[0])
-    {
-      for (i = 1; in_all_cmsg[i]; i++)
-        g_object_unref (in_all_cmsg[i]);
-      *in_cmsg = in_all_cmsg[0];
-    }
-
-  g_free (in_all_cmsg);
-  return TRUE;
+  return session_proxy;
 }
 
-static int
-meta_launcher_open_device (MetaLauncher  *self,
-                           const char    *name,
-                           int            flags,
-                           GError       **error)
+static Login1Seat *
+get_seat_proxy (GCancellable *cancellable)
 {
-  struct weston_launcher_open *message;
-  GSocketControlMessage *cmsg;
-  gboolean ok;
-  gsize size;
-  int *fds, n_fd;
-  int ret;
-
-  size = sizeof (struct weston_launcher_open) + strlen (name) + 1;
-  message = g_malloc (size);
-  message->header.opcode = WESTON_LAUNCHER_OPEN;
-  message->flags = flags;
-  strcpy (message->path, name);
-  message->path[strlen(name)] = 0;
-
-  ok = send_message_to_wl (self, message, size, NULL, &cmsg, error);
-
-  if (ok)
-    {
-      g_assert (G_IS_UNIX_FD_MESSAGE (cmsg));
-
-      fds = g_unix_fd_message_steal_fds (G_UNIX_FD_MESSAGE (cmsg), &n_fd);
-      g_assert (n_fd == 1);
-
-      ret = fds[0];
-      g_free (fds);
-      g_object_unref (cmsg);
-    }
-  else
-    ret = -1;
-
-  g_free (message);
-  return ret;
+  return login1_seat_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+                                             G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+                                             "org.freedesktop.login1",
+                                             "/org/freedesktop/login1/seat/self",
+                                             cancellable, NULL);
 }
 
 /* QQQ RRR SSS */
@@ -228,107 +125,190 @@ session_pause (void)
   clutter_egl_freeze_master_clock ();
 }
 
+static gboolean
+take_device (Login1Session *session_proxy,
+             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 (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_from_path (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 gboolean
+get_device_info_from_fd (int  fd,
+                         int *out_major,
+                         int *out_minor)
+{
+  gboolean ret = FALSE;
+  int r;
+  struct stat st;
+
+  r = fstat (fd, &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)
 {
-  MetaLauncher *launcher = user_data;
+  MetaLauncher *self = user_data;
+  int fd;
+  int major, minor;
+
+  if (!get_device_info_from_path (path, &major, &minor))
+    {
+      g_set_error (error,
+                   G_IO_ERROR,
+                   G_IO_ERROR_NOT_FOUND,
+                   "Could not get device info for path %s: %m", path);
+      return -1;
+    }
+
+  if (!take_device (self->session_proxy, major, minor, &fd, NULL, error))
+    return -1;
 
-  return meta_launcher_open_device (launcher, path, flags, error);
+  return fd;
 }
 
 static void
 on_evdev_device_close (int      fd,
                        gpointer user_data)
 {
-  close (fd);
+  MetaLauncher *self = user_data;
+  int major, minor;
+  GError *error = NULL;
+
+  if (!get_device_info_from_fd (fd, &major, &minor))
+    {
+      g_warning ("Could not get device info for fd %d: %m", fd);
+      return;
+    }
+
+  if (!login1_session_call_release_device_sync (self->session_proxy,
+                                                major, minor,
+                                                NULL, &error))
+    {
+      g_warning ("Could not release device %d,%d: %s", major, minor, error->message);
+    }
 }
 
 /* TTT UUU VVV */
 
 static void
-handle_vt_enter (MetaLauncher *launcher)
+sync_active (MetaLauncher *self)
 {
-  g_assert (launcher->vt_switched);
-  launcher->vt_switched = FALSE;
+  gboolean active = login1_session_get_active (LOGIN1_SESSION (self->session_proxy));
+
+  if (active == self->session_active)
+    return;
 
-  session_unpause ();
+  self->session_active = active;
+
+  if (active)
+    session_unpause ();
+  else
+    session_pause ();
 }
 
 static void
-handle_request_vt_switch (MetaLauncher *launcher)
+on_active_changed (Login1Session *session,
+                   GParamSpec    *pspec,
+                   gpointer       user_data)
 {
-  struct weston_launcher_message message;
-  GError *error;
-  gboolean ok;
-
-  session_pause ();
-
-  message.opcode = WESTON_LAUNCHER_CONFIRM_VT_SWITCH;
-
-  error = NULL;
-  ok = send_message_to_wl (launcher, &message, sizeof (message), NULL, NULL, &error);
-  if (!ok) {
-    g_warning ("Failed to acknowledge VT switch: %s", error->message);
-    g_error_free (error);
-    return;
-  }
-
-  g_assert (!launcher->vt_switched);
-  launcher->vt_switched = TRUE;
-
-  session_unpause ();
+  MetaLauncher *self = user_data;
+  sync_active (self);
 }
 
 static gboolean
-on_socket_readable (GSocket      *socket,
-                    GIOCondition  condition,
-                    gpointer      user_data)
+get_kms_fd (Login1Session *session_proxy,
+            int *fd_out)
 {
-  MetaLauncher *launcher = user_data;
-  struct weston_launcher_event event;
-  gssize read;
-  GError *error;
-
-  if ((condition & G_IO_IN) == 0)
-    return TRUE;
+  int major, minor;
+  int fd;
+  GError *error = NULL;
 
-  error = NULL;
-  read = g_socket_receive (socket, (char*)&event, sizeof(event), NULL, &error);
-  if (read < (gssize)sizeof(event))
+  /* XXX -- use udev to find the DRM master device */
+  if (!get_device_info_from_path ("/dev/dri/card0", &major, &minor))
     {
-      g_warning ("Error reading from weston-launcher socket: %s", error->message);
-      g_error_free (error);
-      return TRUE;
+      g_warning ("Could not stat /dev/dri/card0: %m");
+      return FALSE;
     }
 
-  switch (event.header.opcode)
+  if (!take_device (session_proxy, major, minor, &fd, NULL, &error))
     {
-    case WESTON_LAUNCHER_SERVER_REQUEST_VT_SWITCH:
-      handle_request_vt_switch (launcher);
-      break;
-
-    case WESTON_LAUNCHER_SERVER_VT_ENTER:
-      handle_vt_enter (launcher);
-      break;
+      g_warning ("Could not open DRM device: %s\n", error->message);
+      g_error_free (error);
+      return FALSE;
     }
 
-  return TRUE;
-}
-
-static int
-env_get_fd (const char *env)
-{
-  const char *value;
-
-  value = g_getenv (env);
+  *fd_out = fd;
 
-  if (value == NULL)
-    return -1;
-  else
-    return g_ascii_strtoll (value, NULL, 10);
+  return TRUE;
 }
 
 /* XXX YYY ZZZ */
@@ -336,47 +316,55 @@ env_get_fd (const char *env)
 MetaLauncher *
 meta_launcher_new (void)
 {
-  MetaLauncher *self = g_slice_new0 (MetaLauncher);
+  MetaLauncher *self;
+  Login1Session *session_proxy;
   GError *error = NULL;
-  int launch_fd;
   int kms_fd;
 
-  launch_fd = env_get_fd ("WESTON_LAUNCHER_SOCK");
-  if (launch_fd < 0)
-    g_error ("Invalid mutter-launch socket");
+  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->weston_launch = g_socket_new_from_fd (launch_fd, NULL);
+  if (!get_kms_fd (session_proxy, &kms_fd))
+    return NULL;
 
-  self->weston_launch_source = g_socket_create_source (self->weston_launch, G_IO_IN, NULL);
-  g_source_set_callback (self->weston_launch_source, (GSourceFunc)on_socket_readable, self, NULL);
-  g_source_attach (self->weston_launch_source, NULL);
-  g_source_unref (self->weston_launch_source);
+  self = g_slice_new0 (MetaLauncher);
+  self->session_proxy = session_proxy;
+  self->seat_proxy = get_seat_proxy (NULL);
 
-  kms_fd = meta_launcher_open_device (self, "/dev/dri/card0", O_RDWR, &error);
-  if (error)
-    g_error ("Failed to open /dev/dri/card0: %s", error->message);
+  self->session_active = TRUE;
 
   clutter_egl_set_kms_fd (kms_fd);
   clutter_evdev_set_device_callbacks (on_evdev_device_open,
                                       on_evdev_device_close,
                                       self);
 
+  g_signal_connect (self->session_proxy, "notify::active", G_CALLBACK (on_active_changed), self);
+
   return self;
 }
 
 void
-meta_launcher_free (MetaLauncher *launcher)
+meta_launcher_free (MetaLauncher *self)
 {
-  g_source_destroy (launcher->weston_launch_source);
-  g_object_unref (launcher->weston_launch);
-  g_slice_free (MetaLauncher, launcher);
+  g_object_unref (self->seat_proxy);
+  g_object_unref (self->session_proxy);
+  g_slice_free (MetaLauncher, self);
 }
 
 gboolean
 meta_launcher_activate_session (MetaLauncher  *launcher,
                                 GError       **error)
 {
-  return meta_launcher_activate_vt (launcher, -1, error);
+  if (!login1_session_call_activate_sync (launcher->session_proxy, NULL, error))
+    return FALSE;
+
+  sync_active (launcher);
+  return TRUE;
 }
 
 gboolean
@@ -384,10 +372,5 @@ meta_launcher_activate_vt (MetaLauncher  *launcher,
                            signed char    vt,
                            GError       **error)
 {
-  struct weston_launcher_activate_vt message;
-
-  message.header.opcode = WESTON_LAUNCHER_ACTIVATE_VT;
-  message.vt = vt;
-
-  return send_message_to_wl (launcher, &message, sizeof (message), NULL, NULL, error);
+  return login1_seat_call_switch_to_sync (launcher->seat_proxy, vt, NULL, error);
 }
diff --git a/src/mutter-wayland.desktop.in b/src/mutter-wayland.desktop.in
index fb51a17..8502089 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 --display-server
+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..924e397
--- /dev/null
+++ b/src/org.freedesktop.login1.xml
@@ -0,0 +1,44 @@
+<!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>
+  </interface>
+
+  <interface name="org.freedesktop.login1.Seat">
+    <method name="SwitchTo">
+      <arg name="vt" type="u"/>
+    </method>
+  </interface>
+</node>


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