devilhorns pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=ed3a1f39587187c8acf305fd793f92218995c486

commit ed3a1f39587187c8acf305fd793f92218995c486
Author: Chris Michael <cpmich...@osg.samsung.com>
Date:   Thu Mar 31 12:34:32 2016 -0400

    elput: Add input manager interface and APIs to connect & disconnect
    
    This commit adds the start of the Elput Manager & Interface code. This
    will be used as an inteface to various backend methods of session &
    device control (ie: systemd, direct interface, etc). This will provide
    various abstractions for working with libinput when opening/closing
    input devices.
    
    Signed-off-by: Chris Michael <cpmich...@osg.samsung.com>
---
 src/Makefile_Elput.am         |   2 +
 src/lib/elput/Elput.h         |  36 ++++
 src/lib/elput/elput_logind.c  | 450 ++++++++++++++++++++++++++++++++++++++++++
 src/lib/elput/elput_manager.c |  39 ++++
 src/lib/elput/elput_private.h |  32 +++
 5 files changed, 559 insertions(+)

diff --git a/src/Makefile_Elput.am b/src/Makefile_Elput.am
index 851d4ee..3e1ed58 100644
--- a/src/Makefile_Elput.am
+++ b/src/Makefile_Elput.am
@@ -9,6 +9,8 @@ dist_installed_elputmainheaders_DATA = \
   lib/elput/Elput.h
 
 lib_elput_libelput_la_SOURCES = \
+lib/elput/elput_logind.c \
+lib/elput/elput_manager.c \
 lib/elput/elput.c \
 lib/elput/elput_private.h
 
diff --git a/src/lib/elput/Elput.h b/src/lib/elput/Elput.h
index 7c88e4b..e098b13 100644
--- a/src/lib/elput/Elput.h
+++ b/src/lib/elput/Elput.h
@@ -25,6 +25,9 @@
 
 # ifdef EFL_BETA_API_SUPPORT
 
+/* opaque structure to represent an input manager */
+typedef struct _Elput_Manager Elput_Manager;
+
 /**
  * @file
  * @brief Ecore functions for dealing with libinput
@@ -35,6 +38,7 @@
  * Elput provides a wrapper and functions for using libinput
  *
  * @li @ref Elput_Init_Group
+ * @li @ref Elput_Manager_Group
  *
  */
 
@@ -66,6 +70,38 @@ EAPI int elput_init(void);
  */
 EAPI int elput_shutdown(void);
 
+/**
+ * @defgroup Elput_Manager_Group
+ *
+ * Functions that deal with connecting, disconnecting, opening, closing
+ * of input devices.
+ *
+ */
+
+/**
+ * Create an input manager on the specified seat
+ *
+ * @param seat
+ * @param tty
+ * @param sync
+ *
+ * @return A Elput_Manager on success, NULL on failure
+ *
+ * @ingroup Elput_Manager_Group
+ * @since 1.18
+ */
+EAPI Elput_Manager *elput_manager_connect(const char *seat, unsigned int tty, 
Eina_Bool sync);
+
+/**
+ * Disconnect an input manager
+ *
+ * @param manager
+ *
+ * @ingroup Elput_Manager_Group
+ * @since 1.18
+ */
+EAPI void elput_manager_disconnect(Elput_Manager *manager);
+
 # endif
 
 # undef EAPI
