forked from enlightenment/efl
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 <cpmichael@osg.samsung.com>
This commit is contained in:
parent
08482e1ca4
commit
ed3a1f3958
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue