summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Michael <cpmichael@osg.samsung.com>2016-04-13 14:16:39 -0400
committerChris Michael <cpmichael@osg.samsung.com>2016-04-13 14:16:39 -0400
commitf20eb4eba7321cfc6907bdcc2e3baca16066be2a (patch)
treea4ddd3edcd2dd0ba834d93f9766ef6d7bf84f403
parentc23a61a49caebca1244fad484cae403bf7a0a0fd (diff)
parent43360ca98a60e20d268251aca00a3650f56d7a84 (diff)
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.
-rw-r--r--Makefile.am4
-rw-r--r--configure.ac71
-rw-r--r--pc/elput.pc.in12
-rw-r--r--src/Makefile.am1
-rw-r--r--src/Makefile_Elput.am59
-rw-r--r--src/lib/elput/Elput.h265
-rw-r--r--src/lib/elput/elput.c73
-rw-r--r--src/lib/elput/elput_evdev.c1383
-rw-r--r--src/lib/elput/elput_input.c277
-rw-r--r--src/lib/elput/elput_logind.c569
-rw-r--r--src/lib/elput/elput_manager.c64
-rw-r--r--src/lib/elput/elput_private.h250
-rw-r--r--src/tests/elput/elput_suite.c29
-rw-r--r--src/tests/elput/elput_suite.h8
-rw-r--r--src/tests/elput/elput_test_elput.c29
15 files changed, 3094 insertions, 0 deletions
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
286pkgconfig_DATA += pc/ecore-buffer.pc 286pkgconfig_DATA += pc/ecore-buffer.pc
287endif 287endif
288 288
289if HAVE_ELPUT
290pkgconfig_DATA += pc/elput.pc
291endif
292
289# Cmake configs: 293# Cmake configs:
290efl_cmakeconfigdir = $(libdir)/cmake/Efl/ 294efl_cmakeconfigdir = $(libdir)/cmake/Efl/
291efl_cmakeconfig_DATA = \ 295efl_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],
1984 ], 1984 ],
1985 [want_ecore_buffer="no"]) 1985 [want_ecore_buffer="no"])
1986 1986
1987AC_ARG_ENABLE([elput],
1988 [AS_HELP_STRING([--enable-elput],[enable elput library. @<:@default=disabled@:>@])],
1989 [
1990 if test "x${enableval}" = "xyes" ; then
1991 want_elput="yes"
1992 else
1993 want_elput="no"
1994 fi
1995 ],
1996 [want_elput="no"])
1997
1987# Image Loaders 1998# Image Loaders
1988 1999
1989ARG_ENABLE_EVAS_IMAGE_LOADER(BMP, static) 2000ARG_ENABLE_EVAS_IMAGE_LOADER(BMP, static)
@@ -3566,6 +3577,64 @@ EFL_LIB_END_OPTIONAL([Ecore_Drm])
3566#### End of Ecore_Drm 3577#### End of Ecore_Drm
3567 3578
3568 3579
3580#### Elput
3581have_libinput_new="no"
3582EFL_LIB_START_OPTIONAL([Elput], [test "${want_elput}" = "yes"])
3583
3584### Additional options to configure
3585SUID_CFLAGS=-fPIE
3586SUID_LDFLAGS=-pie
3587AC_SUBST([SUID_CFLAGS])
3588AC_SUBST([SUID_LDFLAGS])
3589
3590### Default values
3591
3592### Checks for programs
3593
3594### Checks for libraries
3595EFL_INTERNAL_DEPEND_PKG([ELPUT], [ecore])
3596EFL_INTERNAL_DEPEND_PKG([ELPUT], [ecore-input])
3597EFL_INTERNAL_DEPEND_PKG([ELPUT], [eldbus])
3598EFL_INTERNAL_DEPEND_PKG([ELPUT], [eeze])
3599EFL_INTERNAL_DEPEND_PKG([ELPUT], [eo])
3600EFL_INTERNAL_DEPEND_PKG([ELPUT], [eina])
3601
3602EFL_DEPEND_PKG([ELPUT], [LIBINPUT], [libinput >= 0.6.0 xkbcommon >= 0.3.0])
3603
3604EFL_ADD_LIBS([ELPUT], [-lm])
3605
3606# API change from 0.7 to 0.8. So we define this to support both for now.
3607PKG_CHECK_EXISTS([libinput >= 0.8.0],
3608 [have_libinput_new="yes"],
3609 [have_libinput_new="no"])
3610AC_MSG_CHECKING([Use new libinput API (newer than 0.8.0)])
3611AC_MSG_RESULT([${have_libinput_new}])
3612if test "x${have_libinput_new}" = "xyes";then
3613 AC_DEFINE_UNQUOTED([LIBINPUT_HIGHER_08], [1], [libinput version >= 0.8])
3614fi
3615if test "x${have_libinput_new}" = "xno";then
3616 AC_DEFINE_UNQUOTED([LIBINPUT_HIGHER_08], [0], [libinput version >= 0.8])
3617fi
3618
3619
3620EFL_EVAL_PKGS([ELPUT])
3621
3622### Checks for header files
3623
3624### Checks for types
3625
3626### Checks for structures
3627
3628### Checks for compiler characteristics
3629
3630### Checks for linker characteristics
3631
3632### Checks for library functions
3633
3634EFL_LIB_END_OPTIONAL([Elput])
3635#### End of Ecore_Drm
3636
3637
3569#### Ecore_Audio 3638#### Ecore_Audio
3570 3639
3571AC_ARG_ENABLE([audio], 3640AC_ARG_ENABLE([audio],
@@ -5512,6 +5581,7 @@ pc/elocation.pc
5512pc/elua.pc 5581pc/elua.pc
5513pc/elementary.pc 5582pc/elementary.pc
5514pc/elementary-cxx.pc 5583pc/elementary-cxx.pc
5584pc/elput.pc
5515dbus-services/org.enlightenment.Ethumb.service 5585dbus-services/org.enlightenment.Ethumb.service
5516systemd-services/ethumb.service 5586systemd-services/ethumb.service
5517$po_makefile_in 5587$po_makefile_in
@@ -5680,6 +5750,7 @@ fi
5680echo "Ecore_Audio.....: ${efl_lib_optional_ecore_audio} (${features_ecore_audio})" 5750echo "Ecore_Audio.....: ${efl_lib_optional_ecore_audio} (${features_ecore_audio})"
5681echo "Ecore_Avahi.....: yes (${features_ecore_avahi})" 5751echo "Ecore_Avahi.....: yes (${features_ecore_avahi})"
5682echo "Ecore_Evas......: yes (${features_ecore_evas})" 5752echo "Ecore_Evas......: yes (${features_ecore_evas})"
5753echo "Elput...........: $want_elput"
5683echo "Ector...........: yes" 5754echo "Ector...........: yes"
5684echo "Eeze............: ${efl_lib_optional_eeze} (${features_eeze})" 5755echo "Eeze............: ${efl_lib_optional_eeze} (${features_eeze})"
5685echo "EPhysics........: ${efl_lib_optional_ephysics}" 5756echo "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 @@
1prefix=@prefix@
2exec_prefix=@exec_prefix@
3libdir=@libdir@
4includedir=@includedir@
5
6Name: elput
7Description: E core library, libinput module
8Requires.private: @requirements_pc_elput@
9Version: @VERSION@
10Libs: -L${libdir} -lelput
11Libs.private: @requirements_libs_elput@
12Cflags: -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
70include Makefile_Ethumb_Client.am 70include Makefile_Ethumb_Client.am
71include Makefile_Elocation.am 71include Makefile_Elocation.am
72include Makefile_Elementary.am 72include Makefile_Elementary.am
73include Makefile_Elput.am
73 74
74include Makefile_Eina_Cxx.am 75include Makefile_Eina_Cxx.am
75include Makefile_Ecore_Cxx.am 76include Makefile_Ecore_Cxx.am
diff --git a/src/Makefile_Elput.am b/src/Makefile_Elput.am
new file mode 100644
index 0000000000..d177f6d3e4
--- /dev/null
+++ b/src/Makefile_Elput.am
@@ -0,0 +1,59 @@
1if HAVE_ELPUT
2
3### Library
4
5lib_LTLIBRARIES += lib/elput/libelput.la
6
7installed_elputmainheadersdir = $(includedir)/elput-@VMAJ@
8dist_installed_elputmainheaders_DATA = \
9 lib/elput/Elput.h
10
11lib_elput_libelput_la_SOURCES = \
12lib/elput/elput_evdev.c \
13lib/elput/elput_input.c \
14lib/elput/elput_logind.c \
15lib/elput/elput_manager.c \
16lib/elput/elput.c \
17lib/elput/elput_private.h
18
19lib_elput_libelput_la_CPPFLAGS = \
20 -I$(top_builddir)/src/lib/efl \
21 @ELPUT_CFLAGS@ @EFL_CFLAGS@ \
22 -DPACKAGE_LIB_DIR=\"$(libdir)\" \
23 -DMODULE_ARCH=\"$(MODULE_ARCH)\"
24
25lib_elput_libelput_la_LIBADD = @ELPUT_LIBS@
26if HAVE_SYSTEMD
27lib_elput_libelput_la_LIBADD += @SYSTEMD_LIBS@
28endif
29lib_elput_libelput_la_DEPENDENCIES = @ELPUT_INTERNAL_LIBS@
30lib_elput_libelput_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
31
32### Unit tests
33
34if EFL_ENABLE_TESTS
35
36check_PROGRAMS += tests/elput/elput_suite
37TESTS += tests/elput/elput_suite
38
39tests_elput_elput_suite_SOURCES = \
40tests/elput/elput_suite.c \
41tests/elput/elput_test_elput.c \
42tests/elput/elput_suite.h
43
44tests_elput_elput_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
45-DTESTS_SRC_DIR=\"$(top_srcdir)/src/tests/elput\" \
46-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/elput\" \
47@CHECK_CFLAGS@ \
48@ELPUT_CFLAGS@
49
50tests_elput_elput_suite_LDADD = \
51@CHECK_LIBS@ \
52@USE_ELPUT_LIBS@
53
54tests_elput_elput_suite_DEPENDENCIES = \
55@USE_ELPUT_INTERNAL_LIBS@
56
57endif
58
59endif
diff --git a/src/lib/elput/Elput.h b/src/lib/elput/Elput.h
new file mode 100644
index 0000000000..a1ac7213b6
--- /dev/null
+++ b/src/lib/elput/Elput.h
@@ -0,0 +1,265 @@
1#ifndef _ELPUT_H
2# define _ELPUT_H
3
4# ifdef EAPI
5# undef EAPI
6# endif
7
8# ifdef _MSC_VER
9# ifdef BUILDING_DLL
10# define EAPI __declspec(dllexport)
11# else // ifdef BUILDING_DLL
12# define EAPI __declspec(dllimport)
13# endif // ifdef BUILDING_DLL
14# else // ifdef _MSC_VER
15# ifdef __GNUC__
16# if __GNUC__ >= 4
17# define EAPI __attribute__ ((visibility("default")))
18# else // if __GNUC__ >= 4
19# define EAPI
20# endif // if __GNUC__ >= 4
21# else // ifdef __GNUC__
22# define EAPI
23# endif // ifdef __GNUC__
24# endif // ifdef _MSC_VER
25
26# ifdef EFL_BETA_API_SUPPORT
27
28/* opaque structure to represent an input manager */
29typedef struct _Elput_Manager Elput_Manager;
30
31/* opaque structure to represent an input seat */
32typedef struct _Elput_Seat Elput_Seat;
33
34/* opaque structure to represent an input device */
35typedef struct _Elput_Device Elput_Device;
36
37/* opaque structure to represent a keyboard */
38typedef struct _Elput_Keyboard Elput_Keyboard;
39
40/* opaque structure to represent a mouse */
41typedef struct _Elput_Pointer Elput_Pointer;
42
43/* opaque structure to represent a touch device */
44typedef struct _Elput_Touch Elput_Touch;
45
46/* structure to represent event for seat capability changes */
47typedef struct _Elput_Event_Seat_Caps
48{
49 int pointer_count;
50 int keyboard_count;
51 int touch_count;
52 Elput_Seat *seat;
53} Elput_Event_Seat_Caps;
54
55/* structure to represent event for seat frame */
56typedef struct _Elput_Event_Seat_Frame
57{
58 Elput_Seat *seat;
59} Elput_Event_Seat_Frame;
60
61/* structure to represent event for seat keymap changes */
62typedef struct _Elput_Event_Keymap_Send
63{
64 int fd, format;
65 size_t size;
66} Elput_Event_Keymap_Send;
67
68/* structure to represent event for seat modifiers changes */
69typedef struct _Elput_Event_Modifiers_Send
70{
71 unsigned int depressed;
72 unsigned int latched;
73 unsigned int locked;
74 unsigned int group;
75} Elput_Event_Modifiers_Send;
76
77typedef enum _Elput_Device_Change_Type
78{
79 ELPUT_DEVICE_ADDED,
80 ELPUT_DEVICE_REMOVED,
81} Elput_Device_Change_Type;
82
83/* structure to represent event for device being added or removed */
84typedef struct _Elput_Event_Device_Change
85{
86 Elput_Device *device;
87 Elput_Device_Change_Type type;
88} Elput_Event_Device_Change;
89
90EAPI extern int ELPUT_EVENT_SEAT_CAPS;
91EAPI extern int ELPUT_EVENT_SEAT_FRAME;
92EAPI extern int ELPUT_EVENT_KEYMAP_SEND;
93EAPI extern int ELPUT_EVENT_MODIFIERS_SEND;
94EAPI extern int ELPUT_EVENT_DEVICE_CHANGE;
95
96/**
97 * @file
98 * @brief Ecore functions for dealing with libinput
99 *
100 * @defgroup Elput_Group Elput - libinput integration
101 * @ingrup Ecore
102 *
103 * Elput provides a wrapper and functions for using libinput
104 *
105 * @li @ref Elput_Init_Group
106 * @li @ref Elput_Manager_Group
107 * @li @ref Elput_Input_Group
108 * @li @ref Elput_Device_Group
109 *
110 */
111
112/**
113 * @defgroup Elput_Init_Group Library Init and Shutdown functions
114 *
115 * Functions that start and shutdown the Elput library
116 */
117
118/**
119 * Initialize the Elput library
120 *
121 * @return The number of times the library has been initialized without being
122 * shutdown. 0 is returned if an error occurs.
123 *
124 * @ingroup Elput_Init_Group
125 * @since 1.18
126 */
127EAPI int elput_init(void);
128
129/**
130 * Shutdown the Elput library
131 *
132 * @return The number of times the library has been initialized without being
133 * shutdown. 0 is returned if an error occurs.
134 *
135 * @ingroup Elput_Init_Group
136 * @since 1.18
137 */
138EAPI int elput_shutdown(void);
139
140/**
141 * @defgroup Elput_Manager_Group
142 *
143 * Functions that deal with connecting, disconnecting, opening, closing
144 * of input devices.
145 */
146
147/**
148 * Create an input manager on the specified seat
149 *
150 * @param seat
151 * @param tty
152 * @param sync
153 *
154 * @return A Elput_Manager on success, NULL on failure
155 *
156 * @ingroup Elput_Manager_Group
157 * @since 1.18
158 */
159EAPI Elput_Manager *elput_manager_connect(const char *seat, unsigned int tty, Eina_Bool sync);
160
161/**
162 * Disconnect an input manager
163 *
164 * @param manager
165 *
166 * @ingroup Elput_Manager_Group
167 * @since 1.18
168 */
169EAPI void elput_manager_disconnect(Elput_Manager *manager);
170
171/**
172 * Request input manager to open a file
173 *
174 * @param manager
175 * @param path
176 * @param flags
177 *
178 * @return Filedescriptor of opened file or -1 on failure
179 *
180 * @ingroup Elput_Manager_Group
181 * @since 1.18
182 */
183EAPI int elput_manager_open(Elput_Manager *manager, const char *path, int flags);
184
185/**
186 * Request input manager to close a file
187 *
188 * @param manager
189 * @param fd
190 *
191 * @ingroup Elput_Manager_Group
192 * @since 1.18
193 */
194EAPI void elput_manager_close(Elput_Manager *manager, int fd);
195
196/**
197 * @defgroup Elput_Input_Group Elput input functions
198 *
199 * Functions that deal with setup of inputs
200 */
201
202/**
203 * Initialize input
204 *
205 * @param manager
206 * @param seat
207 *
208 * @return EINA_TRUE on success, EINA_FALSE on failure
209 *
210 * @ingroup Elput_Input_Group
211 * @since 1.18
212 */
213EAPI Eina_Bool elput_input_init(Elput_Manager *manager, const char *seat);
214
215/**
216 * Shutdown input
217 *
218 * @param manager
219 *
220 * @ingroup Elput_Input_Group
221 * @since 1.18
222 */
223EAPI void elput_input_shutdown(Elput_Manager *manager);
224
225/**
226 * @defgroup Elput_Device_Group
227 *
228 * Functions that deal with input devices.
229 */
230
231/**
232 * Set which window to use for this input device
233 *
234 * @brief This function should be used to specify which window to set on the
235 * input device. Setting a window on the input device is done so that
236 * when we raise events (mouse movement, keyboard key, etc) then
237 * this window is passed to the event structure as the window which
238 * the event occured on.
239 *
240 * @param device
241 * @param window
242 *
243 * @ingroup Elput_Device_Group
244 * @since 1.18
245 */
246EAPI void elput_device_window_set(Elput_Device *device, unsigned int window);
247
248/**
249 * Set size of output for input device calibration
250 *
251 * @param device
252 * @param w
253 * @param h
254 *
255 * @ingroup Elput_Device_Group
256 * @since 1.18
257 */
258EAPI void elput_device_output_size_set(Elput_Device *device, int w, int h);
259
260# endif
261
262# undef EAPI
263# define EAPI
264
265#endif
diff --git a/src/lib/elput/elput.c b/src/lib/elput/elput.c
new file mode 100644
index 0000000000..2e54b3ec28
--- /dev/null
+++ b/src/lib/elput/elput.c
@@ -0,0 +1,73 @@
1#include "elput_private.h"
2
3/* local variables */
4static int _elput_init_count = 0;
5
6/* external variables */
7int _elput_log_dom = -1;
8
9EAPI int ELPUT_EVENT_SEAT_CAPS = -1;
10EAPI int ELPUT_EVENT_SEAT_FRAME = -1;
11EAPI int ELPUT_EVENT_KEYMAP_SEND = -1;
12EAPI int ELPUT_EVENT_MODIFIERS_SEND = -1;
13EAPI int ELPUT_EVENT_DEVICE_CHANGE = -1;
14
15EAPI int
16elput_init(void)
17{
18 if (++_elput_init_count != 1) return _elput_init_count;
19
20 if (!eina_init()) goto eina_err;
21 if (!ecore_init()) goto ecore_err;
22 if (!ecore_event_init()) goto ecore_event_err;
23 if (!eeze_init()) goto eeze_err;
24
25 _elput_log_dom = eina_log_domain_register("elput", ELPUT_DEFAULT_LOG_COLOR);
26 if (!_elput_log_dom)
27 {
28 EINA_LOG_ERR("Could not create logging domain for Elput");
29 goto log_err;
30 }
31
32 ELPUT_EVENT_SEAT_CAPS = ecore_event_type_new();
33 ELPUT_EVENT_SEAT_FRAME = ecore_event_type_new();
34 ELPUT_EVENT_KEYMAP_SEND = ecore_event_type_new();
35 ELPUT_EVENT_MODIFIERS_SEND = ecore_event_type_new();
36 ELPUT_EVENT_DEVICE_CHANGE = ecore_event_type_new();
37
38 return _elput_init_count;
39
40log_err:
41 eeze_shutdown();
42eeze_err:
43 ecore_event_shutdown();
44ecore_event_err:
45 ecore_shutdown();
46ecore_err:
47 eina_shutdown();
48eina_err:
49 return --_elput_init_count;
50}
51
52EAPI int
53elput_shutdown(void)
54{
55 if (_elput_init_count < 1) return 0;
56 if (--_elput_init_count != 0) return _elput_init_count;
57
58 ELPUT_EVENT_SEAT_CAPS = -1;
59 ELPUT_EVENT_SEAT_FRAME = -1;
60 ELPUT_EVENT_KEYMAP_SEND = -1;
61 ELPUT_EVENT_MODIFIERS_SEND = -1;
62 ELPUT_EVENT_DEVICE_CHANGE = -1;
63
64 eina_log_domain_unregister(_elput_log_dom);
65 _elput_log_dom = -1;
66
67 eeze_shutdown();
68 ecore_event_shutdown();
69 ecore_shutdown();
70 eina_shutdown();
71
72 return _elput_init_count;
73}
diff --git a/src/lib/elput/elput_evdev.c b/src/lib/elput/elput_evdev.c
new file mode 100644
index 0000000000..45ccefbcd6
--- /dev/null
+++ b/src/lib/elput/elput_evdev.c
@@ -0,0 +1,1383 @@
1#include "elput_private.h"
2
3static void
4_seat_caps_update(Elput_Seat *seat)
5{
6 Elput_Event_Seat_Caps *ev;
7
8 ev = calloc(1, sizeof(Elput_Event_Seat_Caps));
9 if (!ev) return;
10
11 ev->pointer_count = seat->count.ptr;
12 ev->keyboard_count = seat->count.kbd;
13 ev->touch_count = seat->count.touch;
14 ev->seat = seat;
15
16 ecore_event_add(ELPUT_EVENT_SEAT_CAPS, ev, NULL, NULL);
17}
18
19static void
20_seat_frame_send(Elput_Seat *seat)
21{
22 Elput_Event_Seat_Frame *ev;
23
24 ev = calloc(1, sizeof(Elput_Event_Seat_Frame));
25 if (!ev) return;
26
27 ev->seat = seat;
28 ecore_event_add(ELPUT_EVENT_SEAT_FRAME, ev, NULL, NULL);
29}
30
31static void
32_keyboard_modifiers_update(Elput_Keyboard *kbd, Elput_Seat *seat)
33{
34 xkb_mod_mask_t mask;
35
36 kbd->mods.depressed =
37 xkb_state_serialize_mods(kbd->state, XKB_STATE_DEPRESSED);
38 kbd->mods.latched =
39 xkb_state_serialize_mods(kbd->state, XKB_STATE_LATCHED);
40 kbd->mods.locked =
41 xkb_state_serialize_mods(kbd->state, XKB_STATE_LOCKED);
42 kbd->mods.group =
43 xkb_state_serialize_mods(kbd->state, XKB_STATE_EFFECTIVE);
44
45 mask = (kbd->mods.depressed | kbd->mods.latched);
46
47 seat->modifiers = 0;
48 if (mask & kbd->info->mods.ctrl)
49 seat->modifiers |= ECORE_EVENT_MODIFIER_CTRL;
50 if (mask & kbd->info->mods.alt)
51 seat->modifiers |= ECORE_EVENT_MODIFIER_ALT;
52 if (mask & kbd->info->mods.shift)
53 seat->modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
54 if (mask & kbd->info->mods.super)
55 seat->modifiers |= ECORE_EVENT_MODIFIER_WIN;
56 if (mask & kbd->info->mods.altgr)
57 seat->modifiers |= ECORE_EVENT_MODIFIER_ALTGR;
58}
59
60static int
61_keyboard_fd_get(off_t size)
62{
63 int fd = 0, blen = 0, len = 0;
64 const char *path;
65 char tmp[PATH_MAX];
66 long flags;
67
68 blen = sizeof(tmp) - 1;
69
70 if (!(path = getenv("XDG_RUNTIME_DIR")))
71 return -1;
72
73 len = strlen(path);
74 if (len < blen)
75 {
76 strcpy(tmp, path);
77 strcat(tmp, "/elput-keymap-XXXXXX");
78 }
79 else
80 return -1;
81
82 if ((fd = mkstemp(tmp)) < 0) return -1;
83
84 flags = fcntl(fd, F_GETFD);
85 if (flags < 0)
86 {
87 close(fd);
88 return -1;
89 }
90
91 if (fcntl(fd, F_SETFD, (flags | FD_CLOEXEC)) == -1)
92 {
93 close(fd);
94 return -1;
95 }
96
97 if (ftruncate(fd, size) < 0)
98 {
99 close(fd);
100 return -1;
101 }
102
103 unlink(tmp);
104 return fd;
105}
106
107static Elput_Keyboard_Info *
108_keyboard_info_create(struct xkb_keymap *keymap, Eina_Bool external)
109{
110 Elput_Keyboard_Info *info;
111 char *str;
112
113 info = calloc(1, sizeof(Elput_Keyboard_Info));
114 if (!info) return NULL;
115
116 info->keymap.map = xkb_keymap_ref(keymap);
117 info->refs = 1;
118
119 info->mods.super =
120 1 << xkb_keymap_mod_get_index(info->keymap.map, XKB_MOD_NAME_LOGO);
121 info->mods.shift =
122 1 << xkb_keymap_mod_get_index(info->keymap.map, XKB_MOD_NAME_SHIFT);
123 info->mods.caps =
124 1 << xkb_keymap_mod_get_index(info->keymap.map, XKB_MOD_NAME_CAPS);
125 info->mods.ctrl =
126 1 << xkb_keymap_mod_get_index(info->keymap.map, XKB_MOD_NAME_CTRL);
127 info->mods.alt =
128 1 << xkb_keymap_mod_get_index(info->keymap.map, XKB_MOD_NAME_ALT);
129 info->mods.altgr =
130 1 << xkb_keymap_mod_get_index(info->keymap.map, "ISO_Level3_Shift");
131
132 /* if we are using an external keymap then we do not need go further */
133 if (external) return info;
134
135 str = xkb_keymap_get_as_string(info->keymap.map, XKB_KEYMAP_FORMAT_TEXT_V1);
136 if (!str) goto err;
137
138 info->keymap.size = strlen(str) + 1;
139
140 info->keymap.fd = _keyboard_fd_get(info->keymap.size);
141 if (info->keymap.fd < 0) goto err_fd;
142
143 info->keymap.area =
144 mmap(NULL, info->keymap.size, PROT_READ | PROT_WRITE,
145 MAP_SHARED, info->keymap.fd, 0);
146 if (info->keymap.area == MAP_FAILED) goto err_map;
147
148 strcpy(info->keymap.area, str);
149 free(str);
150
151 return info;
152
153err_map:
154 close(info->keymap.fd);
155err_fd:
156 free(str);
157err:
158 xkb_keymap_unref(info->keymap.map);
159 free(info);
160 return NULL;
161}
162
163static void
164_keyboard_info_destroy(Elput_Keyboard_Info *info, Eina_Bool external)
165{
166 if (--info->refs > 0) return;
167
168 if (!external)
169 {
170 xkb_keymap_unref(info->keymap.map);
171 if (info->keymap.area) munmap(info->keymap.area, info->keymap.size);
172 if (info->keymap.fd >= 0) close(info->keymap.fd);
173 }
174
175 free(info);
176}
177
178static Eina_Bool
179_keyboard_global_build(Elput_Keyboard *kbd)
180{
181 struct xkb_keymap *keymap;
182
183 kbd->context = xkb_context_new(0);
184 if (!kbd->context) return EINA_FALSE;
185
186 if (!kbd->names.rules) kbd->names.rules = strdup("evdev");
187 if (!kbd->names.model) kbd->names.model = strdup("pc105");
188 if (!kbd->names.layout) kbd->names.layout = strdup("us");
189
190 keymap = xkb_keymap_new_from_names(kbd->context, &kbd->names, 0);
191 if (!keymap) return EINA_FALSE;
192
193 kbd->info = _keyboard_info_create(keymap, EINA_FALSE);
194 xkb_keymap_unref(keymap);
195
196 if (!kbd->info) return EINA_FALSE;
197 return EINA_TRUE;
198}
199
200static Elput_Keyboard *
201_keyboard_create(Elput_Seat *seat)
202{
203 Elput_Keyboard *kbd;
204
205 kbd = calloc(1, sizeof(Elput_Keyboard));
206 if (!kbd) return NULL;
207
208 kbd->seat = seat;
209 return kbd;
210}
211
212static Eina_Bool
213_keyboard_init(Elput_Seat *seat, struct xkb_keymap *keymap)
214{
215 Elput_Keyboard *kbd;
216
217 if (seat->kbd)
218 {
219 seat->count.kbd += 1;
220 if (seat->count.kbd == 1)
221 {
222 _seat_caps_update(seat);
223 return EINA_TRUE;
224 }
225 }
226
227 kbd = _keyboard_create(seat);
228 if (!kbd) return EINA_FALSE;
229
230 if (keymap)
231 {
232 kbd->info = _keyboard_info_create(keymap, EINA_TRUE);
233 if (!kbd->info) goto err;
234 }
235 else
236 {
237 if (!_keyboard_global_build(kbd)) goto err;
238 kbd->info->refs++;
239 }
240
241 kbd->state = xkb_state_new(kbd->info->keymap.map);
242 if (!kbd->state) goto err;
243
244 seat->kbd = kbd;
245 seat->count.kbd = 1;
246
247 _seat_caps_update(seat);
248
249 return EINA_TRUE;
250
251err:
252 if (kbd->info) _keyboard_info_destroy(kbd->info, kbd->external_map);
253 free(kbd);
254 return EINA_FALSE;
255}
256
257static void
258_keyboard_state_reset(Elput_Keyboard *kbd)
259{
260 struct xkb_state *state;
261
262 state = xkb_state_new(kbd->info->keymap.map);
263 if (!state) return;
264
265 xkb_state_unref(kbd->state);
266 kbd->state = state;
267}
268
269static void
270_keyboard_release(Elput_Seat *seat)
271{
272 seat->count.kbd--;
273 if (seat->count.kbd == 0)
274 {
275 _keyboard_state_reset(seat->kbd);
276 _seat_caps_update(seat);
277 }
278}
279
280static void
281_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)
282{
283 Ecore_Event_Key *ev;
284
285 ev = calloc(1, sizeof(Ecore_Event_Key) + strlen(key) + strlen(keyname) +
286 ((compose[0] != '\0') ? strlen(compose) : 0) + 3);
287 if (!ev) return;
288
289 ev->keyname = (char *)(ev + 1);
290 ev->key = ev->keyname + strlen(keyname) + 1;
291 ev->compose = strlen(compose) ? ev->key + strlen(key) + 1 : NULL;
292 ev->string = ev->compose;
293
294 strcpy((char *)ev->keyname, keyname);
295 strcpy((char *)ev->key, key);
296 if (strlen(compose)) strcpy((char *)ev->compose, compose);
297
298 /* ev->string = ev->compose; */
299 ev->keycode = code;
300 ev->modifiers = dev->seat->modifiers;
301 ev->timestamp = timestamp;
302 ev->same_screen = 1;
303
304 ev->window = dev->window;
305 ev->event_window = dev->window;
306 ev->root_window = dev->window;
307
308 if (state == LIBINPUT_KEY_STATE_PRESSED)
309 ecore_event_add(ECORE_EVENT_KEY_DOWN, ev, NULL, NULL);
310 else
311 ecore_event_add(ECORE_EVENT_KEY_UP, ev, NULL, NULL);
312}
313
314static void
315_keyboard_keymap_send(Elput_Keyboard_Info *info)
316{
317 Elput_Event_Keymap_Send *ev;
318
319 ev = calloc(1, sizeof(Elput_Event_Keymap_Send));
320 if (!ev) return;
321
322 ev->fd = info->keymap.fd;
323 ev->size = info->keymap.size;
324 ev->format = XKB_KEYMAP_FORMAT_TEXT_V1;
325
326 ecore_event_add(ELPUT_EVENT_KEYMAP_SEND, ev, NULL, NULL);
327}
328
329static void
330_keyboard_modifiers_send(Elput_Keyboard *kbd)
331{
332 Elput_Event_Modifiers_Send *ev;
333
334 ev = calloc(1, sizeof(Elput_Event_Modifiers_Send));
335 if (!ev) return;
336
337 ev->depressed = kbd->mods.depressed;
338 ev->latched = kbd->mods.latched;
339 ev->locked = kbd->mods.locked;
340 ev->group = kbd->mods.group;
341
342 ecore_event_add(ELPUT_EVENT_MODIFIERS_SEND, ev, NULL, NULL);
343}
344
345static void
346_keyboard_keymap_update(Elput_Seat *seat)
347{
348 Elput_Keyboard *kbd;
349 Elput_Keyboard_Info *info;
350 struct xkb_state *state;
351 xkb_mod_mask_t latched, locked;
352
353 kbd = _evdev_keyboard_get(seat);
354 if (!kbd) return;
355
356 info = _keyboard_info_create(kbd->pending_map, kbd->external_map);
357 xkb_keymap_unref(kbd->pending_map);
358 kbd->pending_map = NULL;
359
360 if (!info) return;
361
362 state = xkb_state_new(info->keymap.map);
363 if (!state)
364 {
365 _keyboard_info_destroy(info, kbd->external_map);
366 return;
367 }
368
369 latched = xkb_state_serialize_mods(kbd->state, XKB_STATE_MODS_LATCHED);
370 locked = xkb_state_serialize_mods(kbd->state, XKB_STATE_MODS_LOCKED);
371 xkb_state_update_mask(state, 0, latched, locked, 0, 0, 0);
372
373 _keyboard_info_destroy(kbd->info, kbd->external_map);
374 kbd->info = info;
375
376 xkb_state_unref(kbd->state);
377 kbd->state = state;
378
379 _keyboard_modifiers_update(kbd, seat);
380 _keyboard_keymap_send(kbd->info);
381
382 if ((!latched) && (!locked)) return;
383
384 _keyboard_modifiers_send(kbd);
385}
386
387static int
388_keyboard_keysym_translate(xkb_keysym_t keysym, unsigned int modifiers, char *buffer, int bytes)
389{
390 unsigned long hbytes = 0;
391 unsigned char c;
392
393 if (!keysym) return 0;
394 hbytes = (keysym >> 8);
395
396 if (!(bytes &&
397 ((hbytes == 0) ||
398 ((hbytes == 0xFF) &&
399 (((keysym >= XKB_KEY_BackSpace) && (keysym <= XKB_KEY_Clear)) ||
400 (keysym == XKB_KEY_Return) || (keysym == XKB_KEY_Escape) ||
401 (keysym == XKB_KEY_KP_Space) || (keysym == XKB_KEY_KP_Tab) ||
402 (keysym == XKB_KEY_KP_Enter) ||
403 ((keysym >= XKB_KEY_KP_Multiply) && (keysym <= XKB_KEY_KP_9)) ||
404 (keysym == XKB_KEY_KP_Equal) || (keysym == XKB_KEY_Delete))))))
405 return 0;
406
407 if (keysym == XKB_KEY_KP_Space)
408 c = (XKB_KEY_space & 0x7F);
409 else if (hbytes == 0xFF)
410 c = (keysym & 0x7F);
411 else
412 c = (keysym & 0xFF);
413
414 if (modifiers & ECORE_EVENT_MODIFIER_CTRL)
415 {
416 if (((c >= '@') && (c < '\177')) || c == ' ')
417 c &= 0x1F;
418 else if (c == '2')
419 c = '\000';
420 else if ((c >= '3') && (c <= '7'))
421 c -= ('3' - '\033');
422 else if (c == '8')
423 c = '\177';
424 else if (c == '/')
425 c = '_' & 0x1F;
426 }
427 buffer[0] = c;
428 return 1;
429}
430
431static void
432_keyboard_key(struct libinput_device *idevice, struct libinput_event_keyboard *event)
433{
434 Elput_Device *dev;
435 Elput_Keyboard *kbd;
436 enum libinput_key_state state;
437 xkb_keysym_t sym = XKB_KEY_NoSymbol;
438 const xkb_keysym_t *syms;
439 unsigned int code = 0;
440 unsigned int nsyms;
441 unsigned int timestamp;
442 char key[256], keyname[256], buffer[256];
443 char *tmp = NULL, *compose = NULL;
444 int count;
445
446 dev = libinput_device_get_user_data(idevice);
447 if (!dev) return;
448
449 kbd = _evdev_keyboard_get(dev->seat);
450 if (!kbd) return;
451
452 state = libinput_event_keyboard_get_key_state(event);
453 count = libinput_event_keyboard_get_seat_key_count(event);
454
455 /* Ignore key events that are not seat wide state changes. */
456 if (((state == LIBINPUT_KEY_STATE_PRESSED) && (count != 1)) ||
457 ((state == LIBINPUT_KEY_STATE_RELEASED) && (count != 0)))
458 return;
459
460 code = libinput_event_keyboard_get_key(event) + 8;
461 timestamp = libinput_event_keyboard_get_time(event);
462
463 if (state == LIBINPUT_KEY_STATE_PRESSED)
464 xkb_state_update_key(kbd->state, code, XKB_KEY_DOWN);
465 else
466 xkb_state_update_key(kbd->state, code, XKB_KEY_UP);
467
468 nsyms = xkb_key_get_syms(kbd->state, code, &syms);
469 if (nsyms == 1) sym = syms[0];
470
471 memset(key, 0, sizeof(key));
472 xkb_keysym_get_name(sym, key, sizeof(key));
473
474 memset(keyname, 0, sizeof(keyname));
475 memcpy(keyname, key, sizeof(keyname));
476
477 if (keyname[0] == '\0')
478 snprintf(keyname, sizeof(keyname), "Keycode-%u", code);
479
480 if (xkb_state_mod_index_is_active(kbd->state, kbd->info->mods.shift,
481 XKB_STATE_MODS_EFFECTIVE))
482 {
483 if (keyname[0] != '\0')
484 keyname[0] = tolower(keyname[0]);
485 }
486
487 _keyboard_modifiers_update(kbd, dev->seat);
488
489 memset(buffer, 0, sizeof(buffer));
490 if (_keyboard_keysym_translate(sym, dev->seat->modifiers,
491 buffer, sizeof(buffer)))
492 {
493 compose = eina_str_convert("ISO8859-1", "UTF-8", buffer);
494 if (!compose)
495 {
496 ERR("Ecore_Drm2 cannot convert input key string '%s' to UTF-8. "
497 "Is Eina built with iconv support?", buffer);
498 }
499 else
500 tmp = compose;
501 }
502
503 if (!compose) compose = buffer;
504
505 _keyboard_key_send(dev, state, keyname, key, compose, code, timestamp);
506
507 if (tmp) free(tmp);
508
509 if ((kbd->pending_map) && (count == 0))
510 _keyboard_keymap_update(dev->seat);
511
512 if (state == LIBINPUT_KEY_STATE_PRESSED)
513 {
514 kbd->grab.key = code;
515 kbd->grab.timestamp = timestamp;
516 }
517}
518
519static Elput_Pointer *
520_pointer_create(Elput_Seat *seat)
521{
522 Elput_Pointer *ptr;
523
524 ptr = calloc(1, sizeof(Elput_Pointer));
525 if (!ptr) return NULL;
526
527 ptr->seat = seat;
528
529 return ptr;
530}
531
532static Eina_Bool
533_pointer_init(Elput_Seat *seat)
534{
535 Elput_Pointer *ptr;
536
537 if (seat->ptr)
538 {
539 seat->count.ptr += 1;
540 if (seat->count.ptr == 1)
541 {
542 _seat_caps_update(seat);
543 return EINA_TRUE;
544 }
545 }
546
547 ptr = _pointer_create(seat);
548 if (!ptr) return EINA_FALSE;
549
550 seat->ptr = ptr;
551 seat->count.ptr = 1;
552
553 _seat_caps_update(seat);
554
555 return EINA_TRUE;
556}
557
558static void
559_pointer_release(Elput_Seat *seat)
560{
561 seat->count.ptr--;
562 if (seat->count.ptr == 0)
563 {
564 seat->ptr->buttons = 0;
565 _seat_caps_update(seat);
566 }
567}
568
569static Elput_Touch *
570_touch_create(Elput_Seat *seat)
571{
572 Elput_Touch *touch;
573
574 touch = calloc(1, sizeof(Elput_Touch));
575 if (!touch) return NULL;
576
577 touch->seat = seat;
578
579 return touch;
580}
581
582static Eina_Bool
583_touch_init(Elput_Seat *seat)
584{
585 Elput_Touch *touch;
586
587 if (seat->touch)
588 {
589 seat->count.touch += 1;
590 if (seat->count.touch == 1)
591 {
592 _seat_caps_update(seat);
593 return EINA_TRUE;
594 }
595 }
596
597 touch = _touch_create(seat);
598 if (!touch) return EINA_FALSE;
599
600 seat->touch = touch;
601 seat->count.touch = 1;
602
603 _seat_caps_update(seat);
604
605 return EINA_TRUE;
606}
607
608static void
609_touch_release(Elput_Seat *seat)
610{
611 seat->count.touch--;
612 if (seat->count.touch == 0)
613 {
614 seat->touch->points = 0;
615 _seat_caps_update(seat);
616 }
617}
618
619static void
620_pointer_motion_send(Elput_Device *edev)
621{
622 Elput_Pointer *ptr;
623 Elput_Keyboard *kbd;
624 Elput_Touch *touch;
625 Ecore_Event_Mouse_Move *ev;
626 double x, y;
627
628 ptr = _evdev_pointer_get(edev->seat);
629 if (!ptr) return;
630
631 ev = calloc(1, sizeof(Ecore_Event_Mouse_Move));
632 if (!ev) return;
633
634 x = ptr->x;
635 y = ptr->y;
636
637 if (x < ptr->minx)
638 x = ptr->minx;
639 else if (x >= ptr->minx + ptr->maxw)
640 x = ptr->minx + ptr->maxw - 1;
641
642 if (y < ptr->miny)
643 y = ptr->miny;
644 else if (y >= ptr->miny + ptr->maxh)
645 y = ptr->miny + ptr->maxh - 1;
646
647 ev->window = edev->window;
648 ev->event_window = edev->window;
649 ev->root_window = edev->window;
650 ev->timestamp = ptr->timestamp;
651 ev->same_screen = 1;
652
653 ev->x = x;
654 ev->y = y;
655 ev->root.x = x;
656 ev->root.y = y;
657
658 kbd = _evdev_keyboard_get(edev->seat);
659 if (kbd) _keyboard_modifiers_update(kbd, edev->seat);
660
661 ev->modifiers = edev->seat->modifiers;
662
663 touch = _evdev_touch_get(edev->seat);
664 if (touch) ev->multi.device = touch->slot;
665
666 ev->multi.radius = 1;
667 ev->multi.radius_x = 1;
668 ev->multi.radius_y = 1;
669 ev->multi.pressure = 1.0;
670 ev->multi.angle = 0.0;
671 ev->multi.x = ev->x;
672 ev->multi.y = ev->y;
673 ev->multi.root.x = ev->x;
674 ev->multi.root.y = ev->y;
675
676 ecore_event_add(ECORE_EVENT_MOUSE_MOVE, ev, NULL, NULL);
677}
678
679static Eina_Bool
680_pointer_motion(struct libinput_device *idev, struct libinput_event_pointer *event)
681{
682 Elput_Device *edev;
683 Elput_Pointer *ptr;
684 double x, y;
685
686 edev = libinput_device_get_user_data(idev);
687 if (!edev) return EINA_FALSE;
688
689 ptr = _evdev_pointer_get(edev->seat);
690 if (!ptr) return EINA_FALSE;
691
692 x = ptr->x + libinput_event_pointer_get_dx(event);
693 y = ptr->y + libinput_event_pointer_get_dy(event);
694
695 if (x < ptr->minx)
696 x = ptr->minx;
697 else if (x >= ptr->minx + ptr->maxw)
698 x = ptr->minx + ptr->maxw - 1;
699
700 if (y < ptr->miny)
701 y = ptr->miny;
702 else if (y >= ptr->miny + ptr->maxh)
703 y = ptr->miny + ptr->maxh - 1;
704
705 ptr->x = x;
706 ptr->y = y;
707 ptr->timestamp = libinput_event_pointer_get_time(event);
708
709 _pointer_motion_send(edev);
710
711 return EINA_TRUE;
712}
713
714static Eina_Bool
715_pointer_motion_abs(struct libinput_device *idev, struct libinput_event_pointer *event)
716{
717 Elput_Device *edev;
718 Elput_Pointer *ptr;
719
720 edev = libinput_device_get_user_data(idev);
721 if (!edev) return EINA_FALSE;
722
723 ptr = _evdev_pointer_get(edev->seat);
724 if (!ptr) return EINA_FALSE;
725
726 ptr->x = libinput_event_pointer_get_absolute_x_transformed(event, edev->ow);
727 ptr->y = libinput_event_pointer_get_absolute_y_transformed(event, edev->oh);
728 ptr->timestamp = libinput_event_pointer_get_time(event);
729
730 /* TODO: these needs to run a matrix transform based on output */
731
732 _pointer_motion_send(edev);
733
734 return EINA_TRUE;
735}
736
737static void
738_pointer_button_send(Elput_Device *edev, enum libinput_button_state state)
739{
740 Elput_Pointer *ptr;
741 Elput_Keyboard *kbd;
742 Elput_Touch *touch;
743 Ecore_Event_Mouse_Button *ev;
744
745 ptr = _evdev_pointer_get(edev->seat);
746 if (!ptr) return;
747
748 ev = calloc(1, sizeof(Ecore_Event_Mouse_Button));
749 if (!ev) return;
750
751 ev->window = edev->window;
752 ev->event_window = edev->window;
753 ev->root_window = edev->window;
754 ev->timestamp = ptr->timestamp;
755 ev->same_screen = 1;
756
757 ev->x = ptr->x;
758 ev->y = ptr->y;
759 ev->root.x = ptr->x;
760 ev->root.y = ptr->y;
761
762 touch = _evdev_touch_get(edev->seat);
763 if (touch) ev->multi.device = touch->slot;
764 ev->multi.radius = 1;
765 ev->multi.radius_x = 1;
766 ev->multi.radius_y = 1;
767 ev->multi.pressure = 1.0;
768 ev->multi.angle = 0.0;
769 ev->multi.x = ev->x;
770 ev->multi.y = ev->y;
771 ev->multi.root.x = ev->x;
772 ev->multi.root.y = ev->y;
773
774 ev->buttons = ptr->buttons;
775
776 ev->double_click = ptr->mouse.double_click;
777 ev->triple_click = ptr->mouse.triple_click;
778
779 kbd = _evdev_keyboard_get(edev->seat);
780 if (kbd)
781 _keyboard_modifiers_update(kbd, edev->seat);
782 ev->modifiers = edev->seat->modifiers;
783
784 if (state)
785 ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, ev, NULL, NULL);
786 else
787 ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, ev, NULL, NULL);
788}
789
790static Eina_Bool
791_pointer_button(struct libinput_device *idev, struct libinput_event_pointer *event)
792{
793 Elput_Device *edev;
794 Elput_Pointer *ptr;
795 int count;
796 enum libinput_button_state state;
797 unsigned int btn;
798
799 edev = libinput_device_get_user_data(idev);
800 if (!edev) return EINA_FALSE;
801
802 ptr = _evdev_pointer_get(edev->seat);
803 if (!ptr) return EINA_FALSE;
804
805 state = libinput_event_pointer_get_button_state(event);
806 count = libinput_event_pointer_get_seat_button_count(event);
807
808 /* Ignore button events that are not seat wide state changes. */
809 if (((state == LIBINPUT_BUTTON_STATE_PRESSED) && (count != 1)) ||
810 ((state == LIBINPUT_BUTTON_STATE_RELEASED) && (count != 0)))
811 return EINA_FALSE;
812
813 btn = libinput_event_pointer_get_button(event);
814
815 btn = ((btn & 0x00F) + 1);
816 if (btn == 3) btn = 2;
817 else if (btn == 2) btn = 3;
818
819 ptr->buttons = btn;
820 ptr->timestamp = libinput_event_pointer_get_time(event);
821
822 if (state)
823 {
824 unsigned int current;
825
826 current = ptr->timestamp;
827 ptr->mouse.double_click = EINA_FALSE;
828 ptr->mouse.triple_click = EINA_FALSE;
829
830 if (((current - ptr->mouse.prev_time) <= ptr->mouse.threshold) &&
831 (btn == ptr->mouse.prev_button))
832 {
833 ptr->mouse.double_click = EINA_TRUE;
834 if (((current - ptr->mouse.last_time) <=
835 (2 * ptr->mouse.threshold)) &&
836 (btn == ptr->mouse.last_button))
837 {
838 ptr->mouse.triple_click = EINA_TRUE;
839 ptr->mouse.prev_time = 0;
840 ptr->mouse.last_time = 0;
841 current = 0;
842 }
843 }
844
845 ptr->mouse.last_time = ptr->mouse.prev_time;
846 ptr->mouse.prev_time = current;
847 ptr->mouse.last_button = ptr->mouse.prev_button;
848 ptr->mouse.prev_button = ptr->buttons;
849 }
850
851 _pointer_button_send(edev, state);
852
853 return EINA_TRUE;
854}
855
856static void
857_pointer_axis_send(Elput_Device *dev, int direction, int value)
858{
859 Elput_Pointer *ptr;
860 Elput_Keyboard *kbd;
861 Ecore_Event_Mouse_Wheel *ev;
862
863 ptr = _evdev_pointer_get(dev->seat);
864 if (!ptr) return;
865
866 ev = calloc(1, sizeof(Ecore_Event_Mouse_Wheel));
867 if (!ev) return;
868
869 ev->window = dev->window;
870 ev->event_window = dev->window;
871 ev->root_window = dev->window;
872 ev->timestamp = ptr->timestamp;
873 ev->same_screen = 1;
874
875 ev->x = ptr->x;
876 ev->y = ptr->y;
877 ev->root.x = ptr->x;
878 ev->root.y = ptr->y;
879
880 ev->z = value;
881 ev->direction = direction;
882
883 kbd = _evdev_keyboard_get(dev->seat);
884 if (kbd) _keyboard_modifiers_update(kbd, dev->seat);
885
886 ev->modifiers = dev->seat->modifiers;
887
888 ecore_event_add(ECORE_EVENT_MOUSE_WHEEL, ev, NULL, NULL);
889}
890
891static double
892_pointer_axis_value(struct libinput_event_pointer *event, enum libinput_pointer_axis axis)
893{
894 enum libinput_pointer_axis_source source;
895 double val = 0.0;
896
897 source = libinput_event_pointer_get_axis_source(event);
898 switch (source)
899 {
900 case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL:
901 val = 10 * libinput_event_pointer_get_axis_value_discrete(event, axis);
902 break;
903 case LIBINPUT_POINTER_AXIS_SOURCE_FINGER:
904 case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS:
905 val = libinput_event_pointer_get_axis_value(event, axis);
906 break;
907 }
908
909 return val;
910}
911
912static Eina_Bool
913_pointer_axis(struct libinput_device *idevice, struct libinput_event_pointer *event)
914{
915 Elput_Device *dev;
916 Elput_Pointer *ptr;
917 enum libinput_pointer_axis axis;
918 Eina_Bool vert = EINA_FALSE, horiz = EINA_FALSE;
919 int dir = 0, val = 0;
920
921 dev = libinput_device_get_user_data(idevice);
922 if (!dev) return EINA_FALSE;
923
924 ptr = _evdev_pointer_get(dev->seat);
925 if (!ptr) return EINA_FALSE;
926
927#ifdef LIBINPUT_HIGHER_08
928 vert =
929 libinput_event_pointer_has_axis(event,
930 LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
931 horiz =
932 libinput_event_pointer_has_axis(event,
933 LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
934 if ((!vert) && (!horiz)) return EINA_FALSE;
935
936 if (vert)
937 {
938 axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL;
939 val = _pointer_axis_value(event, axis);
940 }
941
942 if (horiz)
943 {
944 axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL;
945 val = _pointer_axis_value(event, axis);
946 dir = 1;
947 }
948
949#else
950 axis = libinput_event_pointer_get_axis(event);
951 if (axis == LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL) dir = 1;
952 val = libinput_event_pointer_get_axis_value(event);
953#endif
954
955 ptr->timestamp = libinput_event_pointer_get_time(event);
956
957 _pointer_axis_send(dev, dir, val);
958
959 return EINA_TRUE;
960}
961
962static void
963_touch_event_send(Elput_Device *dev, struct libinput_event_touch *event, int type)
964{
965 Elput_Touch *touch;
966 Ecore_Event_Mouse_Button *ev;
967 unsigned int btn = 0;
968
969 touch = _evdev_touch_get(dev->seat);
970 if (!touch) return;
971
972 ev = calloc(1, sizeof(Ecore_Event_Mouse_Button));
973 if (!ev) return;
974
975 ev->window = dev->window;
976 ev->event_window = dev->window;
977 ev->root_window = dev->window;
978 ev->timestamp = libinput_event_touch_get_time(event);
979 ev->same_screen = 1;
980
981 ev->x = touch->x;
982 ev->y = touch->y;
983 ev->root.x = touch->x;
984 ev->root.y = touch->y;
985
986 ev->modifiers = dev->seat->modifiers;
987
988 ev->multi.device = touch->slot;
989 ev->multi.radius = 1;
990 ev->multi.radius_x = 1;
991 ev->multi.radius_y = 1;
992 ev->multi.pressure = 1.0;
993 ev->multi.angle = 0.0;
994 ev->multi.x = ev->x;
995 ev->multi.y = ev->y;
996 ev->multi.root.x = ev->x;
997 ev->multi.root.y = ev->y;
998
999 btn = ((btn & 0x00F) + 1);
1000 if (btn == 3) btn = 2;
1001 else if (btn == 2) btn = 3;
1002 ev->buttons = btn;
1003
1004 ecore_event_add(type, ev, NULL, NULL);
1005}
1006
1007static void
1008_touch_down(struct libinput_device *idevice, struct libinput_event_touch *event)
1009{
1010 Elput_Device *dev;
1011 Elput_Touch *touch;
1012 unsigned int timestamp;
1013 int slot;
1014
1015 dev = libinput_device_get_user_data(idevice);
1016 if (!dev) return;
1017
1018 touch = _evdev_touch_get(dev->seat);
1019 if (!touch) return;
1020
1021 slot = libinput_event_touch_get_seat_slot(event);
1022 timestamp = libinput_event_touch_get_time(event);
1023
1024 touch->x = libinput_event_touch_get_x_transformed(event, dev->ow);
1025 touch->y = libinput_event_touch_get_y_transformed(event, dev->oh);
1026
1027 /* TODO: these needs to run a matrix transform based on output */
1028 /* _ecore_drm2_output_coordinate_transform(dev->output, */
1029 /* touch->x, touch->y, */
1030 /* &touch->x, &touch->y); */
1031
1032 if (slot == touch->grab.id)
1033 {
1034 touch->grab.x = touch->x;
1035 touch->grab.y = touch->y;
1036 }
1037
1038 touch->slot = slot;
1039 touch->points++;
1040
1041 _touch_event_send(dev, event, ECORE_EVENT_MOUSE_BUTTON_DOWN);
1042
1043 if (touch->points == 1)
1044 {
1045 touch->grab.id = slot;
1046 touch->grab.x = touch->x;
1047 touch->grab.y = touch->y;
1048 touch->grab.timestamp = timestamp;
1049 }
1050}
1051
1052static void
1053_touch_up(struct libinput_device *idevice, struct libinput_event_touch *event)
1054{
1055 Elput_Device *dev;
1056 Elput_Touch *touch;
1057
1058 dev = libinput_device_get_user_data(idevice);
1059 if (!dev) return;
1060
1061 touch = _evdev_touch_get(dev->seat);
1062 if (!touch) return;
1063
1064 touch->points--;
1065 touch->slot = libinput_event_touch_get_seat_slot(event);
1066
1067 _touch_event_send(dev, event, ECORE_EVENT_MOUSE_BUTTON_UP);
1068}
1069
1070static void
1071_touch_motion_send(Elput_Device *dev, struct libinput_event_touch *event)
1072{
1073 Elput_Touch *touch;
1074 Ecore_Event_Mouse_Move *ev;
1075
1076 touch = _evdev_touch_get(dev->seat);
1077 if (!touch) return;
1078
1079 ev = calloc(1, sizeof(Ecore_Event_Mouse_Move));
1080 if (!ev) return;
1081
1082 ev->window = dev->window;
1083 ev->event_window = dev->window;
1084 ev->root_window = dev->window;
1085 ev->timestamp = libinput_event_touch_get_time(event);
1086 ev->same_screen = 1;
1087
1088 ev->x = touch->x;
1089 ev->y = touch->y;
1090 ev->root.x = touch->x;
1091 ev->root.y = touch->y;
1092
1093 ev->modifiers = dev->seat->modifiers;
1094
1095 ev->multi.device = touch->slot;
1096 ev->multi.radius = 1;
1097 ev->multi.radius_x = 1;
1098 ev->multi.radius_y = 1;
1099 ev->multi.pressure = 1.0;
1100 ev->multi.angle = 0.0;
1101 ev->multi.x = ev->x;
1102 ev->multi.y = ev->y;
1103 ev->multi.root.x = ev->x;
1104 ev->multi.root.y = ev->y;
1105
1106 ecore_event_add(ECORE_EVENT_MOUSE_MOVE, ev, NULL, NULL);
1107}
1108
1109static void
1110_touch_motion(struct libinput_device *idevice, struct libinput_event_touch *event)
1111{
1112 Elput_Device *dev;
1113 Elput_Touch *touch;
1114
1115 dev = libinput_device_get_user_data(idevice);
1116 if (!dev) return;
1117
1118 touch = _evdev_touch_get(dev->seat);
1119 if (!touch) return;
1120
1121 touch->x = libinput_event_touch_get_x_transformed(event, dev->ow);
1122 touch->y = libinput_event_touch_get_y_transformed(event, dev->oh);
1123
1124 /* TODO: these needs to run a matrix transform based on output */
1125 /* _ecore_drm2_output_coordinate_transform(dev->output, */
1126 /* touch->x, touch->y, */
1127 /* &touch->x, &touch->y); */
1128
1129 touch->slot = libinput_event_touch_get_seat_slot(event);
1130
1131 _touch_motion_send(dev, event);
1132}
1133
1134static void
1135_evdev_device_calibrate(Elput_Device *dev)
1136{
1137 float cal[6];
1138 const char *vals;
1139 const char *sysname;
1140 const char *device;
1141 Eina_List *devices;
1142 int w = 0, h = 0;
1143 enum libinput_config_status status;
1144
1145 w = dev->ow;
1146 h = dev->oh;
1147 if ((w == 0) || (h == 0)) return;
1148
1149 if ((!libinput_device_config_calibration_has_matrix(dev->device)) ||
1150 (libinput_device_config_calibration_get_default_matrix(dev->device, cal)))
1151 return;
1152
1153 sysname = libinput_device_get_sysname(dev->device);
1154
1155 devices = eeze_udev_find_by_subsystem_sysname("input", sysname);
1156 EINA_LIST_FREE(devices, device)
1157 {
1158 vals = eeze_udev_syspath_get_property(device, "WL_CALIBRATION");
1159 if ((!vals) ||
1160 (sscanf(vals, "%f %f %f %f %f %f",
1161 &cal[0], &cal[1], &cal[2], &cal[3], &cal[4], &cal[5]) != 6))
1162 goto cont;
1163
1164 cal[2] /= w;
1165 cal[5] /= h;
1166
1167 status =
1168 libinput_device_config_calibration_set_matrix(dev->device, cal);
1169 if (status != LIBINPUT_CONFIG_STATUS_SUCCESS)
1170 WRN("Failed to apply device calibration");
1171
1172cont:
1173 eina_stringshare_del(device);
1174 }
1175}
1176
1177int
1178_evdev_event_process(struct libinput_event *event)
1179{
1180 struct libinput_device *idev;
1181 int ret = 1;
1182 Eina_Bool frame = EINA_FALSE;
1183
1184 idev = libinput_event_get_device(event);
1185 switch (libinput_event_get_type(event))
1186 {
1187 case LIBINPUT_EVENT_KEYBOARD_KEY:
1188 _keyboard_key(idev, libinput_event_get_keyboard_event(event));
1189 break;
1190 case LIBINPUT_EVENT_POINTER_MOTION:
1191 frame =
1192 _pointer_motion(idev, libinput_event_get_pointer_event(event));
1193 break;
1194 case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
1195 frame =
1196 _pointer_motion_abs(idev, libinput_event_get_pointer_event(event));
1197 break;
1198 case LIBINPUT_EVENT_POINTER_BUTTON:
1199 frame =
1200 _pointer_button(idev, libinput_event_get_pointer_event(event));
1201 break;
1202 case LIBINPUT_EVENT_POINTER_AXIS:
1203 frame =
1204 _pointer_axis(idev, libinput_event_get_pointer_event(event));
1205 break;
1206 case LIBINPUT_EVENT_TOUCH_DOWN:
1207 _touch_down(idev, libinput_event_get_touch_event(event));
1208 break;
1209 case LIBINPUT_EVENT_TOUCH_MOTION:
1210 _touch_motion(idev, libinput_event_get_touch_event(event));
1211 break;
1212 case LIBINPUT_EVENT_TOUCH_UP:
1213 _touch_up(idev, libinput_event_get_touch_event(event));
1214 break;
1215 case LIBINPUT_EVENT_TOUCH_FRAME:
1216 default:
1217 ret = 0;
1218 break;
1219 }
1220
1221 if (frame)
1222 {
1223 Elput_Device *edev;
1224
1225 edev = libinput_device_get_user_data(idev);
1226 if (edev) _seat_frame_send(edev->seat);
1227 }
1228
1229 return ret;
1230}
1231
1232Elput_Device *
1233_evdev_device_create(Elput_Seat *seat, struct libinput_device *device)
1234{
1235 Elput_Device *edev;
1236
1237 edev = calloc(1, sizeof(Elput_Device));
1238 if (!edev) return NULL;
1239
1240 edev->seat = seat;
1241 edev->device = device;
1242
1243 if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_KEYBOARD))
1244 {
1245 _keyboard_init(seat, NULL);
1246 edev->caps |= EVDEV_SEAT_KEYBOARD;
1247 }
1248
1249 if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_POINTER))
1250 {
1251 _pointer_init(seat);
1252 edev->caps |= EVDEV_SEAT_POINTER;
1253 }
1254
1255 if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TOUCH))
1256 {
1257 _touch_init(seat);
1258 edev->caps |= EVDEV_SEAT_TOUCH;
1259 }
1260
1261 libinput_device_set_user_data(device, edev);
1262 libinput_device_ref(edev->device);
1263
1264 if (libinput_device_config_tap_get_finger_count(edev->device) > 0)
1265 {
1266 Eina_Bool enable = EINA_FALSE;
1267
1268 enable = libinput_device_config_tap_get_default_enabled(edev->device);
1269 libinput_device_config_tap_set_enabled(edev->device, enable);
1270 }
1271
1272 /* FIXME: Normally we would do a device calibration set here however
1273 * that requires Output support. Since this is just an input library, we
1274 * may need to add external facing APIs to do calibration. Then a user of
1275 * elput would handle outputs, and make calls to calibrate */
1276
1277 return edev;
1278}
1279
1280void
1281_evdev_device_destroy(Elput_Device *edev)
1282{
1283 if (!edev) return;
1284
1285 if (edev->caps & EVDEV_SEAT_POINTER)
1286 _pointer_release(edev->seat);
1287 if (edev->caps & EVDEV_SEAT_KEYBOARD)
1288 _keyboard_release(edev->seat);
1289 if (edev->caps & EVDEV_SEAT_TOUCH)
1290 _touch_release(edev->seat);
1291
1292 libinput_device_unref(edev->device);
1293 eina_stringshare_del(edev->output_name);
1294 free(edev);
1295}
1296
1297void
1298_evdev_keyboard_destroy(Elput_Keyboard *kbd)
1299{
1300 free((char *)kbd->names.rules);
1301 free((char *)kbd->names.model);
1302 free((char *)kbd->names.layout);
1303 free((char *)kbd->names.variant);
1304 free((char *)kbd->names.options);
1305
1306 if (kbd->state) xkb_state_unref(kbd->state);
1307 if (kbd->info) _keyboard_info_destroy(kbd->info, kbd->external_map);
1308
1309 xkb_context_unref(kbd->context);
1310 xkb_keymap_unref(kbd->pending_map);
1311
1312 free(kbd);
1313}
1314
1315void
1316_evdev_pointer_destroy(Elput_Pointer *ptr)
1317{
1318 /* FIXME: destroy any resources inside pointer structure */
1319 free(ptr);
1320}
1321
1322void
1323_evdev_touch_destroy(Elput_Touch *touch)
1324{
1325 /* FIXME: destroy any resources inside touch structure */
1326 free(touch);
1327}
1328
1329Elput_Pointer *
1330_evdev_pointer_get(Elput_Seat *seat)
1331{
1332 if (!seat) return NULL;
1333 if (seat->count.ptr) return seat->ptr;
1334 return NULL;
1335}
1336
1337Elput_Keyboard *
1338_evdev_keyboard_get(Elput_Seat *seat)
1339{
1340 if (!seat) return NULL;
1341 if (seat->count.kbd) return seat->kbd;
1342 return NULL;
1343}
1344
1345Elput_Touch *
1346_evdev_touch_get(Elput_Seat *seat)
1347{
1348 if (!seat) return NULL;
1349 if (seat->count.touch) return seat->touch;
1350 return NULL;
1351}
1352
1353EAPI void
1354elput_device_window_set(Elput_Device *device, unsigned int window)
1355{
1356 EINA_SAFETY_ON_NULL_RETURN(device);
1357
1358 device->window = window;
1359}
1360
1361EAPI void
1362elput_device_output_size_set(Elput_Device *device, int w, int h)
1363{
1364 EINA_SAFETY_ON_NULL_RETURN(device);
1365
1366 device->ow = w;
1367 device->oh = h;
1368
1369 if (libinput_device_has_capability(device->device,
1370 LIBINPUT_DEVICE_CAP_POINTER))
1371 {
1372 Elput_Pointer *ptr;
1373
1374 ptr = _evdev_pointer_get(device->seat);
1375 if (ptr)
1376 {
1377 ptr->x = device->ow / 2;
1378 ptr->y = device->oh / 2;
1379 }
1380 }
1381
1382 _evdev_device_calibrate(device);
1383}
diff --git a/src/lib/elput/elput_input.c b/src/lib/elput/elput_input.c
new file mode 100644
index 0000000000..6c43f2f03d
--- /dev/null
+++ b/src/lib/elput/elput_input.c
@@ -0,0 +1,277 @@
1#include "elput_private.h"
2
3static int
4_cb_open_restricted(const char *path, int flags, void *data)
5{
6 Elput_Manager *em;
7
8 em = data;
9 return elput_manager_open(em, path, flags);
10}
11
12static void
13_cb_close_restricted(int fd, void *data)
14{
15 Elput_Manager *em;
16
17 em = data;
18 elput_manager_close(em, fd);
19}
20
21const struct libinput_interface _input_interface =
22{
23 _cb_open_restricted,
24 _cb_close_restricted,
25};
26
27static Elput_Seat *
28_udev_seat_create(Elput_Manager *em, const char *name)
29{
30 Elput_Seat *eseat;
31
32 eseat = calloc(1, sizeof(Elput_Seat));
33 if (!eseat) return NULL;
34
35 eseat->name = eina_stringshare_add(name);
36 em->input.seats = eina_list_append(em->input.seats, eseat);
37
38 return eseat;
39}
40
41static void
42_udev_seat_destroy(Elput_Seat *eseat)
43{
44 Elput_Device *edev;
45
46 EINA_LIST_FREE(eseat->devices, edev)
47 _evdev_device_destroy(edev);
48
49 if (eseat->kbd) _evdev_keyboard_destroy(eseat->kbd);
50 if (eseat->ptr) _evdev_pointer_destroy(eseat->ptr);
51 if (eseat->touch) _evdev_touch_destroy(eseat->touch);
52
53 eina_stringshare_del(eseat->name);
54 free(eseat);
55}
56
57static Elput_Seat *
58_udev_seat_named_get(Elput_Manager *em, const char *name)
59{
60 Elput_Seat *eseat;
61 Eina_List *l;
62
63 EINA_LIST_FOREACH(em->input.seats, l, eseat)
64 if (!strcmp(eseat->name, name)) return eseat;
65
66 return _udev_seat_create(em, name);
67}
68
69static Elput_Seat *
70_udev_seat_get(Elput_Manager *em, struct libinput_device *device)
71{
72 struct libinput_seat *lseat;
73 const char *name;
74
75 lseat = libinput_device_get_seat(device);
76 name = libinput_seat_get_logical_name(lseat);
77
78 return _udev_seat_named_get(em, name);
79}
80
81static void
82_device_event_cb_free(void *data EINA_UNUSED, void *event)
83{
84 Elput_Event_Device_Change *ev;
85
86 ev = event;
87
88 if (ev->type == ELPUT_DEVICE_REMOVED)
89 {
90 Elput_Seat *seat;
91
92 seat = ev->device->seat;
93 if (seat)
94 seat->devices = eina_list_remove(seat->devices, ev->device);
95
96 _evdev_device_destroy(ev->device);
97 }
98
99 free(ev);
100}
101
102static void
103_device_event_send(Elput_Device *edev, Elput_Device_Change_Type type)
104{
105 Elput_Event_Device_Change *ev;
106
107 ev = calloc(1, sizeof(Elput_Event_Device_Change));
108 if (!ev) return;
109
110 ev->device = edev;
111 ev->type = type;
112
113 ecore_event_add(ELPUT_EVENT_DEVICE_CHANGE, ev, _device_event_cb_free, NULL);
114}
115
116static void
117_device_add(Elput_Manager *em, struct libinput_device *dev)
118{
119 Elput_Seat *eseat;
120 Elput_Device *edev;
121 const char *oname;
122
123 eseat = _udev_seat_get(em, dev);
124 if (!eseat) return;
125
126 edev = _evdev_device_create(eseat, dev);
127 if (!edev) return;
128
129 oname = libinput_device_get_output_name(dev);
130 eina_stringshare_replace(&edev->output_name, oname);
131
132 eseat->devices = eina_list_append(eseat->devices, edev);
133
134 _device_event_send(edev, ELPUT_DEVICE_ADDED);
135}
136
137static void
138_device_remove(Elput_Manager *em EINA_UNUSED, struct libinput_device *device)
139{
140 /* Elput_Seat *eseat; */
141 Elput_Device *edev;
142
143 edev = libinput_device_get_user_data(device);
144 if (!edev) return;
145
146 /* eseat = _udev_seat_get(em, device); */
147 /* if (eseat) */
148 /* eseat->devices = eina_list_remove(eseat->devices, edev); */
149
150 _device_event_send(edev, ELPUT_DEVICE_REMOVED);
151 /* _evdev_device_destroy(edev); */
152}
153
154static int
155_udev_process_event(struct libinput_event *event)
156{
157 Elput_Manager *em;
158 struct libinput *lib;
159 struct libinput_device *dev;
160 int ret = 1;
161
162 lib = libinput_event_get_context(event);
163 dev = libinput_event_get_device(event);
164 em = libinput_get_user_data(lib);
165
166 switch (libinput_event_get_type(event))
167 {
168 case LIBINPUT_EVENT_DEVICE_ADDED:
169 DBG("Input Device Added: %s", libinput_device_get_name(dev));
170 _device_add(em, dev);
171 break;
172 case LIBINPUT_EVENT_DEVICE_REMOVED:
173 DBG("Input Device Removed: %s", libinput_device_get_name(dev));
174 _device_remove(em, dev);
175 break;
176 default:
177 ret = 0;
178 break;
179 }
180
181 return ret;
182}
183
184static void
185_process_event(struct libinput_event *event)
186{
187 if (_udev_process_event(event)) return;
188 if (_evdev_event_process(event)) return;
189}
190
191static void
192_process_events(Elput_Input *ei)
193{
194 struct libinput_event *event;
195
196 while ((event = libinput_get_event(ei->lib)))
197 {
198 _process_event(event);
199 libinput_event_destroy(event);
200 }
201}
202
203static Eina_Bool
204_cb_input_dispatch(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED)
205{
206 Elput_Input *ei;
207
208 ei = data;
209
210 if (libinput_dispatch(ei->lib) != 0)
211 WRN("libinput failed to dispatch events");
212
213 _process_events(ei);
214
215 return EINA_TRUE;
216}
217
218EAPI Eina_Bool
219elput_input_init(Elput_Manager *manager, const char *seat)
220{
221 int fd;
222
223 EINA_SAFETY_ON_NULL_RETURN_VAL(manager, EINA_FALSE);
224
225 memset(&manager->input, 0, sizeof(Elput_Input));
226
227 manager->input.lib =
228 libinput_udev_create_context(&_input_interface, manager, eeze_udev_get());
229 if (!manager->input.lib)
230 {
231 ERR("libinput could not create udev context");
232 goto udev_err;
233 }
234
235 if (libinput_udev_assign_seat(manager->input.lib, seat) != 0)
236 {
237 ERR("libinput could not assign udev seat");
238 goto seat_err;
239 }
240
241 _process_events(&manager->input);
242
243 fd = libinput_get_fd(manager->input.lib);
244
245 manager->input.hdlr =
246 ecore_main_fd_handler_add(fd, ECORE_FD_READ, _cb_input_dispatch,
247 &manager->input, NULL, NULL);
248 if (!manager->input.hdlr)
249 {
250 ERR("Could not create input fd handler");
251 goto hdlr_err;
252 }
253
254 return EINA_TRUE;
255
256hdlr_err:
257seat_err:
258 libinput_unref(manager->input.lib);
259udev_err:
260 return EINA_FALSE;
261}
262
263EAPI void
264elput_input_shutdown(Elput_Manager *manager)
265{
266 Elput_Seat *seat;
267
268 EINA_SAFETY_ON_NULL_RETURN(manager);
269 EINA_SAFETY_ON_NULL_RETURN(&manager->input);
270
271 if (manager->input.hdlr) ecore_main_fd_handler_del(manager->input.hdlr);
272
273 EINA_LIST_FREE(manager->input.seats, seat)
274 _udev_seat_destroy(seat);
275
276 libinput_unref(manager->input.lib);
277}
diff --git a/src/lib/elput/elput_logind.c b/src/lib/elput/elput_logind.c
new file mode 100644
index 0000000000..e829b4ac12
--- /dev/null
+++ b/src/lib/elput/elput_logind.c
@@ -0,0 +1,569 @@
1#include "elput_private.h"
2
3#ifdef HAVE_SYSTEMD
4
5static void
6_logind_device_pause_complete(Elput_Manager *em, uint32_t major, uint32_t minor)
7{
8 Eldbus_Proxy *proxy;
9 Eldbus_Message *msg;
10
11 proxy =
12 eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session");
13 if (!proxy)
14 {
15 ERR("Could not get proxy for session");
16 return;
17 }
18
19 msg = eldbus_proxy_method_call_new(proxy, "PauseDeviceComplete");
20 if (!msg)
21 {
22 ERR("Could not create method call for proxy");
23 goto end;
24 }
25
26 eldbus_message_arguments_append(msg, "uu", major, minor);
27
28 eldbus_proxy_send(proxy, msg, NULL, NULL, -1);
29
30end:
31 eldbus_message_unref(msg);
32 eldbus_proxy_unref(proxy);
33}
34
35static void
36_cb_session_removed(void *data, const Eldbus_Message *msg)
37{
38 Elput_Manager *em;
39 const char *errname, *errmsg;
40 const char *sid;
41
42 em = data;
43
44 if (eldbus_message_error_get(msg, &errname, &errmsg))
45 {
46 ERR("Eldbus Message Error: %s %s", errname, errmsg);
47 return;
48 }
49
50 if (eldbus_message_arguments_get(msg, "s", &sid))
51 {
52 if (!strcmp(sid, em->sid))
53 {
54 WRN("Logind session removed");
55 /* TODO: call manager restore function */
56 }
57 }
58}
59
60static void
61_cb_device_paused(void *data, const Eldbus_Message *msg)
62{
63 Elput_Manager *em;
64 const char *errname, *errmsg;
65 const char *type;
66 uint32_t maj, min;
67
68 em = data;
69
70 if (eldbus_message_error_get(msg, &errname, &errmsg))
71 {
72 ERR("Eldbus Message Error: %s %s", errname, errmsg);
73 return;
74 }
75
76 if (eldbus_message_arguments_get(msg, "uus", &maj, &min, &type))
77 {
78 if (!strcmp(type, "pause"))
79 _logind_device_pause_complete(em, maj, min);
80
81 if ((em->sync) && (maj == 226)) // DRM_MAJOR
82 {
83 /* TODO: _ecore_drm2_launcher_activate_send(em, EINA_FALSE); */
84 }
85 }
86}
87
88static void
89_cb_device_resumed(void *data, const Eldbus_Message *msg)
90{
91 Elput_Manager *em;
92 const char *errname, *errmsg;
93 uint32_t maj, min;
94 int fd;
95
96 em = data;
97
98 if (eldbus_message_error_get(msg, &errname, &errmsg))
99 {
100 ERR("Eldbus Message Error: %s %s", errname, errmsg);
101 return;
102 }
103
104 if (eldbus_message_arguments_get(msg, "uuh", &maj, &min, &fd))
105 {
106 if ((em->sync) && (maj == 226)) // DRM_MAJOR
107 {
108 /* TODO: _ecore_drm2_launcher_activate_send(em, EINA_TRUE); */
109 }
110 }
111}
112
113static void
114_cb_property_changed(void *data, Eldbus_Proxy *proxy EINA_UNUSED, void *event)
115{
116 Elput_Manager *em;
117 Eldbus_Proxy_Event_Property_Changed *ev;
118 Eina_Bool active = EINA_FALSE;
119
120 em = data;
121 ev = event;
122
123 DBG("DBus Property Changed: %s", ev->name);
124
125 if (!strcmp(ev->name, "Active"))
126 {
127 eina_value_get(ev->value, &active);
128 if ((!em->sync) || (!active))
129 {
130 /* TODO: _ecore_drm2_launcher_activate_send(em, active); */
131 }
132 }
133}
134
135static Eina_Bool
136_logind_session_vt_get(const char *sid, unsigned int *vt)
137{
138# ifdef HAVE_SYSTEMD_LOGIN_209
139 return (sd_session_get_vt(sid, vt) >= 0);
140# else
141 int ret = 0;
142 char *tty;
143
144 ret = sd_session_get_tty(sid, &tty);
145 if (ret < 0) return ret;
146
147 ret = sscanf(tty, "tty%u", vt);
148 free(tty);
149
150 if (ret != 1) return EINA_FALSE;
151 return EINA_TRUE;
152# endif
153}
154
155static Eina_Bool
156_logind_dbus_open(Eldbus_Connection **conn)
157{
158 if (!eldbus_init()) return EINA_FALSE;
159
160 *conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM);
161 if (!*conn) return EINA_FALSE;
162
163 return EINA_TRUE;
164}
165
166static void
167_logind_dbus_close(Eldbus_Connection *conn)
168{
169 if (conn) eldbus_connection_unref(conn);
170 eldbus_shutdown();
171}
172
173static Eina_Bool
174_logind_dbus_setup(Elput_Manager *em)
175{
176 Eldbus_Proxy *proxy;
177 int ret = 0;
178
179 ret = asprintf(&em->dbus.path,
180 "/org/freedesktop/login1/session/%s", em->sid);
181 if (ret < 0) return EINA_FALSE;
182
183 em->dbus.obj =
184 eldbus_object_get(em->dbus.conn, "org.freedesktop.login1",
185 em->dbus.path);
186 if (!em->dbus.obj)
187 {
188 ERR("Could not get dbus object");
189 goto obj_err;
190 }
191
192 proxy =
193 eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Manager");
194 if (!proxy)
195 {
196 ERR("Could not get dbus proxy");
197 goto proxy_err;
198 }
199
200 eldbus_proxy_signal_handler_add(proxy, "SessionRemoved",
201 _cb_session_removed, em);
202 eldbus_proxy_unref(proxy);
203
204 proxy =
205 eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session");
206 if (!proxy)
207 {
208 ERR("Could not get dbus proxy");
209 goto proxy_err;
210 }
211
212 eldbus_proxy_signal_handler_add(proxy, "PauseDevice",
213 _cb_device_paused, em);
214 eldbus_proxy_signal_handler_add(proxy, "ResumeDevice",
215 _cb_device_resumed, em);
216 eldbus_proxy_unref(proxy);
217
218 proxy =
219 eldbus_proxy_get(em->dbus.obj, "org.freedesktop.DBus.Properties");
220 if (!proxy)
221 {
222 ERR("Could not get dbus proxy");
223 goto proxy_err;
224 }
225
226 eldbus_proxy_properties_monitor(proxy, EINA_TRUE);
227 eldbus_proxy_event_callback_add(proxy, ELDBUS_PROXY_EVENT_PROPERTY_CHANGED,
228 _cb_property_changed, em);
229 eldbus_proxy_unref(proxy);
230
231 return EINA_TRUE;
232
233proxy_err:
234 eldbus_object_unref(em->dbus.obj);
235obj_err:
236 free(em->dbus.path);
237 return EINA_FALSE;
238}
239
240static Eina_Bool
241_logind_control_take(Elput_Manager *em)
242{
243 Eldbus_Proxy *proxy;
244 Eldbus_Message *msg, *reply;
245 const char *errname, *errmsg;
246
247 proxy =
248 eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session");
249 if (!proxy)
250 {
251 ERR("Could not get proxy for session");
252 return EINA_FALSE;
253 }
254
255 msg = eldbus_proxy_method_call_new(proxy, "TakeControl");
256 if (!msg)
257 {
258 ERR("Could not create method call for proxy");
259 goto msg_err;
260 }
261
262 eldbus_message_arguments_append(msg, "b", EINA_FALSE);
263
264 reply = eldbus_proxy_send_and_block(proxy, msg, -1);
265 if (eldbus_message_error_get(reply, &errname, &errmsg))
266 {
267 ERR("Eldbus Message Error: %s %s", errname, errmsg);
268 goto msg_err;
269 }
270
271 eldbus_message_unref(reply);
272 eldbus_proxy_unref(proxy);
273
274 return EINA_TRUE;
275
276msg_err:
277 eldbus_proxy_unref(proxy);
278 return EINA_FALSE;
279}
280
281static void
282_logind_control_release(Elput_Manager *em)
283{
284 Eldbus_Proxy *proxy;
285 Eldbus_Message *msg;
286
287 proxy =
288 eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session");
289 if (!proxy)
290 {
291 ERR("Could not get proxy for session");
292 return;
293 }
294
295 msg = eldbus_proxy_method_call_new(proxy, "ReleaseControl");
296 if (!msg)
297 {
298 ERR("Could not create method call for proxy");
299 goto end;
300 }
301
302 eldbus_proxy_send(proxy, msg, NULL, NULL, -1);
303
304end:
305 eldbus_proxy_unref(proxy);
306}
307
308static int
309_logind_device_take(Elput_Manager *em, uint32_t major, uint32_t minor)
310{
311 Eldbus_Proxy *proxy;
312 Eldbus_Message *msg, *reply;
313 Eina_Bool p = EINA_FALSE;
314 const char *errname, *errmsg;
315 int fd = -1;
316
317 proxy =
318 eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session");
319 if (!proxy)
320 {
321 ERR("Could not get dbus proxy");
322 return -1;
323 }
324
325 msg = eldbus_proxy_method_call_new(proxy, "TakeDevice");
326 if (!msg)
327 {
328 ERR("Could not create method call for proxy");
329 goto err;
330 }
331
332 eldbus_message_arguments_append(msg, "uu", major, minor);
333
334 reply = eldbus_proxy_send_and_block(proxy, msg, -1);
335 if (eldbus_message_error_get(reply, &errname, &errmsg))
336 {
337 ERR("Eldbus Message Error: %s %s", errname, errmsg);
338 goto err;
339 }
340
341 if (!eldbus_message_arguments_get(reply, "hb", &fd, &p))
342 ERR("Could not get UNIX_FD from dbus message");
343
344 eldbus_message_unref(reply);
345
346err:
347 eldbus_proxy_unref(proxy);
348 return fd;
349}
350
351static void
352_logind_device_release(Elput_Manager *em, uint32_t major, uint32_t minor)
353{
354 Eldbus_Proxy *proxy;
355 Eldbus_Message *msg;
356
357 proxy =
358 eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session");
359 if (!proxy)
360 {
361 ERR("Could not get proxy for session");
362 return;
363 }
364
365 msg = eldbus_proxy_method_call_new(proxy, "ReleaseDevice");
366 if (!msg)
367 {
368 ERR("Could not create method call for proxy");
369 goto end;
370 }
371
372 eldbus_message_arguments_append(msg, "uu", major, minor);
373
374 eldbus_proxy_send(proxy, msg, NULL, NULL, -1);
375
376end:
377 eldbus_proxy_unref(proxy);
378}
379
380static Eina_Bool
381_logind_activate(Elput_Manager *em)
382{
383 Eldbus_Proxy *proxy;
384 Eldbus_Message *msg;
385
386 proxy =
387 eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session");
388 if (!proxy)
389 {
390 ERR("Could not get proxy for session");
391 return EINA_FALSE;
392 }
393
394 msg = eldbus_proxy_method_call_new(proxy, "Activate");
395 if (!msg)
396 {
397 ERR("Could not create method call for proxy");
398 goto msg_err;
399 }
400
401 eldbus_proxy_send(proxy, msg, NULL, NULL, -1);
402
403 eldbus_proxy_unref(proxy);
404
405 return EINA_TRUE;
406
407msg_err:
408 eldbus_proxy_unref(proxy);
409 return EINA_FALSE;
410}
411
412static Eina_Bool
413_logind_connect(Elput_Manager **manager, const char *seat, unsigned int tty, Eina_Bool sync)
414{
415 Elput_Manager *em;
416 int ret = 0;
417 char *s;
418
419 em = calloc(1, sizeof(Elput_Manager));
420 if (!em) return EINA_FALSE;
421
422 em->interface = &_logind_interface;
423 em->sync = sync;
424 em->seat = eina_stringshare_add(seat);
425
426 ret = sd_pid_get_session(getpid(), &em->sid);
427 if (ret < 0)
428 {
429 ERR("Could not get systemd session");
430 goto session_err;
431 }
432
433 ret = sd_session_get_seat(em->sid, &s);
434 if (ret < 0)
435 {
436 ERR("Failed to get session seat");
437 free(s);
438 goto seat_err;
439 }
440 else if ((seat) && (strcmp(seat, s)))
441 {
442 ERR("Seat '%s' differs from session seat '%s'", seat, s);
443 free(s);
444 goto seat_err;
445 }
446
447 if (!_logind_session_vt_get(em->sid, &em->vt_num))
448 {
449 ERR("Could not get session vt");
450 goto vt_err;
451 }
452 else if ((tty > 0) && (em->vt_num != tty))
453 {
454 ERR("Requested VT %u differs from session VT %u", tty, em->vt_num);
455 goto vt_err;
456 }
457
458 free(s);
459
460 if (!_logind_dbus_open(&em->dbus.conn))
461 {
462 ERR("Could not connect to dbus");
463 goto vt_err;
464 }
465
466 if (!_logind_dbus_setup(em))
467 {
468 ERR("Could not setup dbus");
469 goto dbus_err;
470 }
471
472 if (!_logind_control_take(em))
473 {
474 ERR("Could not take control of session");
475 goto ctrl_err;
476 }
477
478 if (!_logind_activate(em))
479 {
480 ERR("Could not activate session");
481 goto actv_err;
482 }
483
484 *(Elput_Manager **)manager = em;
485
486 return EINA_TRUE;
487
488actv_err:
489 _logind_control_release(em);
490ctrl_err:
491 eldbus_object_unref(em->dbus.obj);
492 free(em->dbus.path);
493dbus_err:
494 _logind_dbus_close(em->dbus.conn);
495vt_err:
496seat_err:
497 free(em->sid);
498session_err:
499 free(em);
500 return EINA_FALSE;
501}
502
503static void
504_logind_disconnect(Elput_Manager *em)
505{
506 _logind_control_release(em);
507 eldbus_object_unref(em->dbus.obj);
508 free(em->dbus.path);
509 _logind_dbus_close(em->dbus.conn);
510 eina_stringshare_del(em->seat);
511 free(em->sid);
512 free(em);
513}
514
515static int
516_logind_open(Elput_Manager *em, const char *path, int flags)
517{
518 struct stat st;
519 int ret, fd = -1;
520 int fl;
521
522 ret = stat(path, &st);
523 if (ret < 0) return -1;
524
525 if (!S_ISCHR(st.st_mode)) return -1;
526
527 fd = _logind_device_take(em, major(st.st_rdev), minor(st.st_rdev));
528 if (fd < 0) return fd;
529
530 fl = fcntl(fd, F_GETFL);
531 if (fl < 0) goto err;
532
533 if (flags & O_NONBLOCK)
534 fl |= O_NONBLOCK;
535
536 ret = fcntl(fd, F_SETFL, fl);
537 if (ret < 0) goto err;
538
539 return fd;
540
541err:
542 close(fd);
543 _logind_device_release(em, major(st.st_rdev), minor(st.st_rdev));
544 return -1;
545}
546
547static void
548_logind_close(Elput_Manager *em, int fd)
549{
550 struct stat st;
551 int ret;
552
553 ret = fstat(fd, &st);
554 if (ret < 0) return;
555
556 if (!S_ISCHR(st.st_mode)) return;
557
558 _logind_device_release(em, major(st.st_rdev), minor(st.st_rdev));
559}
560
561Elput_Interface _logind_interface =
562{
563 _logind_connect,
564 _logind_disconnect,
565 _logind_open,
566 _logind_close,
567};
568
569#endif
diff --git a/src/lib/elput/elput_manager.c b/src/lib/elput/elput_manager.c
new file mode 100644
index 0000000000..3dc67d9594
--- /dev/null
+++ b/src/lib/elput/elput_manager.c
@@ -0,0 +1,64 @@
1#include "elput_private.h"
2
3static Elput_Interface *_ifaces[] =
4{
5#ifdef HAVE_SYSTEMD
6 &_logind_interface,
7#endif
8 NULL, // launcher
9 NULL, // direct
10 NULL,
11};
12
13EAPI Elput_Manager *
14elput_manager_connect(const char *seat, unsigned int tty, Eina_Bool sync)
15{
16 Elput_Interface **it;
17
18 for (it = _ifaces; *it != NULL; it++)
19 {
20 Elput_Interface *iface;
21 Elput_Manager *em;
22
23 iface = *it;
24 if (iface->connect(&em, seat, tty, sync))
25 return em;
26 }
27
28 return NULL;
29}
30
31EAPI void
32elput_manager_disconnect(Elput_Manager *manager)
33{
34 EINA_SAFETY_ON_NULL_RETURN(manager);
35 EINA_SAFETY_ON_NULL_RETURN(manager->interface);
36
37 if (manager->interface->disconnect)
38 manager->interface->disconnect(manager);
39}
40
41EAPI int
42elput_manager_open(Elput_Manager *manager, const char *path, int flags)
43{
44 EINA_SAFETY_ON_NULL_RETURN_VAL(manager, -1);
45 EINA_SAFETY_ON_NULL_RETURN_VAL(manager->interface, -1);
46 EINA_SAFETY_ON_NULL_RETURN_VAL(path, -1);
47
48 if (flags < 0) flags = O_RDWR;
49
50 if (manager->interface->open)
51 return manager->interface->open(manager, path, flags);
52
53 return -1;
54}
55
56EAPI void
57elput_manager_close(Elput_Manager *manager, int fd)
58{
59 EINA_SAFETY_ON_NULL_RETURN(manager);
60 EINA_SAFETY_ON_NULL_RETURN(manager->interface);
61
62 if (manager->interface->close)
63 manager->interface->close(manager, fd);
64}
diff --git a/src/lib/elput/elput_private.h b/src/lib/elput/elput_private.h
new file mode 100644
index 0000000000..3564161375
--- /dev/null
+++ b/src/lib/elput/elput_private.h
@@ -0,0 +1,250 @@
1#ifndef _ELPUT_PRIVATE_H
2# define _ELPUT_PRIVATE_H
3
4# ifdef HAVE_CONFIG_H
5# include "config.h"
6# endif
7
8# include "Ecore.h"
9# include "ecore_private.h"
10# include "Ecore_Input.h"
11# include "Eeze.h"
12# include "Eldbus.h"
13# include <Elput.h>
14
15# include <ctype.h>
16# include <sys/mman.h>
17# include <fcntl.h>
18# include <unistd.h>
19# include <linux/vt.h>
20# include <linux/kd.h>
21# include <linux/major.h>
22# include <linux/input.h>
23# include <libinput.h>
24# include <xkbcommon/xkbcommon.h>
25
26# ifdef HAVE_SYSTEMD
27# include <systemd/sd-login.h>
28# endif
29
30# ifdef ELPUT_DEFAULT_LOG_COLOR
31# undef ELPUT_DEFAULT_LOG_COLOR
32# endif
33# define ELPUT_DEFAULT_LOG_COLOR EINA_COLOR_GREEN
34
35extern int _elput_log_dom;
36
37# ifdef ERR
38# undef ERR
39# endif
40# define ERR(...) EINA_LOG_DOM_ERR(_elput_log_dom, __VA_ARGS__)
41
42# ifdef DBG
43# undef DBG
44# endif
45# define DBG(...) EINA_LOG_DOM_DBG(_elput_log_dom, __VA_ARGS__)
46
47# ifdef INF
48# undef INF
49# endif
50# define INF(...) EINA_LOG_DOM_INFO(_elput_log_dom, __VA_ARGS__)
51
52# ifdef WRN
53# undef WRN
54# endif
55# define WRN(...) EINA_LOG_DOM_WARN(_elput_log_dom, __VA_ARGS__)
56
57# ifdef CRIT
58# undef CRIT
59# endif
60# define CRIT(...) EINA_LOG_DOM_CRIT(_elput_log_dom, __VA_ARGS__)
61
62typedef enum _Elput_Device_Capability
63{
64 EVDEV_SEAT_POINTER = (1 << 0),
65 EVDEV_SEAT_KEYBOARD = (1 << 1),
66 EVDEV_SEAT_TOUCH = (1 << 2)
67} Elput_Device_Capability;
68
69typedef struct _Elput_Interface
70{
71 Eina_Bool (*connect)(Elput_Manager **manager, const char *seat, unsigned int tty, Eina_Bool sync);
72 void (*disconnect)(Elput_Manager *manager);
73 int (*open)(Elput_Manager *manager, const char *path, int flags);
74 void (*close)(Elput_Manager *manager, int fd);
75} Elput_Interface;
76
77typedef struct _Elput_Input
78{
79 struct libinput *lib;
80
81 Ecore_Fd_Handler *hdlr;
82
83 Eina_List *seats;
84
85 Eina_Bool suspended : 1;
86} Elput_Input;
87
88typedef struct _Elput_Keyboard_Info
89{
90 int refs;
91
92 struct
93 {
94 int fd;
95 size_t size;
96 char *area;
97 struct xkb_keymap *map;
98 } keymap;
99
100 struct
101 {
102 xkb_mod_index_t shift;
103 xkb_mod_index_t caps;
104 xkb_mod_index_t ctrl;
105 xkb_mod_index_t alt;
106 xkb_mod_index_t altgr;
107 xkb_mod_index_t super;
108 } mods;
109} Elput_Keyboard_Info;
110
111struct _Elput_Keyboard
112{
113 struct
114 {
115 unsigned int depressed;
116 unsigned int latched;
117 unsigned int locked;
118 unsigned int group;
119 } mods;
120
121 struct
122 {
123 unsigned int key;
124 unsigned int timestamp;
125 } grab;
126
127 Elput_Keyboard_Info *info;
128
129 struct xkb_state *state;
130 struct xkb_keymap *pending_map;
131 struct xkb_context *context;
132 struct xkb_rule_names names;
133
134 Elput_Seat *seat;
135
136 Eina_Bool external_map : 1;
137};
138
139struct _Elput_Pointer
140{
141 double x, y;
142 int buttons;
143 unsigned int timestamp;
144
145 int minx, miny;
146 int maxw, maxh;
147 int hotx, hoty;
148
149 struct
150 {
151 double x, y;
152 unsigned int button;
153 unsigned int timestamp;
154 } grab;
155
156 struct
157 {
158 unsigned int threshold;
159 unsigned int last_button, prev_button;
160 unsigned int last_time, prev_time;
161 Eina_Bool double_click : 1;
162 Eina_Bool triple_click : 1;
163 } mouse;
164
165 Elput_Seat *seat;
166};
167
168struct _Elput_Touch
169{
170 double x, y;
171 int slot;
172 unsigned int points;
173
174 struct
175 {
176 int id;
177 double x, y;
178 unsigned int timestamp;
179 } grab;
180
181 Elput_Seat *seat;
182};
183
184struct _Elput_Seat
185{
186 const char *name;
187
188 struct
189 {
190 int kbd, ptr, touch;
191 } count;
192
193 unsigned int modifiers;
194
195 Elput_Keyboard *kbd;
196 Elput_Pointer *ptr;
197 Elput_Touch *touch;
198
199 Eina_List *devices;
200};
201
202struct _Elput_Device
203{
204 Elput_Seat *seat;
205
206 uint32_t window;
207 uint32_t ow, oh;
208
209 const char *path;
210 const char *output_name;
211 struct libinput_device *device;
212
213 Elput_Device_Capability caps;
214};
215
216struct _Elput_Manager
217{
218 Elput_Interface *interface;
219
220 int fd;
221 char *sid;
222 const char *seat;
223 unsigned int vt_num;
224
225 struct
226 {
227 char *path;
228 Eldbus_Object *obj;
229 Eldbus_Connection *conn;
230 } dbus;
231
232 Elput_Input input;
233
234 Eina_Bool sync : 1;
235};
236
237int _evdev_event_process(struct libinput_event *event);
238Elput_Device *_evdev_device_create(Elput_Seat *seat, struct libinput_device *device);
239void _evdev_device_destroy(Elput_Device *edev);
240void _evdev_keyboard_destroy(Elput_Keyboard *kbd);
241void _evdev_pointer_destroy(Elput_Pointer *ptr);
242void _evdev_touch_destroy(Elput_Touch *touch);
243
244Elput_Pointer *_evdev_pointer_get(Elput_Seat *seat);
245Elput_Keyboard *_evdev_keyboard_get(Elput_Seat *seat);
246Elput_Touch *_evdev_touch_get(Elput_Seat *seat);
247
248extern Elput_Interface _logind_interface;
249
250#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 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include "elput_suite.h"
6#include "../efl_check.h"
7
8static const Efl_Test_Case etc[] =
9{
10#if HAVE_ELPUT
11 { "Elput", elput_test_elput },
12#endif
13 { NULL, NULL }
14};
15
16int
17main(int argc, char **argv)
18{
19 int count;
20
21 if (!_efl_test_option_disp(argc, argv, etc)) return 0;
22
23 putenv("EFL_RUN_IN_TREE=1");
24
25 count =
26 _efl_suite_build_and_run(argc - 1, (const char **)argv + 1, "Elput", etc);
27
28 return (count == 0) ? 0 : 255;
29}
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 @@
1#ifndef _ELPUT_SUITE_H
2# define _ELPUT_SUITE_H
3
4# include <check.h>
5
6void elput_test_elput(TCase *tc);
7
8#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 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <stdio.h>
6#include <unistd.h>
7
8#include <Eina.h>
9#include <Ecore.h>
10#include <Elput.h>
11
12#include "elput_suite.h"
13
14START_TEST(elput_test_elput_init)
15{
16 int ret;
17
18 ret = elput_init();
19 fail_if(ret < 1);
20
21 ret = elput_shutdown();
22 fail_if(ret != 0);
23}
24END_TEST
25
26void elput_test_elput(TCase *tc)
27{
28 tcase_add_test(tc, elput_test_elput_init);
29}