forked from enlightenment/efl
Merge branch 'devs/devilhorns/elput'
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. Elput currently uses systemd-logind by default to open/close input devices, but has the ability for other methods (direct opening) to be easily added through the Manager implementation. NB: This library is merged with EFL_BETA_API_SUPPORT and is subject to API changes.
This commit is contained in:
commit
f20eb4eba7
|
@ -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 = \
|
||||
|
|
71
configure.ac
71
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}"
|
||||
|
|
|
@ -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@
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
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_evdev.c \
|
||||
lib/elput/elput_input.c \
|
||||
lib/elput/elput_logind.c \
|
||||
lib/elput/elput_manager.c \
|
||||
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@
|
||||
|
||||
### 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
|
|
@ -0,0 +1,265 @@
|
|||
#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
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* structure to represent event for seat frame */
|
||||
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;
|
||||
|
||||
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
|
||||
* @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
|
||||
* @li @ref Elput_Manager_Group
|
||||
* @li @ref Elput_Input_Group
|
||||
* @li @ref Elput_Device_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);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* 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
|
||||
# define EAPI
|
||||
|
||||
#endif
|
|
@ -0,0 +1,73 @@
|
|||
#include "elput_private.h"
|
||||
|
||||
/* local variables */
|
||||
static int _elput_init_count = 0;
|
||||
|
||||
/* external variables */
|
||||
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_EVENT_DEVICE_CHANGE = -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;
|
||||
}
|
||||
|
||||
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();
|
||||
ELPUT_EVENT_DEVICE_CHANGE = ecore_event_type_new();
|
||||
|
||||
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;
|
||||
|
||||
ELPUT_EVENT_SEAT_CAPS = -1;
|
||||
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;
|
||||
|
||||
eeze_shutdown();
|
||||
ecore_event_shutdown();
|
||||
ecore_shutdown();
|
||||
eina_shutdown();
|
||||
|
||||
return _elput_init_count;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,277 @@
|
|||
#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 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_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)
|
||||
{
|
||||
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);
|
||||
|
||||
_device_event_send(edev, ELPUT_DEVICE_ADDED);
|
||||
}
|
||||
|
||||
static void
|
||||
_device_remove(Elput_Manager *em EINA_UNUSED, 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); */
|
||||
|
||||
_device_event_send(edev, ELPUT_DEVICE_REMOVED);
|
||||
/* _evdev_device_destroy(edev); */
|
||||
}
|
||||
|
||||
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));
|
||||
_device_add(em, dev);
|
||||
break;
|
||||
case LIBINPUT_EVENT_DEVICE_REMOVED:
|
||||
DBG("Input Device Removed: %s", libinput_device_get_name(dev));
|
||||
_device_remove(em, dev);
|
||||
break;
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
_process_event(struct libinput_event *event)
|
||||
{
|
||||
if (_udev_process_event(event)) return;
|
||||
if (_evdev_event_process(event)) return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
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);
|
||||
|
||||
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:
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
EINA_LIST_FREE(manager->input.seats, seat)
|
||||
_udev_seat_destroy(seat);
|
||||
|
||||
libinput_unref(manager->input.lib);
|
||||
}
|
|
@ -0,0 +1,569 @@
|
|||
#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);
|
||||
|
||||
if ((em->sync) && (maj == 226)) // DRM_MAJOR
|
||||
{
|
||||
/* TODO: _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))
|
||||
{
|
||||
if ((em->sync) && (maj == 226)) // DRM_MAJOR
|
||||
{
|
||||
/* TODO: _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);
|
||||
if ((!em->sync) || (!active))
|
||||
{
|
||||
/* TODO: _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 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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
_logind_open,
|
||||
_logind_close,
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,64 @@
|
|||
#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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
|
@ -0,0 +1,250 @@
|
|||
#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 <Elput.h>
|
||||
|
||||
# include <ctype.h>
|
||||
# include <sys/mman.h>
|
||||
# include <fcntl.h>
|
||||
# include <unistd.h>
|
||||
# include <linux/vt.h>
|
||||
# include <linux/kd.h>
|
||||
# include <linux/major.h>
|
||||
# include <linux/input.h>
|
||||
# include <libinput.h>
|
||||
# include <xkbcommon/xkbcommon.h>
|
||||
|
||||
# ifdef HAVE_SYSTEMD
|
||||
# include <systemd/sd-login.h>
|
||||
# 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__)
|
||||
|
||||
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);
|
||||
void (*disconnect)(Elput_Manager *manager);
|
||||
int (*open)(Elput_Manager *manager, const char *path, int flags);
|
||||
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;
|
||||
|
||||
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 maxw, maxh;
|
||||
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;
|
||||
|
||||
unsigned int modifiers;
|
||||
|
||||
Elput_Keyboard *kbd;
|
||||
Elput_Pointer *ptr;
|
||||
Elput_Touch *touch;
|
||||
|
||||
Eina_List *devices;
|
||||
};
|
||||
|
||||
struct _Elput_Device
|
||||
{
|
||||
Elput_Seat *seat;
|
||||
|
||||
uint32_t window;
|
||||
uint32_t ow, oh;
|
||||
|
||||
const char *path;
|
||||
const char *output_name;
|
||||
struct libinput_device *device;
|
||||
|
||||
Elput_Device_Capability caps;
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
Elput_Input input;
|
||||
|
||||
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);
|
||||
|
||||
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
|
|
@ -0,0 +1,29 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#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;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef _ELPUT_SUITE_H
|
||||
# define _ELPUT_SUITE_H
|
||||
|
||||
# include <check.h>
|
||||
|
||||
void elput_test_elput(TCase *tc);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,29 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <Eina.h>
|
||||
#include <Ecore.h>
|
||||
#include <Elput.h>
|
||||
|
||||
#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);
|
||||
}
|
Loading…
Reference in New Issue