From f8964fcf2e4681ab77e0cf37c96e9994d25b19fd Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Thu, 24 Mar 2016 11:19:31 -0400 Subject: [PATCH 01/15] elput: Initial checkin of elput library The elput library is an efl abstraction for the libinput library which can be used by various other subsystems (ecore_fb, ecore_drm, etc) to handle interfacing with libinput without having to duplicate the code in each subsystem. Signed-off-by: Chris Michael --- Makefile.am | 4 ++ configure.ac | 71 +++++++++++++++++++++++++++++++++ pc/elput.pc.in | 12 ++++++ src/Makefile.am | 1 + src/Makefile_Elput.am | 28 +++++++++++++ src/lib/elput/Elput.h | 74 +++++++++++++++++++++++++++++++++++ src/lib/elput/elput.c | 55 ++++++++++++++++++++++++++ src/lib/elput/elput_private.h | 57 +++++++++++++++++++++++++++ 8 files changed, 302 insertions(+) create mode 100644 pc/elput.pc.in create mode 100644 src/Makefile_Elput.am create mode 100644 src/lib/elput/Elput.h create mode 100644 src/lib/elput/elput.c create mode 100644 src/lib/elput/elput_private.h diff --git a/Makefile.am b/Makefile.am index c2422db91e..564f332993 100644 --- a/Makefile.am +++ b/Makefile.am @@ -286,6 +286,10 @@ if HAVE_ECORE_BUFFER pkgconfig_DATA += pc/ecore-buffer.pc endif +if HAVE_ELPUT +pkgconfig_DATA += pc/elput.pc +endif + # Cmake configs: efl_cmakeconfigdir = $(libdir)/cmake/Efl/ efl_cmakeconfig_DATA = \ diff --git a/configure.ac b/configure.ac index 44daa45356..f34bac8554 100644 --- a/configure.ac +++ b/configure.ac @@ -1984,6 +1984,17 @@ AC_ARG_ENABLE([ecore-buffer], ], [want_ecore_buffer="no"]) +AC_ARG_ENABLE([elput], + [AS_HELP_STRING([--enable-elput],[enable elput library. @<:@default=disabled@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + want_elput="yes" + else + want_elput="no" + fi + ], + [want_elput="no"]) + # Image Loaders ARG_ENABLE_EVAS_IMAGE_LOADER(BMP, static) @@ -3566,6 +3577,64 @@ EFL_LIB_END_OPTIONAL([Ecore_Drm]) #### End of Ecore_Drm +#### Elput +have_libinput_new="no" +EFL_LIB_START_OPTIONAL([Elput], [test "${want_elput}" = "yes"]) + +### Additional options to configure +SUID_CFLAGS=-fPIE +SUID_LDFLAGS=-pie +AC_SUBST([SUID_CFLAGS]) +AC_SUBST([SUID_LDFLAGS]) + +### Default values + +### Checks for programs + +### Checks for libraries +EFL_INTERNAL_DEPEND_PKG([ELPUT], [ecore]) +EFL_INTERNAL_DEPEND_PKG([ELPUT], [ecore-input]) +EFL_INTERNAL_DEPEND_PKG([ELPUT], [eldbus]) +EFL_INTERNAL_DEPEND_PKG([ELPUT], [eeze]) +EFL_INTERNAL_DEPEND_PKG([ELPUT], [eo]) +EFL_INTERNAL_DEPEND_PKG([ELPUT], [eina]) + +EFL_DEPEND_PKG([ELPUT], [LIBINPUT], [libinput >= 0.6.0 xkbcommon >= 0.3.0]) + +EFL_ADD_LIBS([ELPUT], [-lm]) + +# API change from 0.7 to 0.8. So we define this to support both for now. +PKG_CHECK_EXISTS([libinput >= 0.8.0], + [have_libinput_new="yes"], + [have_libinput_new="no"]) +AC_MSG_CHECKING([Use new libinput API (newer than 0.8.0)]) +AC_MSG_RESULT([${have_libinput_new}]) +if test "x${have_libinput_new}" = "xyes";then + AC_DEFINE_UNQUOTED([LIBINPUT_HIGHER_08], [1], [libinput version >= 0.8]) +fi +if test "x${have_libinput_new}" = "xno";then + AC_DEFINE_UNQUOTED([LIBINPUT_HIGHER_08], [0], [libinput version >= 0.8]) +fi + + +EFL_EVAL_PKGS([ELPUT]) + +### Checks for header files + +### Checks for types + +### Checks for structures + +### Checks for compiler characteristics + +### Checks for linker characteristics + +### Checks for library functions + +EFL_LIB_END_OPTIONAL([Elput]) +#### End of Ecore_Drm + + #### Ecore_Audio AC_ARG_ENABLE([audio], @@ -5512,6 +5581,7 @@ pc/elocation.pc pc/elua.pc pc/elementary.pc pc/elementary-cxx.pc +pc/elput.pc dbus-services/org.enlightenment.Ethumb.service systemd-services/ethumb.service $po_makefile_in @@ -5680,6 +5750,7 @@ fi echo "Ecore_Audio.....: ${efl_lib_optional_ecore_audio} (${features_ecore_audio})" echo "Ecore_Avahi.....: yes (${features_ecore_avahi})" echo "Ecore_Evas......: yes (${features_ecore_evas})" +echo "Elput...........: $want_elput" echo "Ector...........: yes" echo "Eeze............: ${efl_lib_optional_eeze} (${features_eeze})" echo "EPhysics........: ${efl_lib_optional_ephysics}" diff --git a/pc/elput.pc.in b/pc/elput.pc.in new file mode 100644 index 0000000000..c345022c06 --- /dev/null +++ b/pc/elput.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: elput +Description: E core library, libinput module +Requires.private: @requirements_pc_elput@ +Version: @VERSION@ +Libs: -L${libdir} -lelput +Libs.private: @requirements_libs_elput@ +Cflags: -I${includedir}/efl-@VMAJ@ -I${includedir}/elput-@VMAJ@ diff --git a/src/Makefile.am b/src/Makefile.am index 3aaa2ce944..c08d77cd5d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -70,6 +70,7 @@ include Makefile_Ethumb.am include Makefile_Ethumb_Client.am include Makefile_Elocation.am include Makefile_Elementary.am +include Makefile_Elput.am include Makefile_Eina_Cxx.am include Makefile_Ecore_Cxx.am diff --git a/src/Makefile_Elput.am b/src/Makefile_Elput.am new file mode 100644 index 0000000000..73fe8f9982 --- /dev/null +++ b/src/Makefile_Elput.am @@ -0,0 +1,28 @@ +if HAVE_ELPUT + +### Library + +lib_LTLIBRARIES += lib/elput/libelput.la + +installed_elputmainheadersdir = $(includedir)/elput-@VMAJ@ +dist_installed_elputmainheaders_DATA = \ + lib/elput/Elput.h + +lib_elput_libelput_la_SOURCES = \ +lib/elput/elput.c \ +lib/elput/elput_private.h + +lib_elput_libelput_la_CPPFLAGS = \ + -I$(top_builddir)/src/lib/efl \ + @ELPUT_CFLAGS@ @EFL_CFLAGS@ \ + -DPACKAGE_LIB_DIR=\"$(libdir)\" \ + -DMODULE_ARCH=\"$(MODULE_ARCH)\" + +lib_elput_libelput_la_LIBADD = @ELPUT_LIBS@ +if HAVE_SYSTEMD +lib_elput_libelput_la_LIBADD += @SYSTEMD_LIBS@ +endif +lib_elput_libelput_la_DEPENDENCIES = @ELPUT_INTERNAL_LIBS@ +lib_elput_libelput_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@ + +endif diff --git a/src/lib/elput/Elput.h b/src/lib/elput/Elput.h new file mode 100644 index 0000000000..7c88e4bed6 --- /dev/null +++ b/src/lib/elput/Elput.h @@ -0,0 +1,74 @@ +#ifndef _ELPUT_H +# define _ELPUT_H + +# ifdef EAPI +# undef EAPI +# endif + +# ifdef _MSC_VER +# ifdef BUILDING_DLL +# define EAPI __declspec(dllexport) +# else // ifdef BUILDING_DLL +# define EAPI __declspec(dllimport) +# endif // ifdef BUILDING_DLL +# else // ifdef _MSC_VER +# ifdef __GNUC__ +# if __GNUC__ >= 4 +# define EAPI __attribute__ ((visibility("default"))) +# else // if __GNUC__ >= 4 +# define EAPI +# endif // if __GNUC__ >= 4 +# else // ifdef __GNUC__ +# define EAPI +# endif // ifdef __GNUC__ +# endif // ifdef _MSC_VER + +# ifdef EFL_BETA_API_SUPPORT + +/** + * @file + * @brief Ecore functions for dealing with libinput + * + * @defgroup Elput_Group Elput - libinput integration + * @ingrup Ecore + * + * Elput provides a wrapper and functions for using libinput + * + * @li @ref Elput_Init_Group + * + */ + +/** + * @defgroup Elput_Init_Group Library Init and Shutdown functions + * + * Functions that start and shutdown the Elput library + */ + +/** + * Initialize the Elput library + * + * @return The number of times the library has been initialized without being + * shutdown. 0 is returned if an error occurs. + * + * @ingroup Elput_Init_Group + * @since 1.18 + */ +EAPI int elput_init(void); + +/** + * Shutdown the Elput library + * + * @return The number of times the library has been initialized without being + * shutdown. 0 is returned if an error occurs. + * + * @ingroup Elput_Init_Group + * @since 1.18 + */ +EAPI int elput_shutdown(void); + +# endif + +# undef EAPI +# define EAPI + +#endif diff --git a/src/lib/elput/elput.c b/src/lib/elput/elput.c new file mode 100644 index 0000000000..1b5613fc3a --- /dev/null +++ b/src/lib/elput/elput.c @@ -0,0 +1,55 @@ +#include "elput_private.h" + +/* local variables */ +static int _elput_init_count = 0; + +/* external variables */ +int _elput_log_dom = -1; + +EAPI int +elput_init(void) +{ + if (++_elput_init_count != 1) return _elput_init_count; + + if (!eina_init()) goto eina_err; + if (!ecore_init()) goto ecore_err; + if (!ecore_event_init()) goto ecore_event_err; + if (!eeze_init()) goto eeze_err; + + _elput_log_dom = eina_log_domain_register("elput", ELPUT_DEFAULT_LOG_COLOR); + if (!_elput_log_dom) + { + EINA_LOG_ERR("Could not create logging domain for Elput"); + goto log_err; + } + + return _elput_init_count; + +log_err: + eeze_shutdown(); +eeze_err: + ecore_event_shutdown(); +ecore_event_err: + ecore_shutdown(); +ecore_err: + eina_shutdown(); +eina_err: + return --_elput_init_count; +} + +EAPI int +elput_shutdown(void) +{ + if (_elput_init_count < 1) return 0; + if (--_elput_init_count != 0) return _elput_init_count; + + eina_log_domain_unregister(_elput_log_dom); + _elput_log_dom = -1; + + eeze_shutdown(); + ecore_event_shutdown(); + ecore_shutdown(); + eina_shutdown(); + + return _elput_init_count; +} diff --git a/src/lib/elput/elput_private.h b/src/lib/elput/elput_private.h new file mode 100644 index 0000000000..62b7395c29 --- /dev/null +++ b/src/lib/elput/elput_private.h @@ -0,0 +1,57 @@ +#ifndef _ELPUT_PRIVATE_H +# define _ELPUT_PRIVATE_H + +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif + +# include "Ecore.h" +# include "ecore_private.h" +# include "Ecore_Input.h" +# include "Eeze.h" +# include "Eldbus.h" +# include + +# include +# include +# include +# include +# include + +# ifdef HAVE_SYSTEMD +# include +# endif + +# ifdef ELPUT_DEFAULT_LOG_COLOR +# undef ELPUT_DEFAULT_LOG_COLOR +# endif +# define ELPUT_DEFAULT_LOG_COLOR EINA_COLOR_GREEN + +extern int _elput_log_dom; + +# ifdef ERR +# undef ERR +# endif +# define ERR(...) EINA_LOG_DOM_ERR(_elput_log_dom, __VA_ARGS__) + +# ifdef DBG +# undef DBG +# endif +# define DBG(...) EINA_LOG_DOM_DBG(_elput_log_dom, __VA_ARGS__) + +# ifdef INF +# undef INF +# endif +# define INF(...) EINA_LOG_DOM_INFO(_elput_log_dom, __VA_ARGS__) + +# ifdef WRN +# undef WRN +# endif +# define WRN(...) EINA_LOG_DOM_WARN(_elput_log_dom, __VA_ARGS__) + +# ifdef CRIT +# undef CRIT +# endif +# define CRIT(...) EINA_LOG_DOM_CRIT(_elput_log_dom, __VA_ARGS__) + +#endif From 08482e1ca4feaff2c631a125b58fda7e57084b97 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Thu, 24 Mar 2016 13:38:44 -0400 Subject: [PATCH 02/15] elput: Add test framework for Elput library Signed-off-by: Chris Michael --- src/Makefile_Elput.am | 27 +++++++++++++++++++++++++++ src/tests/elput/elput_suite.c | 29 +++++++++++++++++++++++++++++ src/tests/elput/elput_suite.h | 8 ++++++++ src/tests/elput/elput_test_elput.c | 29 +++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+) create mode 100644 src/tests/elput/elput_suite.c create mode 100644 src/tests/elput/elput_suite.h create mode 100644 src/tests/elput/elput_test_elput.c diff --git a/src/Makefile_Elput.am b/src/Makefile_Elput.am index 73fe8f9982..851d4ee260 100644 --- a/src/Makefile_Elput.am +++ b/src/Makefile_Elput.am @@ -25,4 +25,31 @@ endif lib_elput_libelput_la_DEPENDENCIES = @ELPUT_INTERNAL_LIBS@ lib_elput_libelput_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@ +### Unit tests + +if EFL_ENABLE_TESTS + +check_PROGRAMS += tests/elput/elput_suite +TESTS += tests/elput/elput_suite + +tests_elput_elput_suite_SOURCES = \ +tests/elput/elput_suite.c \ +tests/elput/elput_test_elput.c \ +tests/elput/elput_suite.h + +tests_elput_elput_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ +-DTESTS_SRC_DIR=\"$(top_srcdir)/src/tests/elput\" \ +-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/elput\" \ +@CHECK_CFLAGS@ \ +@ELPUT_CFLAGS@ + +tests_elput_elput_suite_LDADD = \ +@CHECK_LIBS@ \ +@USE_ELPUT_LIBS@ + +tests_elput_elput_suite_DEPENDENCIES = \ +@USE_ELPUT_INTERNAL_LIBS@ + +endif + endif diff --git a/src/tests/elput/elput_suite.c b/src/tests/elput/elput_suite.c new file mode 100644 index 0000000000..b56b84e714 --- /dev/null +++ b/src/tests/elput/elput_suite.c @@ -0,0 +1,29 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "elput_suite.h" +#include "../efl_check.h" + +static const Efl_Test_Case etc[] = +{ +#if HAVE_ELPUT + { "Elput", elput_test_elput }, +#endif + { NULL, NULL } +}; + +int +main(int argc, char **argv) +{ + int count; + + if (!_efl_test_option_disp(argc, argv, etc)) return 0; + + putenv("EFL_RUN_IN_TREE=1"); + + count = + _efl_suite_build_and_run(argc - 1, (const char **)argv + 1, "Elput", etc); + + return (count == 0) ? 0 : 255; +} diff --git a/src/tests/elput/elput_suite.h b/src/tests/elput/elput_suite.h new file mode 100644 index 0000000000..34a7ffd2e0 --- /dev/null +++ b/src/tests/elput/elput_suite.h @@ -0,0 +1,8 @@ +#ifndef _ELPUT_SUITE_H +# define _ELPUT_SUITE_H + +# include + +void elput_test_elput(TCase *tc); + +#endif diff --git a/src/tests/elput/elput_test_elput.c b/src/tests/elput/elput_test_elput.c new file mode 100644 index 0000000000..8207ee8d25 --- /dev/null +++ b/src/tests/elput/elput_test_elput.c @@ -0,0 +1,29 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include +#include +#include + +#include "elput_suite.h" + +START_TEST(elput_test_elput_init) +{ + int ret; + + ret = elput_init(); + fail_if(ret < 1); + + ret = elput_shutdown(); + fail_if(ret != 0); +} +END_TEST + +void elput_test_elput(TCase *tc) +{ + tcase_add_test(tc, elput_test_elput_init); +} From ed3a1f39587187c8acf305fd793f92218995c486 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Thu, 31 Mar 2016 12:34:32 -0400 Subject: [PATCH 03/15] 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 --- 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(+) create mode 100644 src/lib/elput/elput_logind.c create mode 100644 src/lib/elput/elput_manager.c diff --git a/src/Makefile_Elput.am b/src/Makefile_Elput.am index 851d4ee260..3e1ed58861 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 7c88e4bed6..e098b138e8 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 0000000000..d649bf34ea --- /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 0000000000..2073ff78f9 --- /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 62b7395c29..07e147bcf5 100644 --- a/src/lib/elput/elput_private.h +++ b/src/lib/elput/elput_private.h @@ -12,6 +12,7 @@ # include "Eldbus.h" # include +# include # include # include # include @@ -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 From 1ce6cd438244d644a63e6d1ab1dde88633bba34e Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Fri, 1 Apr 2016 09:12:36 -0400 Subject: [PATCH 04/15] elput: Add API functions to open and close an input device This adds new API functions which can be called to open or close an input device and take control (or release control) of said device Signed-off-by: Chris Michael --- src/lib/elput/Elput.h | 25 +++++++ src/lib/elput/elput_logind.c | 122 +++++++++++++++++++++++++++++++++- src/lib/elput/elput_manager.c | 25 +++++++ src/lib/elput/elput_private.h | 1 + 4 files changed, 171 insertions(+), 2 deletions(-) diff --git a/src/lib/elput/Elput.h b/src/lib/elput/Elput.h index e098b138e8..44a861ce29 100644 --- a/src/lib/elput/Elput.h +++ b/src/lib/elput/Elput.h @@ -102,6 +102,31 @@ EAPI Elput_Manager *elput_manager_connect(const char *seat, unsigned int tty, Ei */ EAPI void elput_manager_disconnect(Elput_Manager *manager); +/** + * Request input manager to open a file + * + * @param manager + * @param path + * @param flags + * + * @return Filedescriptor of opened file or -1 on failure + * + * @ingroup Elput_Manager_Group + * @since 1.18 + */ +EAPI int elput_manager_open(Elput_Manager *manager, const char *path, int flags); + +/** + * Request input manager to close a file + * + * @param manager + * @param fd + * + * @ingroup Elput_Manager_Group + * @since 1.18 + */ +EAPI void elput_manager_close(Elput_Manager *manager, int fd); + # endif # undef EAPI diff --git a/src/lib/elput/elput_logind.c b/src/lib/elput/elput_logind.c index d649bf34ea..ec3cb7ea75 100644 --- a/src/lib/elput/elput_logind.c +++ b/src/lib/elput/elput_logind.c @@ -302,6 +302,78 @@ end: eldbus_proxy_unref(proxy); } +static int +_logind_device_take(Elput_Manager *em, uint32_t major, uint32_t minor) +{ + Eldbus_Proxy *proxy; + Eldbus_Message *msg, *reply; + Eina_Bool p = EINA_FALSE; + const char *errname, *errmsg; + int fd = -1; + + proxy = + eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session"); + if (!proxy) + { + ERR("Could not get dbus proxy"); + return -1; + } + + msg = eldbus_proxy_method_call_new(proxy, "TakeDevice"); + if (!msg) + { + ERR("Could not create method call for proxy"); + goto err; + } + + eldbus_message_arguments_append(msg, "uu", major, minor); + + 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 err; + } + + if (!eldbus_message_arguments_get(reply, "hb", &fd, &p)) + ERR("Could not get UNIX_FD from dbus message"); + + eldbus_message_unref(reply); + +err: + eldbus_proxy_unref(proxy); + return fd; +} + +static void +_logind_device_release(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, "ReleaseDevice"); + 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_proxy_unref(proxy); +} + static Eina_Bool _logind_activate(Elput_Manager *em) { @@ -437,12 +509,58 @@ _logind_disconnect(Elput_Manager *em) free(em); } +static int +_logind_open(Elput_Manager *em, const char *path, int flags) +{ + struct stat st; + int ret, fd = -1; + int fl; + + ret = stat(path, &st); + if (ret < 0) return -1; + + if (!S_ISCHR(st.st_mode)) return -1; + + fd = _logind_device_take(em, major(st.st_rdev), minor(st.st_rdev)); + if (fd < 0) return fd; + + fl = fcntl(fd, F_GETFL); + if (fl < 0) goto err; + + if (flags & O_NONBLOCK) + fl |= O_NONBLOCK; + + ret = fcntl(fd, F_SETFL, fl); + if (ret < 0) goto err; + + return fd; + +err: + close(fd); + _logind_device_release(em, major(st.st_rdev), minor(st.st_rdev)); + return -1; +} + +static void +_logind_close(Elput_Manager *em, int fd) +{ + struct stat st; + int ret; + + ret = fstat(fd, &st); + if (ret < 0) return; + + if (!S_ISCHR(st.st_mode)) return; + + _logind_device_release(em, major(st.st_rdev), minor(st.st_rdev)); +} + Elput_Interface _logind_interface = { _logind_connect, _logind_disconnect, - NULL, - NULL, + _logind_open, + _logind_close, NULL, NULL, }; diff --git a/src/lib/elput/elput_manager.c b/src/lib/elput/elput_manager.c index 2073ff78f9..3dc67d9594 100644 --- a/src/lib/elput/elput_manager.c +++ b/src/lib/elput/elput_manager.c @@ -37,3 +37,28 @@ elput_manager_disconnect(Elput_Manager *manager) if (manager->interface->disconnect) manager->interface->disconnect(manager); } + +EAPI int +elput_manager_open(Elput_Manager *manager, const char *path, int flags) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(manager, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(manager->interface, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(path, -1); + + if (flags < 0) flags = O_RDWR; + + if (manager->interface->open) + return manager->interface->open(manager, path, flags); + + return -1; +} + +EAPI void +elput_manager_close(Elput_Manager *manager, int fd) +{ + EINA_SAFETY_ON_NULL_RETURN(manager); + EINA_SAFETY_ON_NULL_RETURN(manager->interface); + + if (manager->interface->close) + manager->interface->close(manager, fd); +} diff --git a/src/lib/elput/elput_private.h b/src/lib/elput/elput_private.h index 07e147bcf5..74532d57d9 100644 --- a/src/lib/elput/elput_private.h +++ b/src/lib/elput/elput_private.h @@ -12,6 +12,7 @@ # include "Eldbus.h" # include +# include # include # include # include From b5422700c05a102d418faa60f93287b7abcf44db Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Fri, 1 Apr 2016 09:49:36 -0400 Subject: [PATCH 05/15] elput: Remove vt activate/restore from input manager interface As this library is just going to deal with libinput, we don't need to have interface functions to activate or restore a virtual terminal. Signed-off-by: Chris Michael --- src/lib/elput/elput_logind.c | 2 -- src/lib/elput/elput_private.h | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/lib/elput/elput_logind.c b/src/lib/elput/elput_logind.c index ec3cb7ea75..c89ca2ae46 100644 --- a/src/lib/elput/elput_logind.c +++ b/src/lib/elput/elput_logind.c @@ -561,8 +561,6 @@ Elput_Interface _logind_interface = _logind_disconnect, _logind_open, _logind_close, - NULL, - NULL, }; #endif diff --git a/src/lib/elput/elput_private.h b/src/lib/elput/elput_private.h index 74532d57d9..c500a559c1 100644 --- a/src/lib/elput/elput_private.h +++ b/src/lib/elput/elput_private.h @@ -62,8 +62,6 @@ typedef struct _Elput_Interface 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 From f832d2019cc96d750a17f9df3aec3feff78dc5a3 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Fri, 1 Apr 2016 13:04:25 -0400 Subject: [PATCH 06/15] elput: Add API function to initialize and shutdown input devices Signed-off-by: Chris Michael --- src/Makefile_Elput.am | 1 + src/lib/elput/Elput.h | 31 ++++++++++++- src/lib/elput/elput_input.c | 87 +++++++++++++++++++++++++++++++++++ src/lib/elput/elput_private.h | 13 ++++++ 4 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 src/lib/elput/elput_input.c diff --git a/src/Makefile_Elput.am b/src/Makefile_Elput.am index 3e1ed58861..c79763e298 100644 --- a/src/Makefile_Elput.am +++ b/src/Makefile_Elput.am @@ -9,6 +9,7 @@ dist_installed_elputmainheaders_DATA = \ lib/elput/Elput.h lib_elput_libelput_la_SOURCES = \ +lib/elput/elput_input.c \ lib/elput/elput_logind.c \ lib/elput/elput_manager.c \ lib/elput/elput.c \ diff --git a/src/lib/elput/Elput.h b/src/lib/elput/Elput.h index 44a861ce29..234597ff33 100644 --- a/src/lib/elput/Elput.h +++ b/src/lib/elput/Elput.h @@ -39,6 +39,7 @@ typedef struct _Elput_Manager Elput_Manager; * * @li @ref Elput_Init_Group * @li @ref Elput_Manager_Group + * @li @ref Elput_Input_Group * */ @@ -75,7 +76,6 @@ EAPI int elput_shutdown(void); * * Functions that deal with connecting, disconnecting, opening, closing * of input devices. - * */ /** @@ -127,6 +127,35 @@ EAPI int elput_manager_open(Elput_Manager *manager, const char *path, int flags) */ EAPI void elput_manager_close(Elput_Manager *manager, int fd); +/** + * @defgroup Elput_Input_Group Elput input functions + * + * Functions that deal with setup of inputs + */ + +/** + * Initialize input + * + * @param manager + * @param seat + * + * @return EINA_TRUE on success, EINA_FALSE on failure + * + * @ingroup Elput_Input_Group + * @since 1.18 + */ +EAPI Eina_Bool elput_input_init(Elput_Manager *manager, const char *seat); + +/** + * Shutdown input + * + * @param manager + * + * @ingroup Elput_Input_Group + * @since 1.18 + */ +EAPI void elput_input_shutdown(Elput_Manager *manager); + # endif # undef EAPI diff --git a/src/lib/elput/elput_input.c b/src/lib/elput/elput_input.c new file mode 100644 index 0000000000..a2a4ccbd5e --- /dev/null +++ b/src/lib/elput/elput_input.c @@ -0,0 +1,87 @@ +#include "elput_private.h" + +static int +_cb_open_restricted(const char *path, int flags, void *data) +{ + Elput_Manager *em; + + em = data; + return elput_manager_open(em, path, flags); +} + +static void +_cb_close_restricted(int fd, void *data) +{ + Elput_Manager *em; + + em = data; + elput_manager_close(em, fd); +} + +const struct libinput_interface _input_interface = +{ + _cb_open_restricted, + _cb_close_restricted, +}; + +static void +_process_event(struct libinput_event *event) +{ + /* TODO */ +} + +static void +_process_events(Elput_Input *ei) +{ + struct libinput_event *event; + + while ((event = libinput_get_event(ei->lib))) + { + _process_event(event); + libinput_event_destroy(event); + } +} + +EAPI Eina_Bool +elput_input_init(Elput_Manager *manager, const char *seat) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(manager, EINA_FALSE); + + memset(&manager->input, 0, sizeof(Elput_Input)); + + manager->input.lib = + libinput_udev_create_context(&_input_interface, manager, eeze_udev_get()); + if (!manager->input.lib) + { + ERR("libinput could not create udev context"); + goto udev_err; + } + + if (libinput_udev_assign_seat(manager->input.lib, seat) != 0) + { + ERR("libinput could not assign udev seat"); + goto seat_err; + } + + _process_events(&manager->input); + + /* TODO */ + + return EINA_TRUE; + +seat_err: + libinput_unref(manager->input.lib); +udev_err: + return EINA_FALSE; +} + +EAPI void +elput_input_shutdown(Elput_Manager *manager) +{ + EINA_SAFETY_ON_NULL_RETURN(manager); + EINA_SAFETY_ON_NULL_RETURN(&manager->input); + + /* TODO */ + + libinput_unref(manager->input.lib); +} diff --git a/src/lib/elput/elput_private.h b/src/lib/elput/elput_private.h index c500a559c1..6d88943921 100644 --- a/src/lib/elput/elput_private.h +++ b/src/lib/elput/elput_private.h @@ -64,6 +64,17 @@ typedef struct _Elput_Interface void (*close)(Elput_Manager *manager, int fd); } Elput_Interface; +typedef struct _Elput_Input +{ + struct libinput *lib; + + Ecore_Fd_Handler *hdlr; + + Eina_List *seats; + + Eina_Bool suspended : 1; +} Elput_Input; + struct _Elput_Manager { Elput_Interface *interface; @@ -80,6 +91,8 @@ struct _Elput_Manager Eldbus_Connection *conn; } dbus; + Elput_Input input; + Eina_Bool sync : 1; }; From bd0d4ba60fb9ad88ebb8073d67dfde213937fc8c Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Fri, 1 Apr 2016 13:22:16 -0400 Subject: [PATCH 07/15] elput: Start code to process events from libinput Signed-off-by: Chris Michael --- src/lib/elput/elput_input.c | 64 +++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/src/lib/elput/elput_input.c b/src/lib/elput/elput_input.c index a2a4ccbd5e..c001e52e5a 100644 --- a/src/lib/elput/elput_input.c +++ b/src/lib/elput/elput_input.c @@ -24,10 +24,41 @@ const struct libinput_interface _input_interface = _cb_close_restricted, }; +static int +_udev_process_event(struct libinput_event *event) +{ + Elput_Manager *em; + struct libinput *lib; + struct libinput_device *dev; + int ret = 1; + + lib = libinput_event_get_context(event); + dev = libinput_event_get_device(event); + em = libinput_get_user_data(lib); + + switch (libinput_event_get_type(event)) + { + case LIBINPUT_EVENT_DEVICE_ADDED: + DBG("Input Device Added: %s", libinput_device_get_name(dev)); + /* TODO: add device */ + break; + case LIBINPUT_EVENT_DEVICE_REMOVED: + DBG("Input Device Removed: %s", libinput_device_get_name(dev)); + /* TODO: remove device */ + break; + default: + ret = 0; + break; + } + + return ret; +} + static void _process_event(struct libinput_event *event) { - /* TODO */ + if (_udev_process_event(event)) return; + /* TODO: evdev processing */ } static void @@ -42,9 +73,26 @@ _process_events(Elput_Input *ei) } } +static Eina_Bool +_cb_input_dispatch(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED) +{ + Elput_Input *ei; + + ei = data; + + if (libinput_dispatch(ei->lib) != 0) + WRN("libinput failed to dispatch events"); + + _process_events(ei); + + return EINA_TRUE; +} + EAPI Eina_Bool elput_input_init(Elput_Manager *manager, const char *seat) { + int fd; + EINA_SAFETY_ON_NULL_RETURN_VAL(manager, EINA_FALSE); memset(&manager->input, 0, sizeof(Elput_Input)); @@ -65,10 +113,20 @@ elput_input_init(Elput_Manager *manager, const char *seat) _process_events(&manager->input); - /* TODO */ + fd = libinput_get_fd(manager->input.lib); + + manager->input.hdlr = + ecore_main_fd_handler_add(fd, ECORE_FD_READ, _cb_input_dispatch, + &manager->input, NULL, NULL); + if (!manager->input.hdlr) + { + ERR("Could not create input fd handler"); + goto hdlr_err; + } return EINA_TRUE; +hdlr_err: seat_err: libinput_unref(manager->input.lib); udev_err: @@ -81,6 +139,8 @@ elput_input_shutdown(Elput_Manager *manager) EINA_SAFETY_ON_NULL_RETURN(manager); EINA_SAFETY_ON_NULL_RETURN(&manager->input); + if (manager->input.hdlr) ecore_main_fd_handler_del(manager->input.hdlr); + /* TODO */ libinput_unref(manager->input.lib); From 3070c4cf08a28b2a9a3f4838ec78ce7f7bde95ec Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 6 Apr 2016 08:46:29 -0400 Subject: [PATCH 08/15] elput: Add support for creating and removing devices This patch adds start of code to create or remove input devices such as keyboards, pointers, or touch devices. Signed-off-by: Chris Michael --- src/Makefile_Elput.am | 1 + src/lib/elput/Elput.h | 15 ++ src/lib/elput/elput_evdev.c | 464 ++++++++++++++++++++++++++++++++++ src/lib/elput/elput_input.c | 100 +++++++- src/lib/elput/elput_private.h | 139 ++++++++++ 5 files changed, 715 insertions(+), 4 deletions(-) create mode 100644 src/lib/elput/elput_evdev.c diff --git a/src/Makefile_Elput.am b/src/Makefile_Elput.am index c79763e298..d177f6d3e4 100644 --- a/src/Makefile_Elput.am +++ b/src/Makefile_Elput.am @@ -9,6 +9,7 @@ dist_installed_elputmainheaders_DATA = \ lib/elput/Elput.h lib_elput_libelput_la_SOURCES = \ +lib/elput/elput_evdev.c \ lib/elput/elput_input.c \ lib/elput/elput_logind.c \ lib/elput/elput_manager.c \ diff --git a/src/lib/elput/Elput.h b/src/lib/elput/Elput.h index 234597ff33..f6ad5d219c 100644 --- a/src/lib/elput/Elput.h +++ b/src/lib/elput/Elput.h @@ -28,6 +28,21 @@ /* opaque structure to represent an input manager */ typedef struct _Elput_Manager Elput_Manager; +/* opaque structure to represent an input seat */ +typedef struct _Elput_Seat Elput_Seat; + +/* opaque structure to represent an input device */ +typedef struct _Elput_Device Elput_Device; + +/* opaque structure to represent a keyboard */ +typedef struct _Elput_Keyboard Elput_Keyboard; + +/* opaque structure to represent a mouse */ +typedef struct _Elput_Pointer Elput_Pointer; + +/* opaque structure to represent a touch device */ +typedef struct _Elput_Touch Elput_Touch; + /** * @file * @brief Ecore functions for dealing with libinput diff --git a/src/lib/elput/elput_evdev.c b/src/lib/elput/elput_evdev.c new file mode 100644 index 0000000000..4c347386df --- /dev/null +++ b/src/lib/elput/elput_evdev.c @@ -0,0 +1,464 @@ +#include "elput_private.h" + +static void +_seat_caps_update(Elput_Seat *seat) +{ + /* TODO: raise event for seat caps */ +} + +static int +_keyboard_fd_get(off_t size) +{ + int fd = 0, blen = 0, len = 0; + const char *path; + char tmp[PATH_MAX]; + long flags; + + blen = sizeof(tmp) - 1; + + if (!(path = getenv("XDG_RUNTIME_DIR"))) + return -1; + + len = strlen(path); + if (len < blen) + { + strcpy(tmp, path); + strcat(tmp, "/elput-keymap-XXXXXX"); + } + else + return -1; + + if ((fd = mkstemp(tmp)) < 0) return -1; + + flags = fcntl(fd, F_GETFD); + if (flags < 0) + { + close(fd); + return -1; + } + + if (fcntl(fd, F_SETFD, (flags | FD_CLOEXEC)) == -1) + { + close(fd); + return -1; + } + + if (ftruncate(fd, size) < 0) + { + close(fd); + return -1; + } + + unlink(tmp); + return fd; +} + +static Elput_Keyboard_Info * +_keyboard_info_create(struct xkb_keymap *keymap, Eina_Bool external) +{ + Elput_Keyboard_Info *info; + char *str; + + info = calloc(1, sizeof(Elput_Keyboard_Info)); + if (!info) return NULL; + + info->keymap.map = xkb_keymap_ref(keymap); + info->refs = 1; + + info->mods.super = + 1 << xkb_keymap_mod_get_index(info->keymap.map, XKB_MOD_NAME_LOGO); + info->mods.shift = + 1 << xkb_keymap_mod_get_index(info->keymap.map, XKB_MOD_NAME_SHIFT); + info->mods.caps = + 1 << xkb_keymap_mod_get_index(info->keymap.map, XKB_MOD_NAME_CAPS); + info->mods.ctrl = + 1 << xkb_keymap_mod_get_index(info->keymap.map, XKB_MOD_NAME_CTRL); + info->mods.alt = + 1 << xkb_keymap_mod_get_index(info->keymap.map, XKB_MOD_NAME_ALT); + info->mods.altgr = + 1 << xkb_keymap_mod_get_index(info->keymap.map, "ISO_Level3_Shift"); + + /* if we are using an external keymap then we do not need go further */ + if (external) return info; + + str = xkb_keymap_get_as_string(info->keymap.map, XKB_KEYMAP_FORMAT_TEXT_V1); + if (!str) goto err; + + info->keymap.size = strlen(str) + 1; + + info->keymap.fd = _keyboard_fd_get(info->keymap.size); + if (info->keymap.fd < 0) goto err_fd; + + info->keymap.area = + mmap(NULL, info->keymap.size, PROT_READ | PROT_WRITE, + MAP_SHARED, info->keymap.fd, 0); + if (info->keymap.area == MAP_FAILED) goto err_map; + + strcpy(info->keymap.area, str); + free(str); + + return info; + +err_map: + close(info->keymap.fd); +err_fd: + free(str); +err: + xkb_keymap_unref(info->keymap.map); + free(info); + return NULL; +} + +static void +_keyboard_info_destroy(Elput_Keyboard_Info *info, Eina_Bool external) +{ + if (--info->refs > 0) return; + + if (!external) + { + xkb_keymap_unref(info->keymap.map); + if (info->keymap.area) munmap(info->keymap.area, info->keymap.size); + if (info->keymap.fd >= 0) close(info->keymap.fd); + } + + free(info); +} + +static Eina_Bool +_keyboard_global_build(Elput_Keyboard *kbd) +{ + struct xkb_keymap *keymap; + + kbd->context = xkb_context_new(0); + if (!kbd->context) return EINA_FALSE; + + if (!kbd->names.rules) kbd->names.rules = strdup("evdev"); + if (!kbd->names.model) kbd->names.model = strdup("pc105"); + if (!kbd->names.layout) kbd->names.layout = strdup("us"); + + keymap = xkb_keymap_new_from_names(kbd->context, &kbd->names, 0); + if (!keymap) return EINA_FALSE; + + kbd->info = _keyboard_info_create(keymap, EINA_FALSE); + xkb_keymap_unref(keymap); + + if (!kbd->info) return EINA_FALSE; + return EINA_TRUE; +} + +static Elput_Keyboard * +_keyboard_create(Elput_Seat *seat) +{ + Elput_Keyboard *kbd; + + kbd = calloc(1, sizeof(Elput_Keyboard)); + if (!kbd) return NULL; + + kbd->seat = seat; + return kbd; +} + +static Eina_Bool +_keyboard_init(Elput_Seat *seat, struct xkb_keymap *keymap) +{ + Elput_Keyboard *kbd; + + if (seat->kbd) + { + seat->count.kbd += 1; + if (seat->count.kbd == 1) + { + _seat_caps_update(seat); + return EINA_TRUE; + } + } + + kbd = _keyboard_create(seat); + if (!kbd) return EINA_FALSE; + + if (keymap) + { + kbd->info = _keyboard_info_create(keymap, EINA_TRUE); + if (!kbd->info) goto err; + } + else + { + if (!_keyboard_global_build(kbd)) goto err; + kbd->info->refs++; + } + + kbd->state = xkb_state_new(kbd->info->keymap.map); + if (!kbd->state) goto err; + + seat->kbd = kbd; + seat->count.kbd = 1; + + _seat_caps_update(seat); + + return EINA_TRUE; + +err: + if (kbd->info) _keyboard_info_destroy(kbd->info, kbd->external_map); + free(kbd); + return EINA_FALSE; +} + +static void +_keyboard_state_reset(Elput_Keyboard *kbd) +{ + struct xkb_state *state; + + state = xkb_state_new(kbd->info->keymap.map); + if (!state) return; + + xkb_state_unref(kbd->state); + kbd->state = state; +} + +static void +_keyboard_release(Elput_Seat *seat) +{ + seat->count.kbd--; + if (seat->count.kbd == 0) + { + _keyboard_state_reset(seat->kbd); + _seat_caps_update(seat); + } +} + +static Elput_Pointer * +_pointer_create(Elput_Seat *seat) +{ + Elput_Pointer *ptr; + + ptr = calloc(1, sizeof(Elput_Pointer)); + if (!ptr) return NULL; + + ptr->seat = seat; + + return ptr; +} + +static Eina_Bool +_pointer_init(Elput_Seat *seat) +{ + Elput_Pointer *ptr; + + if (seat->ptr) + { + seat->count.ptr += 1; + if (seat->count.ptr == 1) + { + _seat_caps_update(seat); + return EINA_TRUE; + } + } + + ptr = _pointer_create(seat); + if (!ptr) return EINA_FALSE; + + seat->ptr = ptr; + seat->count.ptr = 1; + + _seat_caps_update(seat); + + return EINA_TRUE; +} + +static void +_pointer_release(Elput_Seat *seat) +{ + seat->count.ptr--; + if (seat->count.ptr == 0) + { + seat->ptr->buttons = 0; + _seat_caps_update(seat); + } +} + +static Elput_Touch * +_touch_create(Elput_Seat *seat) +{ + Elput_Touch *touch; + + touch = calloc(1, sizeof(Elput_Touch)); + if (!touch) return NULL; + + touch->seat = seat; + + return touch; +} + +static Eina_Bool +_touch_init(Elput_Seat *seat) +{ + Elput_Touch *touch; + + if (seat->touch) + { + seat->count.touch += 1; + if (seat->count.touch == 1) + { + _seat_caps_update(seat); + return EINA_TRUE; + } + } + + touch = _touch_create(seat); + if (!touch) return EINA_FALSE; + + seat->touch = touch; + seat->count.touch = 1; + + _seat_caps_update(seat); + + return EINA_TRUE; +} + +static void +_touch_release(Elput_Seat *seat) +{ + seat->count.touch--; + if (seat->count.touch == 0) + { + seat->touch->points = 0; + _seat_caps_update(seat); + } +} + +int +_evdev_event_process(struct libinput_event *event) +{ + struct libinput_device *idev; + int ret = 1; + Eina_Bool frame = EINA_FALSE; + + idev = libinput_event_get_device(event); + switch (libinput_event_get_type(event)) + { + case LIBINPUT_EVENT_KEYBOARD_KEY: + break; + case LIBINPUT_EVENT_POINTER_MOTION: + break; + case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: + break; + case LIBINPUT_EVENT_POINTER_BUTTON: + break; + case LIBINPUT_EVENT_POINTER_AXIS: + break; + case LIBINPUT_EVENT_TOUCH_DOWN: + break; + case LIBINPUT_EVENT_TOUCH_MOTION: + break; + case LIBINPUT_EVENT_TOUCH_UP: + break; + case LIBINPUT_EVENT_TOUCH_FRAME: + default: + ret = 0; + break; + } + + if (frame) + { + + } + + return ret; +} + +Elput_Device * +_evdev_device_create(Elput_Seat *seat, struct libinput_device *device) +{ + Elput_Device *edev; + + edev = calloc(1, sizeof(Elput_Device)); + if (!edev) return NULL; + + edev->seat = seat; + edev->device = device; + + if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_KEYBOARD)) + { + _keyboard_init(seat, NULL); + edev->caps |= EVDEV_SEAT_KEYBOARD; + } + + if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_POINTER)) + { + _pointer_init(seat); + edev->caps |= EVDEV_SEAT_POINTER; + } + + if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TOUCH)) + { + _touch_init(seat); + edev->caps |= EVDEV_SEAT_TOUCH; + } + + libinput_device_set_user_data(device, edev); + libinput_device_ref(edev->device); + + if (libinput_device_config_tap_get_finger_count(edev->device) > 0) + { + Eina_Bool enable = EINA_FALSE; + + enable = libinput_device_config_tap_get_default_enabled(edev->device); + libinput_device_config_tap_set_enabled(edev->device, enable); + } + + /* FIXME: Normally we would do a device calibration set here however + * that requires Output support. Since this is just an input library, we + * may need to add external facing APIs to do calibration. Then a user of + * elput would handle outputs, and make calls to calibrate */ + + return edev; +} + +void +_evdev_device_destroy(Elput_Device *edev) +{ + if (!edev) return; + + if (edev->caps & EVDEV_SEAT_POINTER) + _pointer_release(edev->seat); + if (edev->caps & EVDEV_SEAT_KEYBOARD) + _keyboard_release(edev->seat); + if (edev->caps & EVDEV_SEAT_TOUCH) + _touch_release(edev->seat); + + libinput_device_unref(edev->device); + eina_stringshare_del(edev->output_name); + free(edev); +} + +void +_evdev_keyboard_destroy(Elput_Keyboard *kbd) +{ + free((char *)kbd->names.rules); + free((char *)kbd->names.model); + free((char *)kbd->names.layout); + free((char *)kbd->names.variant); + free((char *)kbd->names.options); + + if (kbd->state) xkb_state_unref(kbd->state); + if (kbd->info) _keyboard_info_destroy(kbd->info, kbd->external_map); + + xkb_context_unref(kbd->context); + xkb_keymap_unref(kbd->pending_map); + + free(kbd); +} + +void +_evdev_pointer_destroy(Elput_Pointer *ptr) +{ + /* FIXME: destroy any resources inside pointer structure */ + free(ptr); +} + +void +_evdev_touch_destroy(Elput_Touch *touch) +{ + /* FIXME: destroy any resources inside touch structure */ + free(touch); +} diff --git a/src/lib/elput/elput_input.c b/src/lib/elput/elput_input.c index c001e52e5a..499efcf48b 100644 --- a/src/lib/elput/elput_input.c +++ b/src/lib/elput/elput_input.c @@ -24,6 +24,95 @@ const struct libinput_interface _input_interface = _cb_close_restricted, }; +static Elput_Seat * +_udev_seat_create(Elput_Manager *em, const char *name) +{ + Elput_Seat *eseat; + + eseat = calloc(1, sizeof(Elput_Seat)); + if (!eseat) return NULL; + + eseat->name = eina_stringshare_add(name); + em->input.seats = eina_list_append(em->input.seats, eseat); + + return eseat; +} + +static void +_udev_seat_destroy(Elput_Seat *eseat) +{ + Elput_Device *edev; + + EINA_LIST_FREE(eseat->devices, edev) + _evdev_device_destroy(edev); + + if (eseat->kbd) _evdev_keyboard_destroy(eseat->kbd); + if (eseat->ptr) _evdev_pointer_destroy(eseat->ptr); + if (eseat->touch) _evdev_touch_destroy(eseat->touch); + + eina_stringshare_del(eseat->name); + free(eseat); +} + +static Elput_Seat * +_udev_seat_named_get(Elput_Manager *em, const char *name) +{ + Elput_Seat *eseat; + Eina_List *l; + + EINA_LIST_FOREACH(em->input.seats, l, eseat) + if (!strcmp(eseat->name, name)) return eseat; + + return _udev_seat_create(em, name); +} + +static Elput_Seat * +_udev_seat_get(Elput_Manager *em, struct libinput_device *device) +{ + struct libinput_seat *lseat; + const char *name; + + lseat = libinput_device_get_seat(device); + name = libinput_seat_get_logical_name(lseat); + + return _udev_seat_named_get(em, name); +} + +static void +_device_add(Elput_Manager *em, struct libinput_device *dev) +{ + Elput_Seat *eseat; + Elput_Device *edev; + const char *oname; + + eseat = _udev_seat_get(em, dev); + if (!eseat) return; + + edev = _evdev_device_create(eseat, dev); + if (!edev) return; + + oname = libinput_device_get_output_name(dev); + eina_stringshare_replace(&edev->output_name, oname); + + eseat->devices = eina_list_append(eseat->devices, edev); +} + +static void +_device_remove(Elput_Manager *em, struct libinput_device *device) +{ + Elput_Seat *eseat; + Elput_Device *edev; + + edev = libinput_device_get_user_data(device); + if (!edev) return; + + eseat = _udev_seat_get(em, device); + if (eseat) + eseat->devices = eina_list_remove(eseat->devices, edev); + + _evdev_device_destroy(edev); +} + static int _udev_process_event(struct libinput_event *event) { @@ -40,11 +129,11 @@ _udev_process_event(struct libinput_event *event) { case LIBINPUT_EVENT_DEVICE_ADDED: DBG("Input Device Added: %s", libinput_device_get_name(dev)); - /* TODO: add device */ + _device_add(em, dev); break; case LIBINPUT_EVENT_DEVICE_REMOVED: DBG("Input Device Removed: %s", libinput_device_get_name(dev)); - /* TODO: remove device */ + _device_remove(em, dev); break; default: ret = 0; @@ -58,7 +147,7 @@ static void _process_event(struct libinput_event *event) { if (_udev_process_event(event)) return; - /* TODO: evdev processing */ + if (_evdev_event_process(event)) return; } static void @@ -136,12 +225,15 @@ udev_err: EAPI void elput_input_shutdown(Elput_Manager *manager) { + Elput_Seat *seat; + EINA_SAFETY_ON_NULL_RETURN(manager); EINA_SAFETY_ON_NULL_RETURN(&manager->input); if (manager->input.hdlr) ecore_main_fd_handler_del(manager->input.hdlr); - /* TODO */ + EINA_LIST_FREE(manager->input.seats, seat) + _udev_seat_destroy(seat); libinput_unref(manager->input.lib); } diff --git a/src/lib/elput/elput_private.h b/src/lib/elput/elput_private.h index 6d88943921..32ab797a7c 100644 --- a/src/lib/elput/elput_private.h +++ b/src/lib/elput/elput_private.h @@ -12,6 +12,7 @@ # include "Eldbus.h" # include +# include # include # include # include @@ -19,6 +20,7 @@ # include # include # include +# include # ifdef HAVE_SYSTEMD # include @@ -56,6 +58,13 @@ extern int _elput_log_dom; # endif # define CRIT(...) EINA_LOG_DOM_CRIT(_elput_log_dom, __VA_ARGS__) +typedef enum _Elput_Device_Capability +{ + EVDEV_SEAT_POINTER = (1 << 0), + EVDEV_SEAT_KEYBOARD = (1 << 1), + EVDEV_SEAT_TOUCH = (1 << 2) +} Elput_Device_Capability; + typedef struct _Elput_Interface { Eina_Bool (*connect)(Elput_Manager **manager, const char *seat, unsigned int tty, Eina_Bool sync); @@ -75,6 +84,129 @@ typedef struct _Elput_Input Eina_Bool suspended : 1; } Elput_Input; +typedef struct _Elput_Keyboard_Info +{ + int refs; + + struct + { + int fd; + size_t size; + char *area; + struct xkb_keymap *map; + } keymap; + + struct + { + xkb_mod_index_t shift; + xkb_mod_index_t caps; + xkb_mod_index_t ctrl; + xkb_mod_index_t alt; + xkb_mod_index_t altgr; + xkb_mod_index_t super; + } mods; +} Elput_Keyboard_Info; + +struct _Elput_Keyboard +{ + struct + { + unsigned int depressed; + unsigned int latched; + unsigned int locked; + unsigned int group; + } mods; + + struct + { + unsigned int key; + unsigned int timestamp; + } grab; + + Elput_Keyboard_Info *info; + + struct xkb_state *state; + struct xkb_keymap *pending_map; + struct xkb_context *context; + struct xkb_rule_names names; + + Elput_Seat *seat; + + Eina_Bool external_map : 1; +}; + +struct _Elput_Pointer +{ + double x, y; + int buttons; + unsigned int timestamp; + + int minx, miny; + int maxx, maxy; + int hotx, hoty; + + struct + { + double x, y; + unsigned int button; + unsigned int timestamp; + } grab; + + struct + { + unsigned int threshold; + unsigned int last_button, prev_button; + unsigned int last_time, prev_time; + Eina_Bool double_click : 1; + Eina_Bool triple_click : 1; + } mouse; + + Elput_Seat *seat; +}; + +struct _Elput_Touch +{ + double x, y; + int slot; + unsigned int points; + + struct + { + int id; + double x, y; + unsigned int timestamp; + } grab; + + Elput_Seat *seat; +}; + +struct _Elput_Seat +{ + const char *name; + + struct + { + int kbd, ptr, touch; + } count; + + Elput_Keyboard *kbd; + Elput_Pointer *ptr; + Elput_Touch *touch; + + Eina_List *devices; +}; + +struct _Elput_Device +{ + Elput_Seat *seat; + + const char *path; + const char *output_name; + struct libinput_device *device; + + Elput_Device_Capability caps; +}; + struct _Elput_Manager { Elput_Interface *interface; @@ -96,6 +228,13 @@ struct _Elput_Manager Eina_Bool sync : 1; }; +int _evdev_event_process(struct libinput_event *event); +Elput_Device *_evdev_device_create(Elput_Seat *seat, struct libinput_device *device); +void _evdev_device_destroy(Elput_Device *edev); +void _evdev_keyboard_destroy(Elput_Keyboard *kbd); +void _evdev_pointer_destroy(Elput_Pointer *ptr); +void _evdev_touch_destroy(Elput_Touch *touch); + extern Elput_Interface _logind_interface; #endif From b764978f29d86a3e42eac1de3e438e0932b4331f Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 6 Apr 2016 10:26:46 -0400 Subject: [PATCH 09/15] elput: Create and raise event when seat capabilities change Signed-off-by: Chris Michael --- src/lib/elput/Elput.h | 11 +++++++++++ src/lib/elput/elput.c | 6 ++++++ src/lib/elput/elput_evdev.c | 18 +++++++++++++++++- src/lib/elput/elput_logind.c | 21 ++++++++++++--------- 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/lib/elput/Elput.h b/src/lib/elput/Elput.h index f6ad5d219c..90cfe7717f 100644 --- a/src/lib/elput/Elput.h +++ b/src/lib/elput/Elput.h @@ -43,6 +43,17 @@ typedef struct _Elput_Pointer Elput_Pointer; /* opaque structure to represent a touch device */ typedef struct _Elput_Touch Elput_Touch; +/* structure to represent event for seat capability changes */ +typedef struct _Elput_Event_Seat_Caps +{ + int pointer_count; + int keyboard_count; + int touch_count; + Elput_Seat *seat; +} Elput_Event_Seat_Caps; + +EAPI extern int ELPUT_EVENT_SEAT_CAPS; + /** * @file * @brief Ecore functions for dealing with libinput diff --git a/src/lib/elput/elput.c b/src/lib/elput/elput.c index 1b5613fc3a..ef2ca6b783 100644 --- a/src/lib/elput/elput.c +++ b/src/lib/elput/elput.c @@ -6,6 +6,8 @@ static int _elput_init_count = 0; /* external variables */ int _elput_log_dom = -1; +EAPI int ELPUT_EVENT_SEAT_CAPS = -1; + EAPI int elput_init(void) { @@ -23,6 +25,8 @@ elput_init(void) goto log_err; } + ELPUT_EVENT_SEAT_CAPS = ecore_event_type_new(); + return _elput_init_count; log_err: @@ -43,6 +47,8 @@ elput_shutdown(void) if (_elput_init_count < 1) return 0; if (--_elput_init_count != 0) return _elput_init_count; + ELPUT_EVENT_SEAT_CAPS = -1; + eina_log_domain_unregister(_elput_log_dom); _elput_log_dom = -1; diff --git a/src/lib/elput/elput_evdev.c b/src/lib/elput/elput_evdev.c index 4c347386df..a0dc07e5cd 100644 --- a/src/lib/elput/elput_evdev.c +++ b/src/lib/elput/elput_evdev.c @@ -3,7 +3,17 @@ static void _seat_caps_update(Elput_Seat *seat) { - /* TODO: raise event for seat caps */ + Elput_Event_Seat_Caps *ev; + + ev = calloc(1, sizeof(Elput_Event_Seat_Caps)); + if (!ev) return; + + ev->pointer_count = seat->count.ptr; + ev->keyboard_count = seat->count.kbd; + ev->touch_count = seat->count.touch; + ev->seat = seat; + + ecore_event_add(ELPUT_EVENT_SEAT_CAPS, ev, NULL, NULL); } static int @@ -360,7 +370,13 @@ _evdev_event_process(struct libinput_event *event) if (frame) { + Elput_Device *edev; + edev = libinput_device_get_user_data(idev); + if (edev) + { + /* TODO: send seat frame event ?? */ + } } return ret; diff --git a/src/lib/elput/elput_logind.c b/src/lib/elput/elput_logind.c index c89ca2ae46..e829b4ac12 100644 --- a/src/lib/elput/elput_logind.c +++ b/src/lib/elput/elput_logind.c @@ -78,9 +78,10 @@ _cb_device_paused(void *data, const Eldbus_Message *msg) 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); */ + if ((em->sync) && (maj == 226)) // DRM_MAJOR + { + /* TODO: _ecore_drm2_launcher_activate_send(em, EINA_FALSE); */ + } } } @@ -102,9 +103,10 @@ _cb_device_resumed(void *data, const Eldbus_Message *msg) 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); */ + if ((em->sync) && (maj == 226)) // DRM_MAJOR + { + /* TODO: _ecore_drm2_launcher_activate_send(em, EINA_TRUE); */ + } } } @@ -123,9 +125,10 @@ _cb_property_changed(void *data, Eldbus_Proxy *proxy EINA_UNUSED, void *event) if (!strcmp(ev->name, "Active")) { eina_value_get(ev->value, &active); - /* TODO */ - /* if ((!em->sync) || (!active)) */ - /* _ecore_drm2_launcher_activate_send(em, active); */ + if ((!em->sync) || (!active)) + { + /* TODO: _ecore_drm2_launcher_activate_send(em, active); */ + } } } From 5db91e3802bd7084a2df7c79300e91e7b0d10ce6 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 6 Apr 2016 10:38:08 -0400 Subject: [PATCH 10/15] elput: Create and send seat frame events when we need to Signed-off-by: Chris Michael --- src/lib/elput/Elput.h | 7 +++++++ src/lib/elput/elput.c | 3 +++ src/lib/elput/elput_evdev.c | 17 +++++++++++++---- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/lib/elput/Elput.h b/src/lib/elput/Elput.h index 90cfe7717f..97b184bef4 100644 --- a/src/lib/elput/Elput.h +++ b/src/lib/elput/Elput.h @@ -52,7 +52,14 @@ typedef struct _Elput_Event_Seat_Caps Elput_Seat *seat; } Elput_Event_Seat_Caps; +/* structure to represent event for seat frame */ +typedef struct _Elput_Event_Seat_Frame +{ + Elput_Seat *seat; +} Elput_Event_Seat_Frame; + EAPI extern int ELPUT_EVENT_SEAT_CAPS; +EAPI extern int ELPUT_EVENT_SEAT_FRAME; /** * @file diff --git a/src/lib/elput/elput.c b/src/lib/elput/elput.c index ef2ca6b783..9a673dab6c 100644 --- a/src/lib/elput/elput.c +++ b/src/lib/elput/elput.c @@ -7,6 +7,7 @@ static int _elput_init_count = 0; int _elput_log_dom = -1; EAPI int ELPUT_EVENT_SEAT_CAPS = -1; +EAPI int ELPUT_EVENT_SEAT_FRAME = -1; EAPI int elput_init(void) @@ -26,6 +27,7 @@ elput_init(void) } ELPUT_EVENT_SEAT_CAPS = ecore_event_type_new(); + ELPUT_EVENT_SEAT_FRAME = ecore_event_type_new(); return _elput_init_count; @@ -48,6 +50,7 @@ elput_shutdown(void) if (--_elput_init_count != 0) return _elput_init_count; ELPUT_EVENT_SEAT_CAPS = -1; + ELPUT_EVENT_SEAT_FRAME = -1; eina_log_domain_unregister(_elput_log_dom); _elput_log_dom = -1; diff --git a/src/lib/elput/elput_evdev.c b/src/lib/elput/elput_evdev.c index a0dc07e5cd..2036d17546 100644 --- a/src/lib/elput/elput_evdev.c +++ b/src/lib/elput/elput_evdev.c @@ -16,6 +16,18 @@ _seat_caps_update(Elput_Seat *seat) ecore_event_add(ELPUT_EVENT_SEAT_CAPS, ev, NULL, NULL); } +static void +_seat_frame_send(Elput_Seat *seat) +{ + Elput_Event_Seat_Frame *ev; + + ev = calloc(1, sizeof(Elput_Event_Seat_Frame)); + if (!ev) return; + + ev->seat = seat; + ecore_event_add(ELPUT_EVENT_SEAT_FRAME, ev, NULL, NULL); +} + static int _keyboard_fd_get(off_t size) { @@ -373,10 +385,7 @@ _evdev_event_process(struct libinput_event *event) Elput_Device *edev; edev = libinput_device_get_user_data(idev); - if (edev) - { - /* TODO: send seat frame event ?? */ - } + if (edev) _seat_frame_send(edev->seat); } return ret; From b01666075d9c89dbba2ca279aa299f429784dec4 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 6 Apr 2016 13:23:36 -0400 Subject: [PATCH 11/15] elput: Add event structures for keymap and modifier sending events Signed-off-by: Chris Michael --- src/lib/elput/Elput.h | 18 ++++++++++++++++++ src/lib/elput/elput.c | 6 ++++++ src/lib/elput/elput_private.h | 1 + 3 files changed, 25 insertions(+) diff --git a/src/lib/elput/Elput.h b/src/lib/elput/Elput.h index 97b184bef4..f8808ceee8 100644 --- a/src/lib/elput/Elput.h +++ b/src/lib/elput/Elput.h @@ -58,8 +58,26 @@ typedef struct _Elput_Event_Seat_Frame Elput_Seat *seat; } Elput_Event_Seat_Frame; +/* structure to represent event for seat keymap changes */ +typedef struct _Elput_Event_Keymap_Send +{ + int fd, format; + size_t size; +} Elput_Event_Keymap_Send; + +/* structure to represent event for seat modifiers changes */ +typedef struct _Elput_Event_Modifiers_Send +{ + unsigned int depressed; + unsigned int latched; + unsigned int locked; + unsigned int group; +} Elput_Event_Modifiers_Send; + EAPI extern int ELPUT_EVENT_SEAT_CAPS; EAPI extern int ELPUT_EVENT_SEAT_FRAME; +EAPI extern int ELPUT_EVENT_KEYMAP_SEND; +EAPI extern int ELPUT_EVENT_MODIFIERS_SEND; /** * @file diff --git a/src/lib/elput/elput.c b/src/lib/elput/elput.c index 9a673dab6c..f65da98946 100644 --- a/src/lib/elput/elput.c +++ b/src/lib/elput/elput.c @@ -8,6 +8,8 @@ int _elput_log_dom = -1; EAPI int ELPUT_EVENT_SEAT_CAPS = -1; EAPI int ELPUT_EVENT_SEAT_FRAME = -1; +EAPI int ELPUT_EVENT_KEYMAP_SEND = -1; +EAPI int ELPUT_EVENT_MODIFIERS_SEND = -1; EAPI int elput_init(void) @@ -28,6 +30,8 @@ elput_init(void) ELPUT_EVENT_SEAT_CAPS = ecore_event_type_new(); ELPUT_EVENT_SEAT_FRAME = ecore_event_type_new(); + ELPUT_EVENT_KEYMAP_SEND = ecore_event_type_new(); + ELPUT_EVENT_MODIFIERS_SEND = ecore_event_type_new(); return _elput_init_count; @@ -51,6 +55,8 @@ elput_shutdown(void) ELPUT_EVENT_SEAT_CAPS = -1; ELPUT_EVENT_SEAT_FRAME = -1; + ELPUT_EVENT_KEYMAP_SEND = -1; + ELPUT_EVENT_MODIFIERS_SEND = -1; eina_log_domain_unregister(_elput_log_dom); _elput_log_dom = -1; diff --git a/src/lib/elput/elput_private.h b/src/lib/elput/elput_private.h index 32ab797a7c..4c1b7f1c8e 100644 --- a/src/lib/elput/elput_private.h +++ b/src/lib/elput/elput_private.h @@ -12,6 +12,7 @@ # include "Eldbus.h" # include +# include # include # include # include From 6a7589bf7805b31b532cd6acf972a3f87f65366f Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 6 Apr 2016 11:32:42 -0400 Subject: [PATCH 12/15] elput: Handle various events from libinput and pass to ecore_event Signed-off-by: Chris Michael --- src/lib/elput/elput_evdev.c | 819 ++++++++++++++++++++++++++++++++++ src/lib/elput/elput_private.h | 12 +- 2 files changed, 830 insertions(+), 1 deletion(-) diff --git a/src/lib/elput/elput_evdev.c b/src/lib/elput/elput_evdev.c index 2036d17546..6dd4da4103 100644 --- a/src/lib/elput/elput_evdev.c +++ b/src/lib/elput/elput_evdev.c @@ -28,6 +28,35 @@ _seat_frame_send(Elput_Seat *seat) ecore_event_add(ELPUT_EVENT_SEAT_FRAME, ev, NULL, NULL); } +static void +_keyboard_modifiers_update(Elput_Keyboard *kbd, Elput_Seat *seat) +{ + xkb_mod_mask_t mask; + + kbd->mods.depressed = + xkb_state_serialize_mods(kbd->state, XKB_STATE_DEPRESSED); + kbd->mods.latched = + xkb_state_serialize_mods(kbd->state, XKB_STATE_LATCHED); + kbd->mods.locked = + xkb_state_serialize_mods(kbd->state, XKB_STATE_LOCKED); + kbd->mods.group = + xkb_state_serialize_mods(kbd->state, XKB_STATE_EFFECTIVE); + + mask = (kbd->mods.depressed | kbd->mods.latched); + + seat->modifiers = 0; + if (mask & kbd->info->mods.ctrl) + seat->modifiers |= ECORE_EVENT_MODIFIER_CTRL; + if (mask & kbd->info->mods.alt) + seat->modifiers |= ECORE_EVENT_MODIFIER_ALT; + if (mask & kbd->info->mods.shift) + seat->modifiers |= ECORE_EVENT_MODIFIER_SHIFT; + if (mask & kbd->info->mods.super) + seat->modifiers |= ECORE_EVENT_MODIFIER_WIN; + if (mask & kbd->info->mods.altgr) + seat->modifiers |= ECORE_EVENT_MODIFIER_ALTGR; +} + static int _keyboard_fd_get(off_t size) { @@ -248,6 +277,245 @@ _keyboard_release(Elput_Seat *seat) } } +static void +_keyboard_key_send(Elput_Device *dev, enum libinput_key_state state, const char *keyname, const char *key, const char *compose, unsigned int code, unsigned int timestamp) +{ + Ecore_Event_Key *ev; + + ev = calloc(1, sizeof(Ecore_Event_Key) + strlen(key) + strlen(keyname) + + ((compose[0] != '\0') ? strlen(compose) : 0) + 3); + if (!ev) return; + + ev->keyname = (char *)(ev + 1); + ev->key = ev->keyname + strlen(keyname) + 1; + ev->compose = strlen(compose) ? ev->key + strlen(key) + 1 : NULL; + ev->string = ev->compose; + + strcpy((char *)ev->keyname, keyname); + strcpy((char *)ev->key, key); + if (strlen(compose)) strcpy((char *)ev->compose, compose); + + /* ev->string = ev->compose; */ + ev->keycode = code; + ev->modifiers = dev->seat->modifiers; + ev->timestamp = timestamp; + ev->same_screen = 1; + + ev->window = dev->window; + ev->event_window = dev->window; + ev->root_window = dev->window; + + if (state == LIBINPUT_KEY_STATE_PRESSED) + ecore_event_add(ECORE_EVENT_KEY_DOWN, ev, NULL, NULL); + else + ecore_event_add(ECORE_EVENT_KEY_UP, ev, NULL, NULL); +} + +static void +_keyboard_keymap_send(Elput_Keyboard_Info *info) +{ + Elput_Event_Keymap_Send *ev; + + ev = calloc(1, sizeof(Elput_Event_Keymap_Send)); + if (!ev) return; + + ev->fd = info->keymap.fd; + ev->size = info->keymap.size; + ev->format = XKB_KEYMAP_FORMAT_TEXT_V1; + + ecore_event_add(ELPUT_EVENT_KEYMAP_SEND, ev, NULL, NULL); +} + +static void +_keyboard_modifiers_send(Elput_Keyboard *kbd) +{ + Elput_Event_Modifiers_Send *ev; + + ev = calloc(1, sizeof(Elput_Event_Modifiers_Send)); + if (!ev) return; + + ev->depressed = kbd->mods.depressed; + ev->latched = kbd->mods.latched; + ev->locked = kbd->mods.locked; + ev->group = kbd->mods.group; + + ecore_event_add(ELPUT_EVENT_MODIFIERS_SEND, ev, NULL, NULL); +} + +static void +_keyboard_keymap_update(Elput_Seat *seat) +{ + Elput_Keyboard *kbd; + Elput_Keyboard_Info *info; + struct xkb_state *state; + xkb_mod_mask_t latched, locked; + + kbd = _evdev_keyboard_get(seat); + if (!kbd) return; + + info = _keyboard_info_create(kbd->pending_map, kbd->external_map); + xkb_keymap_unref(kbd->pending_map); + kbd->pending_map = NULL; + + if (!info) return; + + state = xkb_state_new(info->keymap.map); + if (!state) + { + _keyboard_info_destroy(info, kbd->external_map); + return; + } + + latched = xkb_state_serialize_mods(kbd->state, XKB_STATE_MODS_LATCHED); + locked = xkb_state_serialize_mods(kbd->state, XKB_STATE_MODS_LOCKED); + xkb_state_update_mask(state, 0, latched, locked, 0, 0, 0); + + _keyboard_info_destroy(kbd->info, kbd->external_map); + kbd->info = info; + + xkb_state_unref(kbd->state); + kbd->state = state; + + _keyboard_modifiers_update(kbd, seat); + _keyboard_keymap_send(kbd->info); + + if ((!latched) && (!locked)) return; + + _keyboard_modifiers_send(kbd); +} + +static int +_keyboard_keysym_translate(xkb_keysym_t keysym, unsigned int modifiers, char *buffer, int bytes) +{ + unsigned long hbytes = 0; + unsigned char c; + + if (!keysym) return 0; + hbytes = (keysym >> 8); + + if (!(bytes && + ((hbytes == 0) || + ((hbytes == 0xFF) && + (((keysym >= XKB_KEY_BackSpace) && (keysym <= XKB_KEY_Clear)) || + (keysym == XKB_KEY_Return) || (keysym == XKB_KEY_Escape) || + (keysym == XKB_KEY_KP_Space) || (keysym == XKB_KEY_KP_Tab) || + (keysym == XKB_KEY_KP_Enter) || + ((keysym >= XKB_KEY_KP_Multiply) && (keysym <= XKB_KEY_KP_9)) || + (keysym == XKB_KEY_KP_Equal) || (keysym == XKB_KEY_Delete)))))) + return 0; + + if (keysym == XKB_KEY_KP_Space) + c = (XKB_KEY_space & 0x7F); + else if (hbytes == 0xFF) + c = (keysym & 0x7F); + else + c = (keysym & 0xFF); + + if (modifiers & ECORE_EVENT_MODIFIER_CTRL) + { + if (((c >= '@') && (c < '\177')) || c == ' ') + c &= 0x1F; + else if (c == '2') + c = '\000'; + else if ((c >= '3') && (c <= '7')) + c -= ('3' - '\033'); + else if (c == '8') + c = '\177'; + else if (c == '/') + c = '_' & 0x1F; + } + buffer[0] = c; + return 1; +} + +static void +_keyboard_key(struct libinput_device *idevice, struct libinput_event_keyboard *event) +{ + Elput_Device *dev; + Elput_Keyboard *kbd; + enum libinput_key_state state; + xkb_keysym_t sym = XKB_KEY_NoSymbol; + const xkb_keysym_t *syms; + unsigned int code = 0; + unsigned int nsyms; + unsigned int timestamp; + char key[256], keyname[256], buffer[256]; + char *tmp = NULL, *compose = NULL; + int count; + + dev = libinput_device_get_user_data(idevice); + if (!dev) return; + + kbd = _evdev_keyboard_get(dev->seat); + if (!kbd) return; + + state = libinput_event_keyboard_get_key_state(event); + count = libinput_event_keyboard_get_seat_key_count(event); + + /* Ignore key events that are not seat wide state changes. */ + if (((state == LIBINPUT_KEY_STATE_PRESSED) && (count != 1)) || + ((state == LIBINPUT_KEY_STATE_RELEASED) && (count != 0))) + return; + + code = libinput_event_keyboard_get_key(event) + 8; + timestamp = libinput_event_keyboard_get_time(event); + + if (state == LIBINPUT_KEY_STATE_PRESSED) + xkb_state_update_key(kbd->state, code, XKB_KEY_DOWN); + else + xkb_state_update_key(kbd->state, code, XKB_KEY_UP); + + nsyms = xkb_key_get_syms(kbd->state, code, &syms); + if (nsyms == 1) sym = syms[0]; + + memset(key, 0, sizeof(key)); + xkb_keysym_get_name(sym, key, sizeof(key)); + + memset(keyname, 0, sizeof(keyname)); + memcpy(keyname, key, sizeof(keyname)); + + if (keyname[0] == '\0') + snprintf(keyname, sizeof(keyname), "Keycode-%u", code); + + if (xkb_state_mod_index_is_active(kbd->state, kbd->info->mods.shift, + XKB_STATE_MODS_EFFECTIVE)) + { + if (keyname[0] != '\0') + keyname[0] = tolower(keyname[0]); + } + + _keyboard_modifiers_update(kbd, dev->seat); + + memset(buffer, 0, sizeof(buffer)); + if (_keyboard_keysym_translate(sym, dev->seat->modifiers, + buffer, sizeof(buffer))) + { + compose = eina_str_convert("ISO8859-1", "UTF-8", buffer); + if (!compose) + { + ERR("Ecore_Drm2 cannot convert input key string '%s' to UTF-8. " + "Is Eina built with iconv support?", buffer); + } + else + tmp = compose; + } + + if (!compose) compose = buffer; + + _keyboard_key_send(dev, state, keyname, key, compose, code, timestamp); + + if (tmp) free(tmp); + + if ((kbd->pending_map) && (count == 0)) + _keyboard_keymap_update(dev->seat); + + if (state == LIBINPUT_KEY_STATE_PRESSED) + { + kbd->grab.key = code; + kbd->grab.timestamp = timestamp; + } +} + static Elput_Pointer * _pointer_create(Elput_Seat *seat) { @@ -348,6 +616,521 @@ _touch_release(Elput_Seat *seat) } } +static void +_pointer_motion_send(Elput_Device *edev) +{ + Elput_Pointer *ptr; + Elput_Keyboard *kbd; + Elput_Touch *touch; + Ecore_Event_Mouse_Move *ev; + double x, y; + + ptr = _evdev_pointer_get(edev->seat); + if (!ptr) return; + + ev = calloc(1, sizeof(Ecore_Event_Mouse_Move)); + if (!ev) return; + + x = ptr->x; + y = ptr->y; + + if (x < ptr->minx) + x = ptr->minx; + else if (x >= ptr->minx + ptr->maxw) + x = ptr->minx + ptr->maxw - 1; + + if (y < ptr->miny) + y = ptr->miny; + else if (y >= ptr->miny + ptr->maxh) + y = ptr->miny + ptr->maxh - 1; + + ev->window = edev->window; + ev->event_window = edev->window; + ev->root_window = edev->window; + ev->timestamp = ptr->timestamp; + ev->same_screen = 1; + + ev->x = x; + ev->y = y; + ev->root.x = x; + ev->root.y = y; + + kbd = _evdev_keyboard_get(edev->seat); + if (kbd) _keyboard_modifiers_update(kbd, edev->seat); + + ev->modifiers = edev->seat->modifiers; + + touch = _evdev_touch_get(edev->seat); + if (touch) ev->multi.device = touch->slot; + + ev->multi.radius = 1; + ev->multi.radius_x = 1; + ev->multi.radius_y = 1; + ev->multi.pressure = 1.0; + ev->multi.angle = 0.0; + ev->multi.x = ev->x; + ev->multi.y = ev->y; + ev->multi.root.x = ev->x; + ev->multi.root.y = ev->y; + + ecore_event_add(ECORE_EVENT_MOUSE_MOVE, ev, NULL, NULL); +} + +static Eina_Bool +_pointer_motion(struct libinput_device *idev, struct libinput_event_pointer *event) +{ + Elput_Device *edev; + Elput_Pointer *ptr; + double x, y; + + edev = libinput_device_get_user_data(idev); + if (!edev) return EINA_FALSE; + + ptr = _evdev_pointer_get(edev->seat); + if (!ptr) return EINA_FALSE; + + x = ptr->x + libinput_event_pointer_get_dx(event); + y = ptr->y + libinput_event_pointer_get_dy(event); + + if (x < ptr->minx) + x = ptr->minx; + else if (x >= ptr->minx + ptr->maxw) + x = ptr->minx + ptr->maxw - 1; + + if (y < ptr->miny) + y = ptr->miny; + else if (y >= ptr->miny + ptr->maxh) + y = ptr->miny + ptr->maxh - 1; + + ptr->x = x; + ptr->y = y; + ptr->timestamp = libinput_event_pointer_get_time(event); + + _pointer_motion_send(edev); + + return EINA_TRUE; +} + +static Eina_Bool +_pointer_motion_abs(struct libinput_device *idev, struct libinput_event_pointer *event) +{ + Elput_Device *edev; + Elput_Pointer *ptr; + + edev = libinput_device_get_user_data(idev); + if (!edev) return EINA_FALSE; + + ptr = _evdev_pointer_get(edev->seat); + if (!ptr) return EINA_FALSE; + + ptr->x = libinput_event_pointer_get_absolute_x_transformed(event, edev->ow); + ptr->y = libinput_event_pointer_get_absolute_y_transformed(event, edev->oh); + ptr->timestamp = libinput_event_pointer_get_time(event); + + /* TODO: these needs to run a matrix transform based on output */ + + _pointer_motion_send(edev); + + return EINA_TRUE; +} + +static void +_pointer_button_send(Elput_Device *edev, enum libinput_button_state state) +{ + Elput_Pointer *ptr; + Elput_Keyboard *kbd; + Elput_Touch *touch; + Ecore_Event_Mouse_Button *ev; + + ptr = _evdev_pointer_get(edev->seat); + if (!ptr) return; + + ev = calloc(1, sizeof(Ecore_Event_Mouse_Button)); + if (!ev) return; + + ev->window = edev->window; + ev->event_window = edev->window; + ev->root_window = edev->window; + ev->timestamp = ptr->timestamp; + ev->same_screen = 1; + + ev->x = ptr->x; + ev->y = ptr->y; + ev->root.x = ptr->x; + ev->root.y = ptr->y; + + touch = _evdev_touch_get(edev->seat); + if (touch) ev->multi.device = touch->slot; + ev->multi.radius = 1; + ev->multi.radius_x = 1; + ev->multi.radius_y = 1; + ev->multi.pressure = 1.0; + ev->multi.angle = 0.0; + ev->multi.x = ev->x; + ev->multi.y = ev->y; + ev->multi.root.x = ev->x; + ev->multi.root.y = ev->y; + + ev->buttons = ptr->buttons; + + ev->double_click = ptr->mouse.double_click; + ev->triple_click = ptr->mouse.triple_click; + + kbd = _evdev_keyboard_get(edev->seat); + if (kbd) + _keyboard_modifiers_update(kbd, edev->seat); + ev->modifiers = edev->seat->modifiers; + + if (state) + ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, ev, NULL, NULL); + else + ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, ev, NULL, NULL); +} + +static Eina_Bool +_pointer_button(struct libinput_device *idev, struct libinput_event_pointer *event) +{ + Elput_Device *edev; + Elput_Pointer *ptr; + int count; + enum libinput_button_state state; + unsigned int btn; + + edev = libinput_device_get_user_data(idev); + if (!edev) return EINA_FALSE; + + ptr = _evdev_pointer_get(edev->seat); + if (!ptr) return EINA_FALSE; + + state = libinput_event_pointer_get_button_state(event); + count = libinput_event_pointer_get_seat_button_count(event); + + /* Ignore button events that are not seat wide state changes. */ + if (((state == LIBINPUT_BUTTON_STATE_PRESSED) && (count != 1)) || + ((state == LIBINPUT_BUTTON_STATE_RELEASED) && (count != 0))) + return EINA_FALSE; + + btn = libinput_event_pointer_get_button(event); + + btn = ((btn & 0x00F) + 1); + if (btn == 3) btn = 2; + else if (btn == 2) btn = 3; + + ptr->buttons = btn; + ptr->timestamp = libinput_event_pointer_get_time(event); + + if (state) + { + unsigned int current; + + current = ptr->timestamp; + ptr->mouse.double_click = EINA_FALSE; + ptr->mouse.triple_click = EINA_FALSE; + + if (((current - ptr->mouse.prev_time) <= ptr->mouse.threshold) && + (btn == ptr->mouse.prev_button)) + { + ptr->mouse.double_click = EINA_TRUE; + if (((current - ptr->mouse.last_time) <= + (2 * ptr->mouse.threshold)) && + (btn == ptr->mouse.last_button)) + { + ptr->mouse.triple_click = EINA_TRUE; + ptr->mouse.prev_time = 0; + ptr->mouse.last_time = 0; + current = 0; + } + } + + ptr->mouse.last_time = ptr->mouse.prev_time; + ptr->mouse.prev_time = current; + ptr->mouse.last_button = ptr->mouse.prev_button; + ptr->mouse.prev_button = ptr->buttons; + } + + _pointer_button_send(edev, state); + + return EINA_TRUE; +} + +static void +_pointer_axis_send(Elput_Device *dev, int direction, int value) +{ + Elput_Pointer *ptr; + Elput_Keyboard *kbd; + Ecore_Event_Mouse_Wheel *ev; + + ptr = _evdev_pointer_get(dev->seat); + if (!ptr) return; + + ev = calloc(1, sizeof(Ecore_Event_Mouse_Wheel)); + if (!ev) return; + + ev->window = dev->window; + ev->event_window = dev->window; + ev->root_window = dev->window; + ev->timestamp = ptr->timestamp; + ev->same_screen = 1; + + ev->x = ptr->x; + ev->y = ptr->y; + ev->root.x = ptr->x; + ev->root.y = ptr->y; + + ev->z = value; + ev->direction = direction; + + kbd = _evdev_keyboard_get(dev->seat); + if (kbd) _keyboard_modifiers_update(kbd, dev->seat); + + ev->modifiers = dev->seat->modifiers; + + ecore_event_add(ECORE_EVENT_MOUSE_WHEEL, ev, NULL, NULL); +} + +static double +_pointer_axis_value(struct libinput_event_pointer *event, enum libinput_pointer_axis axis) +{ + enum libinput_pointer_axis_source source; + double val = 0.0; + + source = libinput_event_pointer_get_axis_source(event); + switch (source) + { + case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL: + val = 10 * libinput_event_pointer_get_axis_value_discrete(event, axis); + break; + case LIBINPUT_POINTER_AXIS_SOURCE_FINGER: + case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS: + val = libinput_event_pointer_get_axis_value(event, axis); + break; + } + + return val; +} + +static Eina_Bool +_pointer_axis(struct libinput_device *idevice, struct libinput_event_pointer *event) +{ + Elput_Device *dev; + Elput_Pointer *ptr; + enum libinput_pointer_axis axis; + Eina_Bool vert = EINA_FALSE, horiz = EINA_FALSE; + int dir = 0, val = 0; + + dev = libinput_device_get_user_data(idevice); + if (!dev) return EINA_FALSE; + + ptr = _evdev_pointer_get(dev->seat); + if (!ptr) return EINA_FALSE; + +#ifdef LIBINPUT_HIGHER_08 + vert = + libinput_event_pointer_has_axis(event, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); + horiz = + libinput_event_pointer_has_axis(event, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); + if ((!vert) && (!horiz)) return EINA_FALSE; + + if (vert) + { + axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL; + val = _pointer_axis_value(event, axis); + } + + if (horiz) + { + axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL; + val = _pointer_axis_value(event, axis); + dir = 1; + } + +#else + axis = libinput_event_pointer_get_axis(event); + if (axis == LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL) dir = 1; + val = libinput_event_pointer_get_axis_value(event); +#endif + + ptr->timestamp = libinput_event_pointer_get_time(event); + + _pointer_axis_send(dev, dir, val); + + return EINA_TRUE; +} + +static void +_touch_event_send(Elput_Device *dev, struct libinput_event_touch *event, int type) +{ + Elput_Touch *touch; + Ecore_Event_Mouse_Button *ev; + unsigned int btn = 0; + + touch = _evdev_touch_get(dev->seat); + if (!touch) return; + + ev = calloc(1, sizeof(Ecore_Event_Mouse_Button)); + if (!ev) return; + + ev->window = dev->window; + ev->event_window = dev->window; + ev->root_window = dev->window; + ev->timestamp = libinput_event_touch_get_time(event); + ev->same_screen = 1; + + ev->x = touch->x; + ev->y = touch->y; + ev->root.x = touch->x; + ev->root.y = touch->y; + + ev->modifiers = dev->seat->modifiers; + + ev->multi.device = touch->slot; + ev->multi.radius = 1; + ev->multi.radius_x = 1; + ev->multi.radius_y = 1; + ev->multi.pressure = 1.0; + ev->multi.angle = 0.0; + ev->multi.x = ev->x; + ev->multi.y = ev->y; + ev->multi.root.x = ev->x; + ev->multi.root.y = ev->y; + + btn = ((btn & 0x00F) + 1); + if (btn == 3) btn = 2; + else if (btn == 2) btn = 3; + ev->buttons = btn; + + ecore_event_add(type, ev, NULL, NULL); +} + +static void +_touch_down(struct libinput_device *idevice, struct libinput_event_touch *event) +{ + Elput_Device *dev; + Elput_Touch *touch; + unsigned int timestamp; + int slot; + + dev = libinput_device_get_user_data(idevice); + if (!dev) return; + + touch = _evdev_touch_get(dev->seat); + if (!touch) return; + + slot = libinput_event_touch_get_seat_slot(event); + timestamp = libinput_event_touch_get_time(event); + + touch->x = libinput_event_touch_get_x_transformed(event, dev->ow); + touch->y = libinput_event_touch_get_y_transformed(event, dev->oh); + + /* TODO: these needs to run a matrix transform based on output */ + /* _ecore_drm2_output_coordinate_transform(dev->output, */ + /* touch->x, touch->y, */ + /* &touch->x, &touch->y); */ + + if (slot == touch->grab.id) + { + touch->grab.x = touch->x; + touch->grab.y = touch->y; + } + + touch->slot = slot; + touch->points++; + + _touch_event_send(dev, event, ECORE_EVENT_MOUSE_BUTTON_DOWN); + + if (touch->points == 1) + { + touch->grab.id = slot; + touch->grab.x = touch->x; + touch->grab.y = touch->y; + touch->grab.timestamp = timestamp; + } +} + +static void +_touch_up(struct libinput_device *idevice, struct libinput_event_touch *event) +{ + Elput_Device *dev; + Elput_Touch *touch; + + dev = libinput_device_get_user_data(idevice); + if (!dev) return; + + touch = _evdev_touch_get(dev->seat); + if (!touch) return; + + touch->points--; + touch->slot = libinput_event_touch_get_seat_slot(event); + + _touch_event_send(dev, event, ECORE_EVENT_MOUSE_BUTTON_UP); +} + +static void +_touch_motion_send(Elput_Device *dev, struct libinput_event_touch *event) +{ + Elput_Touch *touch; + Ecore_Event_Mouse_Move *ev; + + touch = _evdev_touch_get(dev->seat); + if (!touch) return; + + ev = calloc(1, sizeof(Ecore_Event_Mouse_Move)); + if (!ev) return; + + ev->window = dev->window; + ev->event_window = dev->window; + ev->root_window = dev->window; + ev->timestamp = libinput_event_touch_get_time(event); + ev->same_screen = 1; + + ev->x = touch->x; + ev->y = touch->y; + ev->root.x = touch->x; + ev->root.y = touch->y; + + ev->modifiers = dev->seat->modifiers; + + ev->multi.device = touch->slot; + ev->multi.radius = 1; + ev->multi.radius_x = 1; + ev->multi.radius_y = 1; + ev->multi.pressure = 1.0; + ev->multi.angle = 0.0; + ev->multi.x = ev->x; + ev->multi.y = ev->y; + ev->multi.root.x = ev->x; + ev->multi.root.y = ev->y; + + ecore_event_add(ECORE_EVENT_MOUSE_MOVE, ev, NULL, NULL); +} + +static void +_touch_motion(struct libinput_device *idevice, struct libinput_event_touch *event) +{ + Elput_Device *dev; + Elput_Touch *touch; + + dev = libinput_device_get_user_data(idevice); + if (!dev) return; + + touch = _evdev_touch_get(dev->seat); + if (!touch) return; + + touch->x = libinput_event_touch_get_x_transformed(event, dev->ow); + touch->y = libinput_event_touch_get_y_transformed(event, dev->oh); + + /* TODO: these needs to run a matrix transform based on output */ + /* _ecore_drm2_output_coordinate_transform(dev->output, */ + /* touch->x, touch->y, */ + /* &touch->x, &touch->y); */ + + touch->slot = libinput_event_touch_get_seat_slot(event); + + _touch_motion_send(dev, event); +} + int _evdev_event_process(struct libinput_event *event) { @@ -359,20 +1142,32 @@ _evdev_event_process(struct libinput_event *event) switch (libinput_event_get_type(event)) { case LIBINPUT_EVENT_KEYBOARD_KEY: + _keyboard_key(idev, libinput_event_get_keyboard_event(event)); break; case LIBINPUT_EVENT_POINTER_MOTION: + frame = + _pointer_motion(idev, libinput_event_get_pointer_event(event)); break; case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: + frame = + _pointer_motion_abs(idev, libinput_event_get_pointer_event(event)); break; case LIBINPUT_EVENT_POINTER_BUTTON: + frame = + _pointer_button(idev, libinput_event_get_pointer_event(event)); break; case LIBINPUT_EVENT_POINTER_AXIS: + frame = + _pointer_axis(idev, libinput_event_get_pointer_event(event)); break; case LIBINPUT_EVENT_TOUCH_DOWN: + _touch_down(idev, libinput_event_get_touch_event(event)); break; case LIBINPUT_EVENT_TOUCH_MOTION: + _touch_motion(idev, libinput_event_get_touch_event(event)); break; case LIBINPUT_EVENT_TOUCH_UP: + _touch_up(idev, libinput_event_get_touch_event(event)); break; case LIBINPUT_EVENT_TOUCH_FRAME: default: @@ -487,3 +1282,27 @@ _evdev_touch_destroy(Elput_Touch *touch) /* FIXME: destroy any resources inside touch structure */ free(touch); } + +Elput_Pointer * +_evdev_pointer_get(Elput_Seat *seat) +{ + if (!seat) return NULL; + if (seat->count.ptr) return seat->ptr; + return NULL; +} + +Elput_Keyboard * +_evdev_keyboard_get(Elput_Seat *seat) +{ + if (!seat) return NULL; + if (seat->count.kbd) return seat->kbd; + return NULL; +} + +Elput_Touch * +_evdev_touch_get(Elput_Seat *seat) +{ + if (!seat) return NULL; + if (seat->count.touch) return seat->touch; + return NULL; +} diff --git a/src/lib/elput/elput_private.h b/src/lib/elput/elput_private.h index 4c1b7f1c8e..8dc2752185 100644 --- a/src/lib/elput/elput_private.h +++ b/src/lib/elput/elput_private.h @@ -143,7 +143,7 @@ struct _Elput_Pointer unsigned int timestamp; int minx, miny; - int maxx, maxy; + int maxw, maxh; int hotx, hoty; struct @@ -190,6 +190,8 @@ struct _Elput_Seat int kbd, ptr, touch; } count; + unsigned int modifiers; + Elput_Keyboard *kbd; Elput_Pointer *ptr; Elput_Touch *touch; @@ -201,6 +203,10 @@ struct _Elput_Device { Elput_Seat *seat; + /* TODO: we will need an API to set this */ + uint32_t window; + uint32_t ow, oh; + const char *path; const char *output_name; struct libinput_device *device; @@ -236,6 +242,10 @@ void _evdev_keyboard_destroy(Elput_Keyboard *kbd); void _evdev_pointer_destroy(Elput_Pointer *ptr); void _evdev_touch_destroy(Elput_Touch *touch); +Elput_Pointer *_evdev_pointer_get(Elput_Seat *seat); +Elput_Keyboard *_evdev_keyboard_get(Elput_Seat *seat); +Elput_Touch *_evdev_touch_get(Elput_Seat *seat); + extern Elput_Interface _logind_interface; #endif From 6c85fe751488c344f1c0cff8e9f3dd013bf5f66d Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Thu, 7 Apr 2016 09:00:18 -0400 Subject: [PATCH 13/15] elput: Add event which can be raised when devices get added or removed Signed-off-by: Chris Michael --- src/lib/elput/Elput.h | 14 +++++++++++ src/lib/elput/elput.c | 3 +++ src/lib/elput/elput_input.c | 50 ++++++++++++++++++++++++++++++++----- 3 files changed, 61 insertions(+), 6 deletions(-) diff --git a/src/lib/elput/Elput.h b/src/lib/elput/Elput.h index f8808ceee8..385ea4eb24 100644 --- a/src/lib/elput/Elput.h +++ b/src/lib/elput/Elput.h @@ -74,10 +74,24 @@ typedef struct _Elput_Event_Modifiers_Send unsigned int group; } Elput_Event_Modifiers_Send; +typedef enum _Elput_Device_Change_Type +{ + ELPUT_DEVICE_ADDED, + ELPUT_DEVICE_REMOVED, +} Elput_Device_Change_Type; + +/* structure to represent event for device being added or removed */ +typedef struct _Elput_Event_Device_Change +{ + Elput_Device *device; + Elput_Device_Change_Type type; +} Elput_Event_Device_Change; + EAPI extern int ELPUT_EVENT_SEAT_CAPS; EAPI extern int ELPUT_EVENT_SEAT_FRAME; EAPI extern int ELPUT_EVENT_KEYMAP_SEND; EAPI extern int ELPUT_EVENT_MODIFIERS_SEND; +EAPI extern int ELPUT_EVENT_DEVICE_CHANGE; /** * @file diff --git a/src/lib/elput/elput.c b/src/lib/elput/elput.c index f65da98946..2e54b3ec28 100644 --- a/src/lib/elput/elput.c +++ b/src/lib/elput/elput.c @@ -10,6 +10,7 @@ EAPI int ELPUT_EVENT_SEAT_CAPS = -1; EAPI int ELPUT_EVENT_SEAT_FRAME = -1; EAPI int ELPUT_EVENT_KEYMAP_SEND = -1; EAPI int ELPUT_EVENT_MODIFIERS_SEND = -1; +EAPI int ELPUT_EVENT_DEVICE_CHANGE = -1; EAPI int elput_init(void) @@ -32,6 +33,7 @@ elput_init(void) ELPUT_EVENT_SEAT_FRAME = ecore_event_type_new(); ELPUT_EVENT_KEYMAP_SEND = ecore_event_type_new(); ELPUT_EVENT_MODIFIERS_SEND = ecore_event_type_new(); + ELPUT_EVENT_DEVICE_CHANGE = ecore_event_type_new(); return _elput_init_count; @@ -57,6 +59,7 @@ elput_shutdown(void) ELPUT_EVENT_SEAT_FRAME = -1; ELPUT_EVENT_KEYMAP_SEND = -1; ELPUT_EVENT_MODIFIERS_SEND = -1; + ELPUT_EVENT_DEVICE_CHANGE = -1; eina_log_domain_unregister(_elput_log_dom); _elput_log_dom = -1; diff --git a/src/lib/elput/elput_input.c b/src/lib/elput/elput_input.c index 499efcf48b..6c43f2f03d 100644 --- a/src/lib/elput/elput_input.c +++ b/src/lib/elput/elput_input.c @@ -78,6 +78,41 @@ _udev_seat_get(Elput_Manager *em, struct libinput_device *device) return _udev_seat_named_get(em, name); } +static void +_device_event_cb_free(void *data EINA_UNUSED, void *event) +{ + Elput_Event_Device_Change *ev; + + ev = event; + + if (ev->type == ELPUT_DEVICE_REMOVED) + { + Elput_Seat *seat; + + seat = ev->device->seat; + if (seat) + seat->devices = eina_list_remove(seat->devices, ev->device); + + _evdev_device_destroy(ev->device); + } + + free(ev); +} + +static void +_device_event_send(Elput_Device *edev, Elput_Device_Change_Type type) +{ + Elput_Event_Device_Change *ev; + + ev = calloc(1, sizeof(Elput_Event_Device_Change)); + if (!ev) return; + + ev->device = edev; + ev->type = type; + + ecore_event_add(ELPUT_EVENT_DEVICE_CHANGE, ev, _device_event_cb_free, NULL); +} + static void _device_add(Elput_Manager *em, struct libinput_device *dev) { @@ -95,22 +130,25 @@ _device_add(Elput_Manager *em, struct libinput_device *dev) eina_stringshare_replace(&edev->output_name, oname); eseat->devices = eina_list_append(eseat->devices, edev); + + _device_event_send(edev, ELPUT_DEVICE_ADDED); } static void -_device_remove(Elput_Manager *em, struct libinput_device *device) +_device_remove(Elput_Manager *em EINA_UNUSED, struct libinput_device *device) { - Elput_Seat *eseat; + /* Elput_Seat *eseat; */ Elput_Device *edev; edev = libinput_device_get_user_data(device); if (!edev) return; - eseat = _udev_seat_get(em, device); - if (eseat) - eseat->devices = eina_list_remove(eseat->devices, edev); + /* eseat = _udev_seat_get(em, device); */ + /* if (eseat) */ + /* eseat->devices = eina_list_remove(eseat->devices, edev); */ - _evdev_device_destroy(edev); + _device_event_send(edev, ELPUT_DEVICE_REMOVED); + /* _evdev_device_destroy(edev); */ } static int From 404b3049f3339e4ea95c116312386b3d19d1c99c Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Thu, 7 Apr 2016 09:08:00 -0400 Subject: [PATCH 14/15] elput: Add API function to set input window Signed-off-by: Chris Michael --- src/lib/elput/Elput.h | 24 ++++++++++++++++++++++++ src/lib/elput/elput_evdev.c | 8 ++++++++ 2 files changed, 32 insertions(+) diff --git a/src/lib/elput/Elput.h b/src/lib/elput/Elput.h index 385ea4eb24..06a027d68c 100644 --- a/src/lib/elput/Elput.h +++ b/src/lib/elput/Elput.h @@ -105,6 +105,7 @@ EAPI extern int ELPUT_EVENT_DEVICE_CHANGE; * @li @ref Elput_Init_Group * @li @ref Elput_Manager_Group * @li @ref Elput_Input_Group + * @li @ref Elput_Device_Group * */ @@ -221,6 +222,29 @@ EAPI Eina_Bool elput_input_init(Elput_Manager *manager, const char *seat); */ EAPI void elput_input_shutdown(Elput_Manager *manager); +/** + * @defgroup Elput_Device_Group + * + * Functions that deal with input devices. + */ + +/** + * Set which window to use for this input device + * + * @brief This function should be used to specify which window to set on the + * input device. Setting a window on the input device is done so that + * when we raise events (mouse movement, keyboard key, etc) then + * this window is passed to the event structure as the window which + * the event occured on. + * + * @param device + * @param window + * + * @ingroup Elput_Device_Group + * @since 1.18 + */ +EAPI void elput_device_window_set(Elput_Device *device, unsigned int window); + # endif # undef EAPI diff --git a/src/lib/elput/elput_evdev.c b/src/lib/elput/elput_evdev.c index 6dd4da4103..4b6955d103 100644 --- a/src/lib/elput/elput_evdev.c +++ b/src/lib/elput/elput_evdev.c @@ -1306,3 +1306,11 @@ _evdev_touch_get(Elput_Seat *seat) if (seat->count.touch) return seat->touch; return NULL; } + +EAPI void +elput_device_window_set(Elput_Device *device, unsigned int window) +{ + EINA_SAFETY_ON_NULL_RETURN(device); + + device->window = window; +} From 43360ca98a60e20d268251aca00a3650f56d7a84 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Thu, 7 Apr 2016 09:10:48 -0400 Subject: [PATCH 15/15] elput: Add API function to set output size on an input device This function is used to adjust device calibration based on size of output Signed-off-by: Chris Michael --- src/lib/elput/Elput.h | 12 +++++++ src/lib/elput/elput_evdev.c | 67 +++++++++++++++++++++++++++++++++++ src/lib/elput/elput_private.h | 1 - 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/src/lib/elput/Elput.h b/src/lib/elput/Elput.h index 06a027d68c..a1ac7213b6 100644 --- a/src/lib/elput/Elput.h +++ b/src/lib/elput/Elput.h @@ -245,6 +245,18 @@ EAPI void elput_input_shutdown(Elput_Manager *manager); */ EAPI void elput_device_window_set(Elput_Device *device, unsigned int window); +/** + * Set size of output for input device calibration + * + * @param device + * @param w + * @param h + * + * @ingroup Elput_Device_Group + * @since 1.18 + */ +EAPI void elput_device_output_size_set(Elput_Device *device, int w, int h); + # endif # undef EAPI diff --git a/src/lib/elput/elput_evdev.c b/src/lib/elput/elput_evdev.c index 4b6955d103..45ccefbcd6 100644 --- a/src/lib/elput/elput_evdev.c +++ b/src/lib/elput/elput_evdev.c @@ -1131,6 +1131,49 @@ _touch_motion(struct libinput_device *idevice, struct libinput_event_touch *even _touch_motion_send(dev, event); } +static void +_evdev_device_calibrate(Elput_Device *dev) +{ + float cal[6]; + const char *vals; + const char *sysname; + const char *device; + Eina_List *devices; + int w = 0, h = 0; + enum libinput_config_status status; + + w = dev->ow; + h = dev->oh; + if ((w == 0) || (h == 0)) return; + + if ((!libinput_device_config_calibration_has_matrix(dev->device)) || + (libinput_device_config_calibration_get_default_matrix(dev->device, cal))) + return; + + sysname = libinput_device_get_sysname(dev->device); + + devices = eeze_udev_find_by_subsystem_sysname("input", sysname); + EINA_LIST_FREE(devices, device) + { + vals = eeze_udev_syspath_get_property(device, "WL_CALIBRATION"); + if ((!vals) || + (sscanf(vals, "%f %f %f %f %f %f", + &cal[0], &cal[1], &cal[2], &cal[3], &cal[4], &cal[5]) != 6)) + goto cont; + + cal[2] /= w; + cal[5] /= h; + + status = + libinput_device_config_calibration_set_matrix(dev->device, cal); + if (status != LIBINPUT_CONFIG_STATUS_SUCCESS) + WRN("Failed to apply device calibration"); + +cont: + eina_stringshare_del(device); + } +} + int _evdev_event_process(struct libinput_event *event) { @@ -1314,3 +1357,27 @@ elput_device_window_set(Elput_Device *device, unsigned int window) device->window = window; } + +EAPI void +elput_device_output_size_set(Elput_Device *device, int w, int h) +{ + EINA_SAFETY_ON_NULL_RETURN(device); + + device->ow = w; + device->oh = h; + + if (libinput_device_has_capability(device->device, + LIBINPUT_DEVICE_CAP_POINTER)) + { + Elput_Pointer *ptr; + + ptr = _evdev_pointer_get(device->seat); + if (ptr) + { + ptr->x = device->ow / 2; + ptr->y = device->oh / 2; + } + } + + _evdev_device_calibrate(device); +} diff --git a/src/lib/elput/elput_private.h b/src/lib/elput/elput_private.h index 8dc2752185..3564161375 100644 --- a/src/lib/elput/elput_private.h +++ b/src/lib/elput/elput_private.h @@ -203,7 +203,6 @@ struct _Elput_Device { Elput_Seat *seat; - /* TODO: we will need an API to set this */ uint32_t window; uint32_t ow, oh;