diff --git a/src/lib/elput/elput_logind.c b/src/lib/elput/elput_logind.c
new file mode 100644
index 0000000..d649bf3
--- /dev/null
+++ b/src/lib/elput/elput_logind.c
@@ -0,0 +1,450 @@
+#include "elput_private.h"
+
+#ifdef HAVE_SYSTEMD
+
+static void
+_logind_device_pause_complete(Elput_Manager *em, uint32_t major, uint32_t 
minor)
+{
+   Eldbus_Proxy *proxy;
+   Eldbus_Message *msg;
+
+   proxy =
+     eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session");
+   if (!proxy)
+     {
+        ERR("Could not get proxy for session");
+        return;
+     }
+
+   msg = eldbus_proxy_method_call_new(proxy, "PauseDeviceComplete");
+   if (!msg)
+     {
+        ERR("Could not create method call for proxy");
+        goto end;
+     }
+
+   eldbus_message_arguments_append(msg, "uu", major, minor);
+
+   eldbus_proxy_send(proxy, msg, NULL, NULL, -1);
+
+end:
+   eldbus_message_unref(msg);
+   eldbus_proxy_unref(proxy);
+}
+
+static void
+_cb_session_removed(void *data, const Eldbus_Message *msg)
+{
+   Elput_Manager *em;
+   const char *errname, *errmsg;
+   const char *sid;
+
+   em = data;
+
+   if (eldbus_message_error_get(msg, &errname, &errmsg))
+     {
+        ERR("Eldbus Message Error: %s %s", errname, errmsg);
+        return;
+     }
+
+   if (eldbus_message_arguments_get(msg, "s", &sid))
+     {
+        if (!strcmp(sid, em->sid))
+          {
+             WRN("Logind session removed");
+             /* TODO: call manager restore function */
+          }
+     }
+}
+
+static void
+_cb_device_paused(void *data, const Eldbus_Message *msg)
+{
+   Elput_Manager *em;
+   const char *errname, *errmsg;
+   const char *type;
+   uint32_t maj, min;
+
+   em = data;
+
+   if (eldbus_message_error_get(msg, &errname, &errmsg))
+     {
+        ERR("Eldbus Message Error: %s %s", errname, errmsg);
+        return;
+     }
+
+   if (eldbus_message_arguments_get(msg, "uus", &maj, &min, &type))
+     {
+        if (!strcmp(type, "pause"))
+          _logind_device_pause_complete(em, maj, min);
+
+        /* TODO */
+        /* if ((em->sync) && (maj == DRM_MAJOR)) */
+        /*   _ecore_drm2_launcher_activate_send(em, EINA_FALSE); */
+     }
+}
+
+static void
+_cb_device_resumed(void *data, const Eldbus_Message *msg)
+{
+   Elput_Manager *em;
+   const char *errname, *errmsg;
+   uint32_t maj, min;
+   int fd;
+
+   em = data;
+
+   if (eldbus_message_error_get(msg, &errname, &errmsg))
+     {
+        ERR("Eldbus Message Error: %s %s", errname, errmsg);
+        return;
+     }
+
+   if (eldbus_message_arguments_get(msg, "uuh", &maj, &min, &fd))
+     {
+        /* TODO */
+        /* if ((em->sync) && (maj == DRM_MAJOR)) */
+        /*   _ecore_drm2_launcher_activate_send(em, EINA_TRUE); */
+     }
+}
+
+static void
+_cb_property_changed(void *data, Eldbus_Proxy *proxy EINA_UNUSED, void *event)
+{
+   Elput_Manager *em;
+   Eldbus_Proxy_Event_Property_Changed *ev;
+   Eina_Bool active = EINA_FALSE;
+
+   em = data;
+   ev = event;
+
+   DBG("DBus Property Changed: %s", ev->name);
+
+   if (!strcmp(ev->name, "Active"))
+     {
+        eina_value_get(ev->value, &active);
+        /* TODO */
+        /* if ((!em->sync) || (!active)) */
+        /*   _ecore_drm2_launcher_activate_send(em, active); */
+     }
+}
+
+static Eina_Bool
+_logind_session_vt_get(const char *sid, unsigned int *vt)
+{
+# ifdef HAVE_SYSTEMD_LOGIN_209
+   return (sd_session_get_vt(sid, vt) >= 0);
+# else
+   int ret = 0;
+   char *tty;
+
+   ret = sd_session_get_tty(sid, &tty);
+   if (ret < 0) return ret;
+
+   ret = sscanf(tty, "tty%u", vt);
+   free(tty);
+
+   if (ret != 1) return EINA_FALSE;
+   return EINA_TRUE;
+# endif
+}
+
+static Eina_Bool
+_logind_dbus_open(Eldbus_Connection **conn)
+{
+   if (!eldbus_init()) return EINA_FALSE;
+
+   *conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM);
+   if (!*conn) return EINA_FALSE;
+
+   return EINA_TRUE;
+}
+
+static void
+_logind_dbus_close(Eldbus_Connection *conn)
+{
+   if (conn) eldbus_connection_unref(conn);
+   eldbus_shutdown();
+}
+
+static Eina_Bool
+_logind_dbus_setup(Elput_Manager *em)
+{
+   Eldbus_Proxy *proxy;
+   int ret = 0;
+
+   ret = asprintf(&em->dbus.path,
+                  "/org/freedesktop/login1/session/%s", em->sid);
+   if (ret < 0) return EINA_FALSE;
+
+   em->dbus.obj =
+     eldbus_object_get(em->dbus.conn, "org.freedesktop.login1",
+                       em->dbus.path);
+   if (!em->dbus.obj)
+     {
+        ERR("Could not get dbus object");
+        goto obj_err;
+     }
+
+   proxy =
+     eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Manager");
+   if (!proxy)
+     {
+        ERR("Could not get dbus proxy");
+        goto proxy_err;
+     }
+
+   eldbus_proxy_signal_handler_add(proxy, "SessionRemoved",
+                                   _cb_session_removed, em);
+   eldbus_proxy_unref(proxy);
+
+   proxy =
+     eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session");
+   if (!proxy)
+     {
+        ERR("Could not get dbus proxy");
+        goto proxy_err;
+     }
+
+   eldbus_proxy_signal_handler_add(proxy, "PauseDevice",
+                                   _cb_device_paused, em);
+   eldbus_proxy_signal_handler_add(proxy, "ResumeDevice",
+                                   _cb_device_resumed, em);
+   eldbus_proxy_unref(proxy);
+
+   proxy =
+     eldbus_proxy_get(em->dbus.obj, "org.freedesktop.DBus.Properties");
+   if (!proxy)
+     {
+        ERR("Could not get dbus proxy");
+        goto proxy_err;
+     }
+
+   eldbus_proxy_properties_monitor(proxy, EINA_TRUE);
+   eldbus_proxy_event_callback_add(proxy, ELDBUS_PROXY_EVENT_PROPERTY_CHANGED,
+                                   _cb_property_changed, em);
+   eldbus_proxy_unref(proxy);
+
+   return EINA_TRUE;
+
+proxy_err:
+   eldbus_object_unref(em->dbus.obj);
+obj_err:
+   free(em->dbus.path);
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+_logind_control_take(Elput_Manager *em)
+{
+   Eldbus_Proxy *proxy;
+   Eldbus_Message *msg, *reply;
+   const char *errname, *errmsg;
+
+   proxy =
+     eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session");
+   if (!proxy)
+     {
+        ERR("Could not get proxy for session");
+        return EINA_FALSE;
+     }
+
+   msg = eldbus_proxy_method_call_new(proxy, "TakeControl");
+   if (!msg)
+     {
+        ERR("Could not create method call for proxy");
+        goto msg_err;
+     }
+
+   eldbus_message_arguments_append(msg, "b", EINA_FALSE);
+
+   reply = eldbus_proxy_send_and_block(proxy, msg, -1);
+   if (eldbus_message_error_get(reply, &errname, &errmsg))
+     {
+        ERR("Eldbus Message Error: %s %s", errname, errmsg);
+        goto msg_err;
+     }
+
+   eldbus_message_unref(reply);
+   eldbus_proxy_unref(proxy);
+
+   return EINA_TRUE;
+
+msg_err:
+   eldbus_proxy_unref(proxy);
+   return EINA_FALSE;
+}
+
+static void
+_logind_control_release(Elput_Manager *em)
+{
+   Eldbus_Proxy *proxy;
+   Eldbus_Message *msg;
+
+   proxy =
+     eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session");
+   if (!proxy)
+     {
+        ERR("Could not get proxy for session");
+        return;
+     }
+
+   msg = eldbus_proxy_method_call_new(proxy, "ReleaseControl");
+   if (!msg)
+     {
+        ERR("Could not create method call for proxy");
+        goto end;
+     }
+
+   eldbus_proxy_send(proxy, msg, NULL, NULL, -1);
+
+end:
+   eldbus_proxy_unref(proxy);
+}
+
+static Eina_Bool
+_logind_activate(Elput_Manager *em)
+{
+   Eldbus_Proxy *proxy;
+   Eldbus_Message *msg;
+
+   proxy =
+     eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session");
+   if (!proxy)
+     {
+        ERR("Could not get proxy for session");
+        return EINA_FALSE;
+     }
+
+   msg = eldbus_proxy_method_call_new(proxy, "Activate");
+   if (!msg)
+     {
+        ERR("Could not create method call for proxy");
+        goto msg_err;
+     }
+
+   eldbus_proxy_send(proxy, msg, NULL, NULL, -1);
+
+   eldbus_proxy_unref(proxy);
+
+   return EINA_TRUE;
+
+msg_err:
+   eldbus_proxy_unref(proxy);
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+_logind_connect(Elput_Manager **manager, const char *seat, unsigned int tty, 
Eina_Bool sync)
+{
+   Elput_Manager *em;
+   int ret = 0;
+   char *s;
+
+   em = calloc(1, sizeof(Elput_Manager));
+   if (!em) return EINA_FALSE;
+
+   em->interface = &_logind_interface;
+   em->sync = sync;
+   em->seat = eina_stringshare_add(seat);
+
+   ret = sd_pid_get_session(getpid(), &em->sid);
+   if (ret < 0)
+     {
+        ERR("Could not get systemd session");
+        goto session_err;
+     }
+
+   ret = sd_session_get_seat(em->sid, &s);
+   if (ret < 0)
+     {
+        ERR("Failed to get session seat");
+        free(s);
+        goto seat_err;
+     }
+   else if ((seat) && (strcmp(seat, s)))
+     {
+        ERR("Seat '%s' differs from session seat '%s'", seat, s);
+        free(s);
+        goto seat_err;
+     }
+
+   if (!_logind_session_vt_get(em->sid, &em->vt_num))
+     {
+        ERR("Could not get session vt");
+        goto vt_err;
+     }
+   else if ((tty > 0) && (em->vt_num != tty))
+     {
+        ERR("Requested VT %u differs from session VT %u", tty, em->vt_num);
+        goto vt_err;
+     }
+
+   free(s);
+
+   if (!_logind_dbus_open(&em->dbus.conn))
+     {
+        ERR("Could not connect to dbus");
+        goto vt_err;
+     }
+
+   if (!_logind_dbus_setup(em))
+     {
+        ERR("Could not setup dbus");
+        goto dbus_err;
+     }
+
+   if (!_logind_control_take(em))
+     {
+        ERR("Could not take control of session");
+        goto ctrl_err;
+     }
+
+   if (!_logind_activate(em))
+     {
+        ERR("Could not activate session");
+        goto actv_err;
+     }
+
+   *(Elput_Manager **)manager = em;
+
+   return EINA_TRUE;
+
+actv_err:
+   _logind_control_release(em);
+ctrl_err:
+   eldbus_object_unref(em->dbus.obj);
+   free(em->dbus.path);
+dbus_err:
+   _logind_dbus_close(em->dbus.conn);
+vt_err:
+seat_err:
+   free(em->sid);
+session_err:
+   free(em);
+   return EINA_FALSE;
+}
+
+static void
+_logind_disconnect(Elput_Manager *em)
+{
+   _logind_control_release(em);
+   eldbus_object_unref(em->dbus.obj);
+   free(em->dbus.path);
+   _logind_dbus_close(em->dbus.conn);
+   eina_stringshare_del(em->seat);
+   free(em->sid);
+   free(em);
+}
+
+Elput_Interface _logind_interface =
+{
+   _logind_connect,
+   _logind_disconnect,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+};
+
+#endif
diff --git a/src/lib/elput/elput_manager.c b/src/lib/elput/elput_manager.c
new file mode 100644
index 0000000..2073ff7
--- /dev/null
+++ b/src/lib/elput/elput_manager.c
@@ -0,0 +1,39 @@
+#include "elput_private.h"
+
+static Elput_Interface *_ifaces[] =
+{
+#ifdef HAVE_SYSTEMD
+   &_logind_interface,
+#endif
+   NULL, // launcher
+   NULL, // direct
+   NULL,
+};
+
+EAPI Elput_Manager *
+elput_manager_connect(const char *seat, unsigned int tty, Eina_Bool sync)
+{
+   Elput_Interface **it;
+
+   for (it = _ifaces; *it != NULL; it++)
+     {
+        Elput_Interface *iface;
+        Elput_Manager *em;
+
+        iface = *it;
+        if (iface->connect(&em, seat, tty, sync))
+          return em;
+     }
+
+   return NULL;
+}
+
+EAPI void
+elput_manager_disconnect(Elput_Manager *manager)
+{
+   EINA_SAFETY_ON_NULL_RETURN(manager);
+   EINA_SAFETY_ON_NULL_RETURN(manager->interface);
+
+   if (manager->interface->disconnect)
+     manager->interface->disconnect(manager);
+}
diff --git a/src/lib/elput/elput_private.h b/src/lib/elput/elput_private.h
index 62b7395..07e147b 100644
--- a/src/lib/elput/elput_private.h
+++ b/src/lib/elput/elput_private.h
@@ -12,6 +12,7 @@
 # include "Eldbus.h"
 # include <Elput.h>
 
+# include <unistd.h>
 # include <linux/vt.h>
 # include <linux/kd.h>
 # include <linux/major.h>
@@ -54,4 +55,35 @@ extern int _elput_log_dom;
 # endif
 # define CRIT(...) EINA_LOG_DOM_CRIT(_elput_log_dom, __VA_ARGS__)
 
+typedef struct _Elput_Interface
+{
+   Eina_Bool (*connect)(Elput_Manager **manager, const char *seat, unsigned 
int tty, Eina_Bool sync);
+   void (*disconnect)(Elput_Manager *manager);
+   int (*open)(Elput_Manager *manager, const char *path, int flags);
+   void (*close)(Elput_Manager *manager, int fd);
+   int (*activate)(Elput_Manager *manager, int vt);
+   void (*restore)(Elput_Manager *manager);
+} Elput_Interface;
+
+struct _Elput_Manager
+{
+   Elput_Interface *interface;
+
+   int fd;
+   char *sid;
+   const char *seat;
+   unsigned int vt_num;
+
+   struct
+     {
+        char *path;
+        Eldbus_Object *obj;
+        Eldbus_Connection *conn;
+     } dbus;
+
+   Eina_Bool sync : 1;
+};
+
+extern Elput_Interface _logind_interface;
+
 #endif

-- 


Reply via email to