summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--meson_options.txt4
-rw-r--r--src/bin/e_bindings.c141
-rw-r--r--src/bin/e_bindings.h30
-rw-r--r--src/bin/e_config.c28
-rw-r--r--src/bin/e_config.h12
-rw-r--r--src/modules/conf_bindings/e_int_config_swipebindings.c978
-rw-r--r--src/modules/conf_bindings/e_mod_main.c4
-rw-r--r--src/modules/conf_bindings/e_mod_main.h2
-rw-r--r--src/modules/conf_bindings/meson.build1
-rw-r--r--src/modules/gesture_recognition/e_mod_main.c287
-rw-r--r--src/modules/gesture_recognition/meson.build5
-rw-r--r--src/modules/gesture_recognition/module.desktop6
-rw-r--r--src/modules/meson.build1
13 files changed, 1498 insertions, 1 deletions
diff --git a/meson_options.txt b/meson_options.txt
index 016dd8124..faedfeada 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -297,3 +297,7 @@ option('conf-window-remembers',
297 type: 'boolean', 297 type: 'boolean',
298 value: true, 298 value: true,
299 description: 'enable conf-window-remembers module: (default=true)') 299 description: 'enable conf-window-remembers module: (default=true)')
300option('gesture-recognition',
301 type: 'boolean',
302 value: true,
303 description: 'Enable gesture recognition using libinput, needed to get swipe bindings beeing detected.')
diff --git a/src/bin/e_bindings.c b/src/bin/e_bindings.c
index 084e6ef51..7e4c1408e 100644
--- a/src/bin/e_bindings.c
+++ b/src/bin/e_bindings.c
@@ -7,6 +7,7 @@ static void _e_bindings_edge_free(E_Binding_Edge *bind);
7static void _e_bindings_signal_free(E_Binding_Signal *bind); 7static void _e_bindings_signal_free(E_Binding_Signal *bind);
8static void _e_bindings_wheel_free(E_Binding_Wheel *bind); 8static void _e_bindings_wheel_free(E_Binding_Wheel *bind);
9static void _e_bindings_acpi_free(E_Binding_Acpi *bind); 9static void _e_bindings_acpi_free(E_Binding_Acpi *bind);
10static void _e_bindings_swipe_free(E_Binding_Swipe *bind);
10static Eina_Bool _e_bindings_edge_cb_timer(void *data); 11static Eina_Bool _e_bindings_edge_cb_timer(void *data);
11 12
12/* local subsystem globals */ 13/* local subsystem globals */
@@ -17,9 +18,13 @@ static Eina_List *edge_bindings = NULL;
17static Eina_List *signal_bindings = NULL; 18static Eina_List *signal_bindings = NULL;
18static Eina_List *wheel_bindings = NULL; 19static Eina_List *wheel_bindings = NULL;
19static Eina_List *acpi_bindings = NULL; 20static Eina_List *acpi_bindings = NULL;
21static Eina_List *swipe_bindings = NULL;
20 22
21static unsigned int bindings_disabled = 0; 23static unsigned int bindings_disabled = 0;
22 24
25static E_Bindings_Swipe_Live_Update live_update;
26static E_Bindings_Swipe_Live_Update live_update_data;
27
23EINTERN E_Action *(*e_binding_key_list_cb)(E_Binding_Context, Ecore_Event_Key*, E_Binding_Modifier, E_Binding_Key **); 28EINTERN E_Action *(*e_binding_key_list_cb)(E_Binding_Context, Ecore_Event_Key*, E_Binding_Modifier, E_Binding_Key **);
24 29
25typedef struct _E_Binding_Edge_Data E_Binding_Edge_Data; 30typedef struct _E_Binding_Edge_Data E_Binding_Edge_Data;
@@ -43,6 +48,7 @@ e_bindings_init(void)
43 E_Config_Binding_Edge *ebe; 48 E_Config_Binding_Edge *ebe;
44 E_Config_Binding_Key *ebk; 49 E_Config_Binding_Key *ebk;
45 E_Config_Binding_Acpi *eba; 50 E_Config_Binding_Acpi *eba;
51 E_Config_Binding_Acpi *ebsw;
46 Eina_List *l; 52 Eina_List *l;
47 53
48 EINA_LIST_FOREACH(e_bindings->mouse_bindings, l, ebm) 54 EINA_LIST_FOREACH(e_bindings->mouse_bindings, l, ebm)
@@ -86,6 +92,8 @@ e_bindings_init(void)
86 e_bindings_acpi_add(eba->context, eba->type, eba->status, 92 e_bindings_acpi_add(eba->context, eba->type, eba->status,
87 eba->action, eba->params); 93 eba->action, eba->params);
88 94
95 e_bindings_swipe_reset();
96
89 return 1; 97 return 1;
90} 98}
91 99
@@ -98,6 +106,7 @@ e_bindings_shutdown(void)
98 E_FREE_LIST(signal_bindings, _e_bindings_signal_free); 106 E_FREE_LIST(signal_bindings, _e_bindings_signal_free);
99 E_FREE_LIST(wheel_bindings, _e_bindings_wheel_free); 107 E_FREE_LIST(wheel_bindings, _e_bindings_wheel_free);
100 E_FREE_LIST(acpi_bindings, _e_bindings_acpi_free); 108 E_FREE_LIST(acpi_bindings, _e_bindings_acpi_free);
109 E_FREE_LIST(swipe_bindings, _e_bindings_swipe_free);
101 110
102 return 1; 111 return 1;
103} 112}
@@ -325,6 +334,18 @@ e_bindings_key_reset(void)
325} 334}
326 335
327E_API void 336E_API void
337e_bindings_swipe_reset(void)
338{
339 E_Config_Binding_Swipe *eswipe;
340 Eina_List *l;
341
342 E_FREE_LIST(swipe_bindings, _e_bindings_swipe_free);
343
344 EINA_LIST_FOREACH(e_bindings->swipe_bindings, l, eswipe)
345 e_bindings_swipe_add(eswipe->context, eswipe->direction, eswipe->length, eswipe->fingers, eswipe->error, eswipe->action, eswipe->params);
346}
347
348E_API void
328e_bindings_reset(void) 349e_bindings_reset(void)
329{ 350{
330 e_bindings_signal_reset(); 351 e_bindings_signal_reset();
@@ -332,6 +353,7 @@ e_bindings_reset(void)
332 e_bindings_wheel_reset(); 353 e_bindings_wheel_reset();
333 e_bindings_edge_reset(); 354 e_bindings_edge_reset();
334 e_bindings_key_reset(); 355 e_bindings_key_reset();
356 e_bindings_swipe_reset();
335} 357}
336 358
337E_API void 359E_API void
@@ -1514,6 +1536,14 @@ _e_bindings_acpi_free(E_Binding_Acpi *binding)
1514 E_FREE(binding); 1536 E_FREE(binding);
1515} 1537}
1516 1538
1539static void
1540_e_bindings_swipe_free(E_Binding_Swipe *binding)
1541{
1542 if (binding->action) eina_stringshare_del(binding->action);
1543 if (binding->params) eina_stringshare_del(binding->params);
1544 E_FREE(binding);
1545}
1546
1517E_API int 1547E_API int
1518e_bindings_context_match(E_Binding_Context bctxt, E_Binding_Context ctxt) 1548e_bindings_context_match(E_Binding_Context bctxt, E_Binding_Context ctxt)
1519{ 1549{
@@ -1583,3 +1613,114 @@ _e_bindings_edge_cb_timer(void *data)
1583 1613
1584 return ECORE_CALLBACK_CANCEL; 1614 return ECORE_CALLBACK_CANCEL;
1585} 1615}
1616
1617E_API void
1618e_bindings_swipe_add(E_Binding_Context ctxt, double direction, double length, unsigned int fingers, double error, const char *action, const char *params)
1619{
1620 E_Binding_Swipe *binding = E_NEW(E_Binding_Swipe, 1);
1621
1622 binding->ctxt = ctxt;
1623 binding->direction = direction;
1624 binding->length = length;
1625 binding->fingers = fingers;
1626 binding->error = error;
1627 if (action)
1628 binding->action = eina_stringshare_add(action);
1629 if (params)
1630 binding->params = eina_stringshare_add(params);
1631
1632 swipe_bindings = eina_list_append(swipe_bindings, binding);
1633}
1634
1635E_API void
1636e_bindings_swipe_del(E_Binding_Context ctxt, double direction, double length, unsigned int fingers, double error, const char *action, const char *params)
1637{
1638 E_Binding_Swipe *binding;
1639 Eina_List *n;
1640
1641 EINA_LIST_FOREACH(swipe_bindings, n, binding)
1642 {
1643 if (binding->ctxt == ctxt &&
1644 binding->action == action &&
1645 binding->params == params &&
1646 EINA_DBL_EQ(direction, binding->direction) &&
1647 EINA_DBL_EQ(length, binding->length) &&
1648 EINA_DBL_EQ(fingers, binding->fingers) &&
1649 EINA_DBL_EQ(error, binding->error))
1650 {
1651 _e_bindings_swipe_free(binding);
1652 swipe_bindings = eina_list_remove_list(swipe_bindings, n);
1653 break;
1654 }
1655 }
1656}
1657
1658E_API Eina_Bool
1659e_bindings_swipe_available(void)
1660{
1661 return eina_list_count(swipe_bindings) > 0;
1662}
1663
1664E_API E_Action*
1665e_bindings_swipe_handle(E_Binding_Context ctxt, E_Object *obj, double direction, double length, unsigned int fingers)
1666{
1667 E_Binding_Swipe *binding;
1668 Eina_List *n;
1669 E_Action *act = NULL;
1670
1671 EINA_LIST_FOREACH(swipe_bindings, n, binding)
1672 {
1673 if (binding->ctxt == ctxt &&
1674 binding->length < length &&
1675 EINA_DBL_EQ(fingers, binding->fingers) &&
1676 fmod(binding->direction - binding->error, 2*M_PI) < direction &&
1677 fmod(binding->direction + binding->error, 2*M_PI) > direction)
1678 {
1679 act = e_action_find(binding->action);
1680 act->func.go(obj, binding->params);
1681 }
1682 }
1683 return act;
1684}
1685
1686
1687E_API Eina_Inarray*
1688e_bindings_swipe_find_candidates(E_Binding_Context ctxt, double direction, double length, unsigned int fingers)
1689{
1690 Eina_Inarray *ret = eina_inarray_new(sizeof(E_Binding_Swipe_Candidate), 10);
1691 E_Binding_Swipe *binding;
1692 Eina_List *n;
1693
1694 EINA_LIST_FOREACH(swipe_bindings, n, binding)
1695 {
1696 if (binding->ctxt == ctxt &&
1697 EINA_DBL_EQ(fingers, binding->fingers) &&
1698 fmod(binding->direction - binding->error, 2*M_PI) < direction &&
1699 fmod(binding->direction + binding->error, 2*M_PI) > direction)
1700 {
1701 E_Binding_Swipe_Candidate cad = {binding->action, length / binding->length};
1702 eina_inarray_push(ret, &cad);
1703 }
1704 }
1705
1706 return ret;
1707}
1708
1709E_API void
1710e_bindings_swipe_live_update_hook_set(E_Bindings_Swipe_Live_Update update, void *data)
1711{
1712 live_update = update;
1713 live_update_data = data;
1714}
1715
1716E_API E_Bindings_Swipe_Live_Update
1717e_bindings_swipe_live_update_hook_get(void)
1718{
1719 return live_update;
1720}
1721
1722E_API void*
1723e_bindings_swipe_live_update_hook_data_get(void)
1724{
1725 return live_update_data;
1726}
diff --git a/src/bin/e_bindings.h b/src/bin/e_bindings.h
index 043118cbf..b65fabe38 100644
--- a/src/bin/e_bindings.h
+++ b/src/bin/e_bindings.h
@@ -35,6 +35,7 @@ typedef struct _E_Binding_Edge E_Binding_Edge;
35typedef struct _E_Binding_Signal E_Binding_Signal; 35typedef struct _E_Binding_Signal E_Binding_Signal;
36typedef struct _E_Binding_Wheel E_Binding_Wheel; 36typedef struct _E_Binding_Wheel E_Binding_Wheel;
37typedef struct _E_Binding_Acpi E_Binding_Acpi; 37typedef struct _E_Binding_Acpi E_Binding_Acpi;
38typedef struct _E_Binding_Swipe E_Binding_Swipe;
38 39
39typedef struct E_Binding_Event_Mouse_Button E_Binding_Event_Mouse_Button; 40typedef struct E_Binding_Event_Mouse_Button E_Binding_Event_Mouse_Button;
40typedef struct E_Binding_Event_Wheel E_Binding_Event_Wheel; 41typedef struct E_Binding_Event_Wheel E_Binding_Event_Wheel;
@@ -131,6 +132,15 @@ struct _E_Binding_Acpi
131 const char *action, *params; 132 const char *action, *params;
132}; 133};
133 134
135struct _E_Binding_Swipe
136{
137 E_Binding_Context ctxt;
138 double direction, length, error;
139 unsigned int fingers;
140 const char *action, *params;
141};
142
143
134EINTERN int e_bindings_init(void); 144EINTERN int e_bindings_init(void);
135EINTERN int e_bindings_shutdown(void); 145EINTERN int e_bindings_shutdown(void);
136 146
@@ -139,6 +149,7 @@ E_API void e_bindings_key_reset(void);
139E_API void e_bindings_wheel_reset(void); 149E_API void e_bindings_wheel_reset(void);
140E_API void e_bindings_edge_reset(void); 150E_API void e_bindings_edge_reset(void);
141E_API void e_bindings_signal_reset(void); 151E_API void e_bindings_signal_reset(void);
152E_API void e_bindings_swipe_reset(void);
142E_API void e_bindings_reset(void); 153E_API void e_bindings_reset(void);
143 154
144E_API void e_bindings_mouse_add(E_Binding_Context ctxt, int button, E_Binding_Modifier mod, int any_mod, const char *action, const char *params); 155E_API void e_bindings_mouse_add(E_Binding_Context ctxt, int button, E_Binding_Modifier mod, int any_mod, const char *action, const char *params);
@@ -196,6 +207,25 @@ E_API void e_bindings_acpi_del(E_Binding_Context ctxt, int type, int status, con
196E_API E_Action *e_bindings_acpi_find(E_Binding_Context ctxt, E_Event_Acpi *ev, E_Binding_Acpi **bind_ret); 207E_API E_Action *e_bindings_acpi_find(E_Binding_Context ctxt, E_Event_Acpi *ev, E_Binding_Acpi **bind_ret);
197E_API E_Action *e_bindings_acpi_event_handle(E_Binding_Context ctxt, E_Object *obj, E_Event_Acpi *ev); 208E_API E_Action *e_bindings_acpi_event_handle(E_Binding_Context ctxt, E_Object *obj, E_Event_Acpi *ev);
198 209
210typedef struct {
211 const char *name;
212 double acceptance; //0 to 1
213} E_Binding_Swipe_Candidate;
214
215typedef void (*E_Bindings_Swipe_Live_Update)(void *data, Eina_Bool end, double direction, double length, double error, unsigned int fingers);
216
217/**
218 * Direction is in radiens, 0 is pointing to the right. Going clockwise. (Only positive range)
219 */
220E_API Eina_Bool e_bindings_swipe_available(void);
221E_API void e_bindings_swipe_add(E_Binding_Context ctxt, double direction, double length, unsigned int fingers, double error, const char *action, const char *params);
222E_API void e_bindings_swipe_del(E_Binding_Context ctxt, double direction, double length, unsigned int fingers, double error, const char *action, const char *params);
223E_API E_Action* e_bindings_swipe_handle(E_Binding_Context ctxt, E_Object *obj, double direction, double length, unsigned int fingers);
224E_API Eina_Inarray/*<E_Bindings_Swipe_Candidate>*/* e_bindings_swipe_find_candidates(E_Binding_Context ctxt, double direction, double lenght, unsigned int fingers);
225E_API void e_bindings_swipe_live_update_hook_set(E_Bindings_Swipe_Live_Update update, void *data);
226E_API E_Bindings_Swipe_Live_Update e_bindings_swipe_live_update_hook_get(void);
227E_API void* e_bindings_swipe_live_update_hook_data_get(void);
228
199E_API int e_bindings_evas_modifiers_convert(Evas_Modifier *modifiers); 229E_API int e_bindings_evas_modifiers_convert(Evas_Modifier *modifiers);
200E_API int e_bindings_modifiers_to_ecore_convert(E_Binding_Modifier modifiers); 230E_API int e_bindings_modifiers_to_ecore_convert(E_Binding_Modifier modifiers);
201E_API void e_bindings_evas_event_mouse_button_convert(const Evas_Event_Mouse_Down *ev, E_Binding_Event_Mouse_Button *event); 231E_API void e_bindings_evas_event_mouse_button_convert(const Evas_Event_Mouse_Down *ev, E_Binding_Event_Mouse_Button *event);
diff --git a/src/bin/e_config.c b/src/bin/e_config.c
index 6c792d4f2..3e5d68f76 100644
--- a/src/bin/e_config.c
+++ b/src/bin/e_config.c
@@ -28,6 +28,7 @@ static E_Config_DD *_e_config_bindings_edge_edd = NULL;
28static E_Config_DD *_e_config_bindings_signal_edd = NULL; 28static E_Config_DD *_e_config_bindings_signal_edd = NULL;
29static E_Config_DD *_e_config_bindings_wheel_edd = NULL; 29static E_Config_DD *_e_config_bindings_wheel_edd = NULL;
30static E_Config_DD *_e_config_bindings_acpi_edd = NULL; 30static E_Config_DD *_e_config_bindings_acpi_edd = NULL;
31static E_Config_DD *_e_config_bindings_swipe_edd = NULL;
31static E_Config_DD *_e_config_path_append_edd = NULL; 32static E_Config_DD *_e_config_path_append_edd = NULL;
32static E_Config_DD *_e_config_desktop_bg_edd = NULL; 33static E_Config_DD *_e_config_desktop_bg_edd = NULL;
33static E_Config_DD *_e_config_desklock_bg_edd = NULL; 34static E_Config_DD *_e_config_desklock_bg_edd = NULL;
@@ -460,6 +461,7 @@ _e_config_edd_init(Eina_Bool old)
460 E_CONFIG_LIST(D, T, signal_bindings, _e_config_bindings_signal_edd); /**/ 461 E_CONFIG_LIST(D, T, signal_bindings, _e_config_bindings_signal_edd); /**/
461 E_CONFIG_LIST(D, T, wheel_bindings, _e_config_bindings_wheel_edd); /**/ 462 E_CONFIG_LIST(D, T, wheel_bindings, _e_config_bindings_wheel_edd); /**/
462 E_CONFIG_LIST(D, T, acpi_bindings, _e_config_bindings_acpi_edd); /**/ 463 E_CONFIG_LIST(D, T, acpi_bindings, _e_config_bindings_acpi_edd); /**/
464 E_CONFIG_LIST(D, T, swipe_bindings, _e_config_bindings_swipe_edd); /**/
463 E_CONFIG_LIST(D, T, path_append_data, _e_config_path_append_edd); /**/ 465 E_CONFIG_LIST(D, T, path_append_data, _e_config_path_append_edd); /**/
464 E_CONFIG_LIST(D, T, path_append_images, _e_config_path_append_edd); /**/ 466 E_CONFIG_LIST(D, T, path_append_images, _e_config_path_append_edd); /**/
465 E_CONFIG_LIST(D, T, path_append_fonts, _e_config_path_append_edd); /**/ 467 E_CONFIG_LIST(D, T, path_append_fonts, _e_config_path_append_edd); /**/
@@ -924,6 +926,21 @@ e_config_init(void)
924 E_CONFIG_VAL(D, T, action, STR); 926 E_CONFIG_VAL(D, T, action, STR);
925 E_CONFIG_VAL(D, T, params, STR); 927 E_CONFIG_VAL(D, T, params, STR);
926 928
929 _e_config_bindings_swipe_edd = E_CONFIG_DD_NEW("E_Config_Binding_Swipe",
930 E_Config_Binding_Swipe);
931#undef T
932#undef D
933#define T E_Config_Binding_Swipe
934#define D _e_config_bindings_swipe_edd
935
936 E_CONFIG_VAL(D, T, context, INT);
937 E_CONFIG_VAL(D, T, fingers, UINT);
938 E_CONFIG_VAL(D, T, direction, DOUBLE);
939 E_CONFIG_VAL(D, T, length, DOUBLE);
940 E_CONFIG_VAL(D, T, error, DOUBLE);
941 E_CONFIG_VAL(D, T, action, STR);
942 E_CONFIG_VAL(D, T, params, STR);
943
927 _e_config_edd_init(EINA_FALSE); 944 _e_config_edd_init(EINA_FALSE);
928 945
929 _e_config_binding_edd = E_CONFIG_DD_NEW("E_Config_Bindings", E_Config_Bindings); 946 _e_config_binding_edd = E_CONFIG_DD_NEW("E_Config_Bindings", E_Config_Bindings);
@@ -938,6 +955,7 @@ e_config_init(void)
938 E_CONFIG_LIST(D, T, signal_bindings, _e_config_bindings_signal_edd); /**/ 955 E_CONFIG_LIST(D, T, signal_bindings, _e_config_bindings_signal_edd); /**/
939 E_CONFIG_LIST(D, T, wheel_bindings, _e_config_bindings_wheel_edd); /**/ 956 E_CONFIG_LIST(D, T, wheel_bindings, _e_config_bindings_wheel_edd); /**/
940 E_CONFIG_LIST(D, T, acpi_bindings, _e_config_bindings_acpi_edd); /**/ 957 E_CONFIG_LIST(D, T, acpi_bindings, _e_config_bindings_acpi_edd); /**/
958 E_CONFIG_LIST(D, T, swipe_bindings, _e_config_bindings_swipe_edd); /**/
941 959
942 e_config_load(); 960 e_config_load();
943 961
@@ -2258,6 +2276,16 @@ e_config_mode_changed(void)
2258} 2276}
2259 2277
2260E_API void 2278E_API void
2279e_config_binding_swipe_free(E_Config_Binding_Swipe *eba)
2280{
2281 if (!eba) return;
2282 eina_stringshare_del(eba->action);
2283 eina_stringshare_del(eba->params);
2284 free(eba);
2285}
2286
2287
2288E_API void
2261e_config_binding_acpi_free(E_Config_Binding_Acpi *eba) 2289e_config_binding_acpi_free(E_Config_Binding_Acpi *eba)
2262{ 2290{
2263 if (!eba) return; 2291 if (!eba) return;
diff --git a/src/bin/e_config.h b/src/bin/e_config.h
index deae01d31..3b1c304ca 100644
--- a/src/bin/e_config.h
+++ b/src/bin/e_config.h
@@ -10,6 +10,7 @@ typedef struct _E_Config_Binding_Edge E_Config_Binding_Edge;
10typedef struct _E_Config_Binding_Signal E_Config_Binding_Signal; 10typedef struct _E_Config_Binding_Signal E_Config_Binding_Signal;
11typedef struct _E_Config_Binding_Wheel E_Config_Binding_Wheel; 11typedef struct _E_Config_Binding_Wheel E_Config_Binding_Wheel;
12typedef struct _E_Config_Binding_Acpi E_Config_Binding_Acpi; 12typedef struct _E_Config_Binding_Acpi E_Config_Binding_Acpi;
13typedef struct _E_Config_Binding_Swipe E_Config_Binding_Swipe;
13typedef struct _E_Config_Desktop_Background E_Config_Desktop_Background; 14typedef struct _E_Config_Desktop_Background E_Config_Desktop_Background;
14typedef struct _E_Config_Desklock_Background E_Config_Desklock_Background; 15typedef struct _E_Config_Desklock_Background E_Config_Desklock_Background;
15typedef struct _E_Config_Desktop_Name E_Config_Desktop_Name; 16typedef struct _E_Config_Desktop_Name E_Config_Desktop_Name;
@@ -87,6 +88,7 @@ struct _E_Config
87 Eina_List *signal_bindings; // GUI 88 Eina_List *signal_bindings; // GUI
88 Eina_List *wheel_bindings; // GUI 89 Eina_List *wheel_bindings; // GUI
89 Eina_List *acpi_bindings; // GUI 90 Eina_List *acpi_bindings; // GUI
91 Eina_List *swipe_bindings; // GUI
90 92
91 Eina_List *path_append_data; // GUI 93 Eina_List *path_append_data; // GUI
92 Eina_List *path_append_images; // GUI 94 Eina_List *path_append_images; // GUI
@@ -452,6 +454,7 @@ struct E_Config_Bindings
452 Eina_List *signal_bindings; // GUI 454 Eina_List *signal_bindings; // GUI
453 Eina_List *wheel_bindings; // GUI 455 Eina_List *wheel_bindings; // GUI
454 Eina_List *acpi_bindings; // GUI 456 Eina_List *acpi_bindings; // GUI
457 Eina_List *swipe_bindings;
455}; 458};
456 459
457struct _E_Config_Desklock_Background 460struct _E_Config_Desklock_Background
@@ -542,6 +545,14 @@ struct _E_Config_Binding_Acpi
542 const char *action, *params; 545 const char *action, *params;
543}; 546};
544 547
548struct _E_Config_Binding_Swipe
549{
550 int context;
551 unsigned int fingers;
552 double direction, length, error;
553 const char *action, *params;
554};
555
545struct _E_Config_Desktop_Background 556struct _E_Config_Desktop_Background
546{ 557{
547 int zone; 558 int zone;
@@ -675,6 +686,7 @@ E_API void e_config_binding_mouse_free(E_Config_Binding_Mouse *ebm);
675E_API void e_config_binding_edge_free(E_Config_Binding_Edge *ebe); 686E_API void e_config_binding_edge_free(E_Config_Binding_Edge *ebe);
676E_API void e_config_binding_key_free(E_Config_Binding_Key *ebk); 687E_API void e_config_binding_key_free(E_Config_Binding_Key *ebk);
677E_API void e_config_binding_acpi_free(E_Config_Binding_Acpi *eba); 688E_API void e_config_binding_acpi_free(E_Config_Binding_Acpi *eba);
689E_API void e_config_binding_swipe_free(E_Config_Binding_Swipe *eba);
678 690
679extern E_API E_Config *e_config; 691extern E_API E_Config *e_config;
680extern E_API E_Config_Bindings *e_bindings; 692extern E_API E_Config_Bindings *e_bindings;
diff --git a/src/modules/conf_bindings/e_int_config_swipebindings.c b/src/modules/conf_bindings/e_int_config_swipebindings.c
new file mode 100644
index 000000000..7c47aaa92
--- /dev/null
+++ b/src/modules/conf_bindings/e_int_config_swipebindings.c
@@ -0,0 +1,978 @@
1#include "e.h"
2
3#define TEXT_NO_PARAMS _("<None>")
4
5struct _E_Config_Dialog_Data
6{
7 Evas *evas;
8 struct
9 {
10 Eina_List *swipe;
11 } binding;
12 struct
13 {
14 const char *binding, *action;
15 char *params;
16 const char *cur;
17 int button;
18 int cur_act;
19 const char *swipe;
20 const char *source;
21
22 E_Dialog *dia;
23 double degree;
24 double error;
25 double length;
26 unsigned int fingers;
27 } locals;
28 struct
29 {
30 Evas_Object *o_add, *o_del, *o_del_all;
31 Evas_Object *o_binding_list, *o_action_list;
32 Evas_Object *o_params, *o_selector;
33 } gui;
34
35 const char *params;
36
37 int fullscreen_flip;
38 int multiscreen_flip;
39
40 E_Config_Dialog *cfd;
41};
42
43static E_Config_Binding_Swipe *
44_swipe_binding_copy(E_Config_Binding_Swipe *bi)
45{
46 E_Config_Binding_Swipe *bi2;
47 if (!bi) return NULL;
48
49 bi2 = E_NEW(E_Config_Binding_Swipe, 1);
50 bi2->context = bi->context;
51 bi2->direction = bi->direction;
52 bi2->length = bi->length;
53 bi2->fingers = bi->fingers;
54 bi2->error = bi->error;
55 bi2->action = bi->action;
56 bi2->params = bi->params;
57 return bi2;
58}
59
60static void
61_swipe_binding_free(E_Config_Binding_Swipe *bi)
62{
63 if (!bi) return;
64 eina_stringshare_del(bi->action);
65 eina_stringshare_del(bi->params);
66 free(bi);
67}
68
69
70static void
71_auto_apply_changes(E_Config_Dialog_Data *cfdata)
72{
73 int n, g, a, ok;
74 E_Config_Binding_Swipe *bi;
75 E_Action_Group *actg;
76 E_Action_Description *actd;
77
78 if ((!cfdata->locals.cur) || (!cfdata->locals.cur[0]) ||
79 (!cfdata->locals.action) || (!cfdata->locals.action[0])) return;
80
81 if (sscanf(cfdata->locals.cur, "s%d", &n) != 1)
82 return;
83 if (sscanf(cfdata->locals.action, "%d %d", &g, &a) != 2)
84 return;
85
86 bi = eina_list_nth(cfdata->binding.swipe, n);
87 if (!bi) return;
88
89 actg = eina_list_nth(e_action_groups_get(), g);
90 if (!actg) return;
91 actd = eina_list_nth(actg->acts, a);
92 if (!actd) return;
93
94 eina_stringshare_del(bi->action);
95 bi->action = NULL;
96
97 if (actd->act_cmd) bi->action = eina_stringshare_add(actd->act_cmd);
98
99 eina_stringshare_del(bi->params);
100 bi->params = NULL;
101
102 if (actd->act_params)
103 bi->params = eina_stringshare_add(actd->act_params);
104 else
105 {
106 ok = 1;
107 if (cfdata->locals.params)
108 {
109 if (!strcmp(cfdata->locals.params, TEXT_NO_PARAMS))
110 ok = 0;
111
112 if ((actd->param_example) && (!strcmp(cfdata->locals.params, actd->param_example)))
113 ok = 0;
114 }
115 else
116 ok = 0;
117
118 if (ok)
119 bi->params = eina_stringshare_add(cfdata->locals.params);
120 }
121}
122
123static void
124_fill_data(E_Config_Dialog_Data *cfdata)
125{
126 E_Config_Binding_Swipe *bi, *bi2;
127 Eina_List *l;
128
129 cfdata->locals.params = strdup("");
130 cfdata->locals.action = eina_stringshare_add("");
131 cfdata->locals.binding = eina_stringshare_add("");
132 cfdata->locals.swipe = eina_stringshare_add("");
133 cfdata->locals.source = eina_stringshare_add("");
134 cfdata->locals.cur = NULL;
135 cfdata->locals.dia = NULL;
136 cfdata->binding.swipe = NULL;
137
138 EINA_LIST_FOREACH(e_bindings->swipe_bindings, l, bi)
139 {
140 if (!bi) continue;
141 bi2 = _swipe_binding_copy(bi);
142 cfdata->binding.swipe = eina_list_append(cfdata->binding.swipe, bi2);
143 }
144}
145
146static void *
147_create_data(E_Config_Dialog *cfd)
148{
149 E_Config_Dialog_Data *cfdata;
150
151 cfdata = E_NEW(E_Config_Dialog_Data, 1);
152 cfdata->cfd = cfd;
153 _fill_data(cfdata);
154
155 return cfdata;
156}
157
158static void
159_free_data(E_Config_Dialog *cfd EINA_UNUSED, E_Config_Dialog_Data *cfdata)
160{
161 E_FREE_LIST(cfdata->binding.swipe, _swipe_binding_free);
162
163 eina_stringshare_del(cfdata->locals.cur);
164 eina_stringshare_del(cfdata->params);
165 eina_stringshare_del(cfdata->locals.binding);
166 eina_stringshare_del(cfdata->locals.action);
167 eina_stringshare_del(cfdata->locals.swipe);
168 eina_stringshare_del(cfdata->locals.source);
169
170 if (cfdata->locals.dia) e_object_del(E_OBJECT(cfdata->locals.dia));
171
172 free(cfdata->locals.params);
173 E_FREE(cfdata);
174}
175
176
177static void
178_update_action_params(E_Config_Dialog_Data *cfdata)
179{
180 int g, a, b;
181 E_Action_Group *actg;
182 E_Action_Description *actd;
183 E_Config_Binding_Swipe *bi;
184 const char *action, *params;
185
186#define SIGNAL_EXAMPLE_PARAMS \
187 if ((!actd->param_example) || (!actd->param_example[0])) \
188 e_widget_entry_text_set(cfdata->gui.o_params, TEXT_NO_PARAMS); \
189 else \
190 e_widget_entry_text_set(cfdata->gui.o_params, actd->param_example)
191
192 if ((!cfdata->locals.action) || (!cfdata->locals.action[0]))
193 {
194 e_widget_disabled_set(cfdata->gui.o_params, 1);
195 e_widget_entry_clear(cfdata->gui.o_params);
196 return;
197 }
198 if (sscanf(cfdata->locals.action, "%d %d", &g, &a) != 2)
199 return;
200
201 actg = eina_list_nth(e_action_groups_get(), g);
202 if (!actg) return;
203 actd = eina_list_nth(actg->acts, a);
204 if (!actd) return;
205
206 if (actd->act_params)
207 {
208 e_widget_disabled_set(cfdata->gui.o_params, 1);
209 e_widget_entry_text_set(cfdata->gui.o_params, actd->act_params);
210 return;
211 }
212
213 if ((!cfdata->locals.cur) || (!cfdata->locals.cur[0]))
214 {
215 e_widget_disabled_set(cfdata->gui.o_params, 1);
216 SIGNAL_EXAMPLE_PARAMS;
217 return;
218 }
219
220 if (!actd->editable)
221 e_widget_disabled_set(cfdata->gui.o_params, 1);
222 else
223 e_widget_disabled_set(cfdata->gui.o_params, 0);
224
225 if (cfdata->locals.cur[0] == 's')
226 {
227 if (sscanf(cfdata->locals.cur, "s%d", &b) != 1)
228 {
229 e_widget_disabled_set(cfdata->gui.o_params, 1);
230 SIGNAL_EXAMPLE_PARAMS;
231 return;
232 }
233
234 bi = eina_list_nth(cfdata->binding.swipe, b);
235 if (!bi)
236 {
237 e_widget_disabled_set(cfdata->gui.o_params, 1);
238 SIGNAL_EXAMPLE_PARAMS;
239 return;
240 }
241 action = bi->action;
242 params = bi->params;
243 }
244 else
245 {
246 e_widget_disabled_set(cfdata->gui.o_params, 1);
247 SIGNAL_EXAMPLE_PARAMS;
248 return;
249 }
250
251 if (action)
252 {
253 if (!strcmp(action, actd->act_cmd))
254 {
255 if ((!params) || (!params[0]))
256 SIGNAL_EXAMPLE_PARAMS;
257 else
258 e_widget_entry_text_set(cfdata->gui.o_params, params);
259 }
260 else
261 SIGNAL_EXAMPLE_PARAMS;
262 }
263 else
264 SIGNAL_EXAMPLE_PARAMS;
265}
266
267static void
268_action_change_cb(void *data)
269{
270 E_Config_Dialog_Data *cfdata;
271
272 cfdata = data;
273 _update_action_params(cfdata);
274}
275
276static int
277_swipe_binding_sort_cb(E_Config_Binding_Swipe *a, E_Config_Binding_Swipe *b)
278{
279 int finger_diff = (a->fingers == b->fingers)*-1;
280 if (!finger_diff)
281 {
282 return a->direction - b->direction;
283 }
284 return finger_diff;
285}
286
287static void
288_update_buttons(E_Config_Dialog_Data *cfdata)
289{
290 if (e_widget_ilist_count(cfdata->gui.o_binding_list))
291 e_widget_disabled_set(cfdata->gui.o_del_all, 0);
292 else
293 e_widget_disabled_set(cfdata->gui.o_del_all, 1);
294
295 if (!cfdata->locals.cur)
296 {
297 e_widget_disabled_set(cfdata->gui.o_del, 1);
298 return;
299 }
300 e_widget_disabled_set(cfdata->gui.o_del, 0);
301}
302
303
304static void
305_find_swipe_binding_action(const char *action, const char *params, int *g, int *a, int *n)
306{
307 Eina_List *l, *l2;
308 int gg = -1, aa = -1, nn = -1, found;
309 E_Action_Group *actg;
310 E_Action_Description *actd;
311
312 if (g) *g = -1;
313 if (a) *a = -1;
314 if (n) *n = -1;
315
316 found = 0;
317 for (l = e_action_groups_get(), gg = 0, nn = 0; l; l = l->next, gg++)
318 {
319 actg = l->data;
320
321 for (l2 = actg->acts, aa = 0; l2; l2 = l2->next, aa++)
322 {
323 actd = l2->data;
324 if (!strcmp((!action ? "" : action), (!actd->act_cmd ? "" : actd->act_cmd)))
325 {
326 if (!params || !params[0])
327 {
328 if ((!actd->act_params) || (!actd->act_params[0]))
329 {
330 if (g) *g = gg;
331 if (a) *a = aa;
332 if (n) *n = nn;
333 return;
334 }
335 else
336 continue;
337 }
338 else
339 {
340 if ((!actd->act_params) || (!actd->act_params[0]))
341 {
342 if (g) *g = gg;
343 if (a) *a = aa;
344 if (n) *n = nn;
345 found = 1;
346 }
347 else
348 {
349 if (!strcmp(params, actd->act_params))
350 {
351 if (g) *g = gg;
352 if (a) *a = aa;
353 if (n) *n = nn;
354 return;
355 }
356 }
357 }
358 }
359 nn++;
360 }
361 if (found) break;
362 }
363
364 if (!found)
365 {
366 if (g) *g = -1;
367 if (a) *a = -1;
368 if (n) *n = -1;
369 }
370}
371
372static void
373_update_action_list(E_Config_Dialog_Data *cfdata)
374{
375 E_Config_Binding_Swipe *bi;
376 int j = -1, i, n;
377 const char *action, *params;
378
379 if (!cfdata->locals.cur) return;
380
381 if (cfdata->locals.cur[0] == 's')
382 {
383 if (sscanf(cfdata->locals.cur, "s%d", &n) != 1)
384 return;
385
386 bi = eina_list_nth(cfdata->binding.swipe, n);
387 if (!bi)
388 {
389 e_widget_ilist_unselect(cfdata->gui.o_action_list);
390 e_widget_entry_clear(cfdata->gui.o_params);
391 e_widget_disabled_set(cfdata->gui.o_params, 1);
392 return;
393 }
394 action = bi->action;
395 params = bi->params;
396 }
397 else
398 return;
399
400 _find_swipe_binding_action(action, params, NULL, NULL, &j);
401
402 if (j >= 0)
403 {
404 for (i = 0; i < e_widget_ilist_count(cfdata->gui.o_action_list); i++)
405 {
406 if (i > j) break;
407 if (e_widget_ilist_nth_is_header(cfdata->gui.o_action_list, i)) j++;
408 }
409 }
410
411 if (j >= 0)
412 {
413 if (j == e_widget_ilist_selected_get(cfdata->gui.o_action_list))
414 _update_action_params(cfdata);
415 else
416 e_widget_ilist_selected_set(cfdata->gui.o_action_list, j);
417 }
418 else
419 {
420 e_widget_ilist_unselect(cfdata->gui.o_action_list);
421 eina_stringshare_del(cfdata->locals.action);
422 cfdata->locals.action = eina_stringshare_add("");
423 e_widget_entry_clear(cfdata->gui.o_params);
424 }
425}
426
427static void
428_binding_change_cb(void *data)
429{
430 E_Config_Dialog_Data *cfdata;
431
432 cfdata = data;
433
434 _auto_apply_changes(cfdata);
435 if (cfdata->locals.cur) eina_stringshare_del(cfdata->locals.cur);
436 cfdata->locals.cur = NULL;
437
438 if ((!cfdata->locals.binding) || (!cfdata->locals.binding[0])) return;
439
440 cfdata->locals.cur = eina_stringshare_ref(cfdata->locals.binding);
441
442 _update_buttons(cfdata);
443 _update_action_list(cfdata);
444}
445
446
447static int
448_basic_apply_data(E_Config_Dialog *cfd EINA_UNUSED, E_Config_Dialog_Data *cfdata)
449{
450 Eina_List *l;
451 E_Config_Binding_Swipe *bi, *bi2;
452
453 _auto_apply_changes(cfdata);
454 E_FREE_LIST(e_bindings->swipe_bindings, _swipe_binding_free);
455 EINA_LIST_FOREACH(cfdata->binding.swipe, l, bi2)
456 {
457 bi = _swipe_binding_copy(bi2);
458 e_bindings->swipe_bindings = eina_list_append(e_bindings->swipe_bindings, bi);
459 }
460 e_bindings_swipe_reset();
461
462 e_config_save_queue();
463
464 return 1;
465}
466
467static Evas_Object*
468create_visualisation(Evas *e, double direction, double error)
469{
470 Evas_Vg_Container *vg = NULL;
471 Evas_Vg_Shape *container, *shape, *viewport = NULL;
472
473 double center_x = 15, center_y = 15;
474
475 vg = evas_object_vg_add(e);
476 evas_object_vg_viewbox_set(vg, EINA_RECT(0, 0, 50, 50));
477
478 container = evas_vg_container_add(vg);
479
480 viewport = evas_vg_shape_add(container);
481 evas_vg_shape_append_rect(viewport, 0, 0, 51, 51, 0, 0);
482 evas_vg_shape_stroke_cap_set(viewport, EVAS_VG_CAP_SQUARE);
483 evas_vg_shape_stroke_color_set(viewport, 0, 0, 0, 0);
484 evas_vg_shape_stroke_width_set(viewport, 1);
485
486 shape = evas_vg_shape_add(container);
487 evas_vg_shape_append_rect(shape, 1, 1, 29, 29, 0, 0);
488 evas_vg_shape_stroke_cap_set(shape, EVAS_VG_CAP_SQUARE);
489 evas_vg_shape_stroke_color_set(shape, 100, 100, 100, 255);
490 evas_vg_shape_stroke_width_set(shape, 1);
491
492 shape = evas_vg_shape_add(container);
493 evas_vg_shape_append_line_to(shape, center_x, center_y);
494 evas_vg_shape_append_line_to(shape, center_x + cos(direction - error)*11, center_y + sin(direction - error)*11);
495 evas_vg_shape_append_arc_to(shape, center_x + cos(direction + error)*11, center_y + sin(direction + error)*11, 11, 11, 0, EINA_FALSE, EINA_TRUE);
496 evas_vg_shape_append_line_to(shape, center_x, center_y);
497
498 evas_vg_shape_stroke_cap_set(shape, EVAS_VG_CAP_ROUND);
499 evas_vg_shape_stroke_color_set(shape, 255, 0, 0, 255);
500 evas_vg_shape_stroke_width_set(shape, 2);
501
502 evas_object_vg_root_node_set(vg, container);
503
504 evas_object_show(vg);
505
506 return vg;
507}
508
509static void
510_update_swipe_binding_list(E_Config_Dialog_Data *cfdata)
511{
512 int i = 0;
513 char b2[64], b3[64];
514 Eina_List *l;
515 E_Config_Binding_Swipe *bi;
516 unsigned int previous_fingers = 0;
517
518 evas_event_freeze(evas_object_evas_get(cfdata->gui.o_binding_list));
519 edje_freeze();
520 e_widget_ilist_freeze(cfdata->gui.o_binding_list);
521
522 e_widget_ilist_clear(cfdata->gui.o_binding_list);
523 e_widget_ilist_go(cfdata->gui.o_binding_list);
524
525 if (cfdata->binding.swipe)
526 cfdata->binding.swipe = eina_list_sort(cfdata->binding.swipe, 0, (Eina_Compare_Cb)_swipe_binding_sort_cb);
527
528 EINA_LIST_FOREACH(cfdata->binding.swipe, l, bi)
529 {
530 Evas_Object *vis;
531
532 vis = create_visualisation(evas_object_evas_get(cfdata->gui.o_binding_list), bi->direction, bi->error);
533 if (bi->fingers != previous_fingers)
534 {
535 snprintf(b3, sizeof(b3), "%d Fingers", bi->fingers);
536 previous_fingers = bi->fingers;
537 e_widget_ilist_header_append(cfdata->gui.o_binding_list, NULL, b3);
538 }
539 snprintf(b2, sizeof(b2), "s%d", i);
540 snprintf(b3, sizeof(b3), "Length: %.2f Error: %.2f", bi->length, bi->error);
541
542 e_widget_ilist_append(cfdata->gui.o_binding_list, vis, b3, _binding_change_cb, cfdata, b2);
543 i++;
544 }
545 e_widget_ilist_go(cfdata->gui.o_binding_list);
546
547 e_widget_ilist_thaw(cfdata->gui.o_binding_list);
548 edje_thaw();
549 evas_event_thaw(evas_object_evas_get(cfdata->gui.o_binding_list));
550
551 if (eina_list_count(cfdata->binding.swipe))
552 e_widget_disabled_set(cfdata->gui.o_del_all, 0);
553 else
554 e_widget_disabled_set(cfdata->gui.o_del_all, 1);
555}
556
557static void
558_fill_actions_list(E_Config_Dialog_Data *cfdata)
559{
560 char buf[1024];
561 Eina_List *l, *l2;
562 E_Action_Group *actg;
563 E_Action_Description *actd;
564 int g, a;
565
566 evas_event_freeze(evas_object_evas_get(cfdata->gui.o_action_list));
567 edje_freeze();
568 e_widget_ilist_freeze(cfdata->gui.o_action_list);
569
570 e_widget_ilist_clear(cfdata->gui.o_action_list);
571 for (l = e_action_groups_get(), g = 0; l; l = l->next, g++)
572 {
573 actg = l->data;
574
575 if (!actg->acts) continue;
576
577 e_widget_ilist_header_append(cfdata->gui.o_action_list, NULL, _(actg->act_grp));
578
579 for (l2 = actg->acts, a = 0; l2; l2 = l2->next, a++)
580 {
581 actd = l2->data;
582
583 snprintf(buf, sizeof(buf), "%d %d", g, a);
584 e_widget_ilist_append(cfdata->gui.o_action_list, NULL, _(actd->act_name),
585 _action_change_cb, cfdata, buf);
586 }
587 }
588 e_widget_ilist_go(cfdata->gui.o_action_list);
589 e_widget_ilist_thaw(cfdata->gui.o_action_list);
590 edje_thaw();
591 evas_event_thaw(evas_object_evas_get(cfdata->gui.o_action_list));
592}
593
594static void
595_flush_binding_swipe(E_Config_Dialog_Data *cfdata)
596{
597 E_Config_Binding_Swipe *bi;
598
599 bi = E_NEW(E_Config_Binding_Swipe, 1);
600 bi->context = E_BINDING_CONTEXT_NONE;
601 bi->length = cfdata->locals.length;
602 bi->direction = cfdata->locals.degree;
603 bi->error = cfdata->locals.error;
604 bi->fingers = cfdata->locals.fingers;
605
606 cfdata->binding.swipe = eina_list_append(cfdata->binding.swipe, bi);
607 _update_swipe_binding_list(cfdata);
608}
609
610static void
611_swipe_add_cb_ok(void *data, E_Dialog *dia)
612{
613 E_Config_Dialog_Data *cfdata = data;
614
615 _flush_binding_swipe(cfdata);
616
617 e_object_del(E_OBJECT(dia));
618}
619
620static void
621_swipe_add_cb_cancel(void *data EINA_UNUSED, E_Dialog *dia)
622{
623 e_object_del(E_OBJECT(dia));
624}
625
626static void
627_swipe_add_del(void *data)
628{
629 E_Dialog *dia = data;
630 E_Config_Dialog_Data *cfdata;
631
632 if (!dia->data) return;
633 cfdata = dia->data;
634 cfdata->locals.dia = NULL;
635}
636
637static void
638_double_getter(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
639{
640 double *container = data;
641 double tmp = elm_spinner_value_get(obj);
642 *container = tmp;
643}
644
645static void
646_int_getter(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
647{
648 unsigned int *container = data;
649 double tmp = elm_spinner_value_get(obj);
650 *container = tmp;
651}
652
653static void
654_swipe_add_show(E_Config_Dialog_Data *cfdata)
655{
656 Evas_Object *o, *obg, *ol, *entry;
657 Evas *evas;
658 int w, h;
659
660 if (cfdata->locals.dia) return;
661
662 cfdata->locals.dia = e_dialog_new(cfdata->cfd->dia->win, "E", "_swipebind_new_dialog");
663 e_dialog_resizable_set(cfdata->locals.dia, 1);
664 e_dialog_title_set(cfdata->locals.dia, _("Add Swipe Binding"));
665 e_dialog_icon_set(cfdata->locals.dia, "enlightenment/swipes", 48);
666 e_dialog_button_add(cfdata->locals.dia, _("OK"), NULL, _swipe_add_cb_ok, cfdata);
667 e_dialog_button_add(cfdata->locals.dia, _("Cancel"), NULL, _swipe_add_cb_cancel, cfdata);
668 e_object_del_attach_func_set(E_OBJECT(cfdata->locals.dia), _swipe_add_del);
669 cfdata->locals.dia->data = cfdata;
670 elm_win_center(cfdata->locals.dia->win, 1, 1);
671
672 evas = evas_object_evas_get(cfdata->locals.dia->win);
673 obg = e_widget_list_add(evas, 1, 0);
674
675 ol = e_widget_framelist_add(evas, _("Direction:"), 0);
676 entry = o = elm_spinner_add(cfdata->locals.dia->win);
677 evas_object_smart_callback_add(o, "changed", _double_getter, &cfdata->locals.degree);
678 elm_spinner_min_max_set(o, 0, 2*M_PI);
679 elm_spinner_label_format_set(o, "%f");
680 elm_spinner_step_set(o, 0.1);
681 elm_spinner_editable_set(o, EINA_TRUE);
682 e_widget_framelist_object_append(ol, o);
683 e_widget_list_object_append(obg, ol, 1, 0, 0.5);
684
685 ol = e_widget_framelist_add(evas, _("Error:"), 0);
686 entry = o = elm_spinner_add(cfdata->locals.dia->win);
687 evas_object_smart_callback_add(o, "changed", _double_getter, &cfdata->locals.error);
688 elm_spinner_min_max_set(o, 0, 2*M_PI);
689 elm_spinner_label_format_set(o, "%f");
690 elm_spinner_step_set(o, 0.1);
691 elm_spinner_editable_set(o, EINA_TRUE);
692 e_widget_framelist_object_append(ol, o);
693 e_widget_list_object_append(obg, ol, 1, 0, 0.5);
694
695 ol = e_widget_framelist_add(evas, _("Length:"), 0);
696 entry = o = elm_spinner_add(cfdata->locals.dia->win);
697 evas_object_smart_callback_add(o, "changed", _double_getter, &cfdata->locals.length);
698 elm_spinner_min_max_set(o, 0, 200);
699 elm_spinner_step_set(o, 5);
700 elm_spinner_editable_set(o, EINA_TRUE);
701 e_widget_framelist_object_append(ol, o);
702 e_widget_list_object_append(obg, ol, 1, 0, 0.5);
703
704 cfdata->locals.fingers = 3;
705 ol = e_widget_framelist_add(evas, _("Fingers:"), 0);
706 entry = o = elm_spinner_add(cfdata->locals.dia->win);
707 evas_object_smart_callback_add(o, "changed", _int_getter, &cfdata->locals.fingers);
708 elm_spinner_min_max_set(o, 3, 10);
709 elm_spinner_value_set(o, 3.0);
710 elm_spinner_editable_set(o, EINA_TRUE);
711 e_widget_framelist_object_append(ol, o);
712 e_widget_list_object_append(obg, ol, 1, 0, 0.5);
713
714 e_widget_size_min_get(obg, &w, &h);
715 e_dialog_content_set(cfdata->locals.dia, obg, MAX(w, 200), MAX(h, 100));
716
717 e_dialog_show(cfdata->locals.dia);
718 e_widget_focus_set(entry, 1);
719}
720
721static void
722_add_swipe_binding_cb(void *data, void *data2 EINA_UNUSED)
723{
724 E_Config_Dialog_Data *cfdata = data;
725
726 _auto_apply_changes(cfdata);
727 _swipe_add_show(cfdata);
728}
729
730static void
731_update_swipe_cb(void *data, Eina_Bool end, double direction, double length, double error, unsigned int fingers)
732{
733 E_Config_Dialog_Data *cfdata = data;
734
735 if (end)
736 {
737 e_object_del(E_OBJECT(cfdata->locals.dia));
738 cfdata->locals.dia = NULL;
739 cfdata->locals.degree = direction;
740 cfdata->locals.length = length;
741 cfdata->locals.error = error;
742 cfdata->locals.fingers = fingers;
743 _flush_binding_swipe(cfdata);
744 e_bindings_swipe_live_update_hook_set(NULL, NULL);
745 }
746 else
747 {
748 char text_buf[1000];
749 Evas_Object *vis;
750
751 vis = create_visualisation(evas_object_evas_get(cfdata->locals.dia->win), direction, error);
752 evas_object_size_hint_align_set(vis, 0.0, 0.5);
753 snprintf(text_buf, sizeof(text_buf), "Using %d Fingers<br> <b>Direction</b> %f <b>Length</b> %f <b>Error</b> %f", fingers, direction, length, error);
754 e_dialog_text_set(cfdata->locals.dia, text_buf);
755 elm_object_part_content_set(cfdata->locals.dia->bg_object, "e.swallow.icon", vis);
756 evas_object_size_hint_min_set(vis, 30 * e_scale, 30 * e_scale);
757 elm_layout_signal_emit(cfdata->locals.dia->bg_object, "e,state,icon", "e");
758 elm_layout_signal_emit(cfdata->locals.dia->bg_object, "e,icon,enabled", "e");
759 }
760}
761
762static void
763_add_swipe_binding_by_sample_cb(void *data, void *data2 EINA_UNUSED)
764{
765 E_Config_Dialog_Data *cfdata = data;
766
767 cfdata->locals.dia = e_dialog_new(cfdata->cfd->dia->win, "E", "_swipe_recognition");
768 e_dialog_title_set(cfdata->locals.dia, "Swipe recognition");
769 e_dialog_text_set(cfdata->locals.dia, "Do your swipe gesture.<br>");
770 elm_win_center(cfdata->locals.dia->win, 1, 1);
771 elm_win_borderless_set(cfdata->locals.dia->win, 1);
772 e_dialog_resizable_set(cfdata->locals.dia, 0);
773 e_dialog_show(cfdata->locals.dia);
774 evas_object_layer_set(e_win_client_get(cfdata->locals.dia->win)->frame, E_LAYER_CLIENT_PRIO);
775
776 e_bindings_swipe_live_update_hook_set(_update_swipe_cb, data);
777}
778
779static void
780_delete_swipe_binding_cb(void *data, void *data2 EINA_UNUSED)
781{
782 Eina_List *l = NULL;
783 int sel, n;
784 E_Config_Dialog_Data *cfdata;
785
786 cfdata = data;
787
788 sel = e_widget_ilist_selected_get(cfdata->gui.o_binding_list);
789 if (cfdata->locals.binding[0] == 's')
790 {
791 if (sscanf(cfdata->locals.binding, "s%d", &n) != 1)
792 return;
793
794 l = eina_list_nth_list(cfdata->binding.swipe, n);
795
796 if (l)
797 {
798 _swipe_binding_free(eina_list_data_get(l));
799 cfdata->binding.swipe = eina_list_remove_list(cfdata->binding.swipe, l);
800 }
801 }
802
803 _update_swipe_binding_list(cfdata);
804
805 if (sel >= e_widget_ilist_count(cfdata->gui.o_binding_list))
806 sel = e_widget_ilist_count(cfdata->gui.o_binding_list) - 1;
807
808 eina_stringshare_del(cfdata->locals.cur);
809 cfdata->locals.cur = NULL;
810
811 e_widget_ilist_selected_set(cfdata->gui.o_binding_list, sel);
812 if (sel < 0)
813 {
814 e_widget_ilist_unselect(cfdata->gui.o_action_list);
815 e_widget_entry_clear(cfdata->gui.o_params);
816 e_widget_disabled_set(cfdata->gui.o_params, 1);
817 _update_buttons(cfdata);
818 }
819}
820
821
822static void
823_delete_all_swipe_binding_cb(void *data, void *data2 EINA_UNUSED)
824{
825 E_Config_Binding_Swipe *bi;
826 E_Config_Dialog_Data *cfdata;
827
828 cfdata = data;
829
830 EINA_LIST_FREE(cfdata->binding.swipe, bi)
831 _swipe_binding_free(bi);
832
833 eina_stringshare_del(cfdata->locals.cur);
834 cfdata->locals.cur = NULL;
835
836 e_widget_ilist_clear(cfdata->gui.o_binding_list);
837 e_widget_ilist_go(cfdata->gui.o_binding_list);
838 e_widget_ilist_unselect(cfdata->gui.o_action_list);
839 e_widget_entry_clear(cfdata->gui.o_params);
840 e_widget_disabled_set(cfdata->gui.o_params, 1);
841
842 _update_buttons(cfdata);
843}
844
845
846static void
847_restore_swipe_binding_defaults_cb(void *data, void *data2 EINA_UNUSED)
848{
849 E_Config_Bindings *ecb;
850 Eina_Stringshare *prof;
851 E_Config_Dialog_Data *cfdata = data;
852
853 ecb = e_config_domain_system_load("e_bindings", e_config_descriptor_find("E_Config_Bindings"));
854 if (!ecb)
855 {
856 const char *type;
857
858 prof = eina_stringshare_ref(e_config_profile_get());
859 switch (e_config->config_type)
860 {
861 case E_CONFIG_PROFILE_TYPE_DESKTOP:
862 type = "standard";
863 break;
864 case E_CONFIG_PROFILE_TYPE_MOBILE:
865 type = "mobile";
866 break;
867 //case E_CONFIG_PROFILE_TYPE_TABLET: FIXME - not used
868 default:
869 type = "default";
870 break;
871 }
872 e_config_profile_set(type);
873 ecb = e_config_domain_system_load("e_bindings", e_config_descriptor_find("E_Config_Bindings"));
874 e_config_profile_set(prof);
875 eina_stringshare_del(prof);
876 }
877 if (!ecb) return;
878 E_FREE_LIST(cfdata->binding.swipe, e_config_binding_swipe_free);
879 cfdata->binding.swipe = ecb->swipe_bindings, ecb->swipe_bindings = NULL;
880 e_config_bindings_free(ecb);
881
882 eina_stringshare_del(cfdata->locals.cur);
883 cfdata->locals.cur = NULL;
884
885 _update_swipe_binding_list(cfdata);
886 _update_buttons(cfdata);
887
888 e_widget_ilist_unselect(cfdata->gui.o_action_list);
889 e_widget_entry_clear(cfdata->gui.o_params);
890 e_widget_disabled_set(cfdata->gui.o_params, 1);
891}
892
893static Evas_Object *
894_basic_create_widgets(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata)
895{
896 Evas_Object *o, *ol, *ot, *of, *ob;
897
898 cfdata->evas = evas;
899 o = e_widget_list_add(evas, 0, 0);
900 ol = e_widget_list_add(evas, 0, 1);
901
902 of = e_widget_frametable_add(evas, _("Swipe Bindings"), 0);
903 ob = e_widget_ilist_add(evas, 32, 32, &(cfdata->locals.binding));
904 cfdata->gui.o_binding_list = ob;
905 e_widget_size_min_set(ob, 200, 160);
906 e_widget_frametable_object_append(of, ob, 0, 0, 2, 1, 1, 1, 1, 1);
907
908 ob = e_widget_button_add(evas, _("Add"), "list-add", _add_swipe_binding_by_sample_cb, cfdata, NULL);
909 e_widget_frametable_object_append(of, ob, 0, 1, 1, 1, 1, 0, 1, 0);
910
911 ob = e_widget_button_add(evas, _("Add by props"), "list-add", _add_swipe_binding_cb, cfdata, NULL);
912 cfdata->gui.o_add = ob;
913 e_widget_frametable_object_append(of, ob, 0, 2, 1, 1, 1, 0, 1, 0);
914
915 ob = e_widget_button_add(evas, _("Delete"), "list-remove", _delete_swipe_binding_cb, cfdata, NULL);
916 cfdata->gui.o_del = ob;
917 e_widget_disabled_set(ob, 1);
918 e_widget_frametable_object_append(of, ob, 1, 1, 1, 1, 1, 0, 1, 0);
919 ob = e_widget_button_add(evas, _("Delete All"), "edit-clear", _delete_all_swipe_binding_cb, cfdata, NULL);
920 cfdata->gui.o_del_all = ob;
921 e_widget_disabled_set(ob, 1);
922 e_widget_frametable_object_append(of, ob, 1, 2, 1, 1, 1, 0, 1, 0);
923 ob = e_widget_button_add(evas, _("Restore Default Bindings"), "enlightenment", _restore_swipe_binding_defaults_cb, cfdata, NULL);
924 e_widget_frametable_object_append(of, ob, 0, 3, 2, 1, 1, 0, 1, 0);
925 e_widget_list_object_append(ol, of, 1, 1, 0.5);
926
927 ot = e_widget_table_add(e_win_evas_win_get(evas), 0);
928 of = e_widget_framelist_add(evas, _("Action"), 0);
929 ob = e_widget_ilist_add(evas, 24, 24, &(cfdata->locals.action));
930 cfdata->gui.o_action_list = ob;
931 e_widget_size_min_set(ob, 200, 240);
932 e_widget_framelist_object_append(of, ob);
933 e_widget_table_object_append(ot, of, 0, 0, 1, 1, 1, 1, 1, 1);
934
935 of = e_widget_framelist_add(evas, _("Action Params"), 0);
936 ob = e_widget_entry_add(cfd->dia->win, &(cfdata->locals.params), NULL, NULL, NULL);
937 cfdata->gui.o_params = ob;
938 e_widget_disabled_set(ob, 1);
939 e_widget_framelist_object_append(of, ob);
940 e_widget_table_object_append(ot, of, 0, 3, 1, 1, 1, 1, 1, 0);
941 e_widget_list_object_append(ol, ot, 1, 1, 0.5);
942
943 e_widget_list_object_append(o, ol, 1, 1, 0.5);
944
945 _update_swipe_binding_list(cfdata);
946 _fill_actions_list(cfdata);
947
948 e_dialog_resizable_set(cfd->dia, 1);
949 return o;
950}
951
952
953E_Config_Dialog *
954e_int_config_swipebindings(Evas_Object *parent EINA_UNUSED, const char *params)
955{
956 E_Config_Dialog *cfd;
957 E_Config_Dialog_View *v;
958
959 if (e_config_dialog_find("E", "keyboard_and_mouse/swipe_bindings")) return NULL;
960 v = E_NEW(E_Config_Dialog_View, 1);
961
962 v->create_cfdata = _create_data;
963 v->free_cfdata = _free_data;
964 v->basic.apply_cfdata = _basic_apply_data;
965 v->basic.create_widgets = _basic_create_widgets;
966 v->override_auto_apply = 1;
967
968 cfd = e_config_dialog_new(NULL, _("Swipe Bindings Settings"), "E",
969 "keyboard_and_mouse/swipe_bindings",
970 "enlightenment/swipes", 0, v, NULL);
971 if ((params) && (params[0]))
972 {
973 cfd->cfdata->params = eina_stringshare_add(params);
974// _add_swipe_binding_cb(cfd->cfdata, NULL);
975 }
976
977 return cfd;
978}
diff --git a/src/modules/conf_bindings/e_mod_main.c b/src/modules/conf_bindings/e_mod_main.c
index 97f0a46b7..8800faed8 100644
--- a/src/modules/conf_bindings/e_mod_main.c
+++ b/src/modules/conf_bindings/e_mod_main.c
@@ -33,6 +33,10 @@ e_modapi_init(E_Module *m)
33 _("Edge Bindings"), NULL, 33 _("Edge Bindings"), NULL,
34 "preferences-desktop-edge-bindings", 34 "preferences-desktop-edge-bindings",
35 e_int_config_edgebindings); 35 e_int_config_edgebindings);
36 e_configure_registry_item_add("keyboard_and_mouse/swipe_bindings", 10,
37 _("Swipe Bindings"), NULL,
38 "preferences-desktop-swipe-bindings",
39 e_int_config_swipebindings);
36 40
37 e_configure_registry_category_add("advanced", 80, _("Advanced"), NULL, "preferences-advanced"); 41 e_configure_registry_category_add("advanced", 80, _("Advanced"), NULL, "preferences-advanced");
38 e_configure_registry_item_add("advanced/signal_bindings", 10, 42 e_configure_registry_item_add("advanced/signal_bindings", 10,
diff --git a/src/modules/conf_bindings/e_mod_main.h b/src/modules/conf_bindings/e_mod_main.h
index d33fab98d..cc99913a3 100644
--- a/src/modules/conf_bindings/e_mod_main.h
+++ b/src/modules/conf_bindings/e_mod_main.h
@@ -6,7 +6,7 @@ E_Config_Dialog *e_int_config_keybindings(Evas_Object *parent, const char *param
6E_Config_Dialog *e_int_config_mousebindings(Evas_Object *parent, const char *params EINA_UNUSED); 6E_Config_Dialog *e_int_config_mousebindings(Evas_Object *parent, const char *params EINA_UNUSED);
7E_Config_Dialog *e_int_config_edgebindings(Evas_Object *parent, const char *params EINA_UNUSED); 7E_Config_Dialog *e_int_config_edgebindings(Evas_Object *parent, const char *params EINA_UNUSED);
8E_Config_Dialog *e_int_config_signalbindings(Evas_Object *parent, const char *params); 8E_Config_Dialog *e_int_config_signalbindings(Evas_Object *parent, const char *params);
9 9E_Config_Dialog *e_int_config_swipebindings(Evas_Object *parent EINA_UNUSED, const char *params);
10/** 10/**
11 * @addtogroup Optional_Conf 11 * @addtogroup Optional_Conf
12 * @{ 12 * @{
diff --git a/src/modules/conf_bindings/meson.build b/src/modules/conf_bindings/meson.build
index aec7492fd..ee1adad55 100644
--- a/src/modules/conf_bindings/meson.build
+++ b/src/modules/conf_bindings/meson.build
@@ -5,6 +5,7 @@ src = files(
5 'e_int_config_keybindings.c', 5 'e_int_config_keybindings.c',
6 'e_int_config_mousebindings.c', 6 'e_int_config_mousebindings.c',
7 'e_int_config_signalbindings.c', 7 'e_int_config_signalbindings.c',
8 'e_int_config_swipebindings.c',
8 'e_mod_main.h' 9 'e_mod_main.h'
9) 10)
10 11
diff --git a/src/modules/gesture_recognition/e_mod_main.c b/src/modules/gesture_recognition/e_mod_main.c
new file mode 100644
index 000000000..2ebbebecc
--- /dev/null
+++ b/src/modules/gesture_recognition/e_mod_main.c
@@ -0,0 +1,287 @@
1#include <e.h>
2#include <Eina.h>
3#include <libinput.h>
4#include <grp.h>
5#include <sys/types.h>
6#include <pwd.h>
7
8E_API E_Module_Api e_modapi =
9 {
10 E_MODULE_API_VERSION,
11 "Gesture Recognition"
12 };
13
14static struct libinput *gesture_recognition_ctx;
15static Ecore_Fd_Handler *fd_listener;
16
17static int open_restricted(const char *path, int flags, void *user_data EINA_UNUSED)
18{
19 int fd = open(path, flags);
20 return fd < 0 ? -errno : fd;
21}
22
23static void close_restricted(int fd, void *user_data EINA_UNUSED)
24{
25 close(fd);
26}
27
28static const struct libinput_interface interface = {
29 .open_restricted = open_restricted,
30 .close_restricted = close_restricted,
31};
32
33static void
34_find_all_touch_input_devices(const char *path, struct libinput *li)
35{
36 Eina_File_Direct_Info *info;
37 Eina_Iterator *input_devies = eina_file_direct_ls(path);
38
39 EINA_ITERATOR_FOREACH(input_devies, info)
40 {
41 struct libinput_device *dev = libinput_path_add_device(li, info->path);
42
43 if (!dev) continue;
44
45 if (!libinput_device_has_capability(dev, LIBINPUT_DEVICE_CAP_GESTURE))
46 {
47 libinput_path_remove_device(dev);
48 }
49 }
50}
51
52static Eina_Hash *active_gestures;
53
54typedef struct {
55 Eina_Vector2 pos;
56 unsigned int fingers;
57 struct {
58 Evas_Object *visuals, *win;
59 } visuals;
60} Swipe_Stats;
61
62
63static Swipe_Stats*
64_find_swipe_gesture_recognizition(struct libinput_device *dev)
65{
66 Swipe_Stats *stats = eina_hash_find(active_gestures, dev);
67
68 return stats;
69}
70
71static Swipe_Stats*
72_start_swipe_gesture_recognizition(struct libinput_device *dev)
73{
74 Swipe_Stats *stats = _find_swipe_gesture_recognizition(dev);
75
76 if (stats)
77 eina_hash_del_by_key(active_gestures, dev);
78
79 stats = calloc(1, sizeof(Swipe_Stats));
80 EINA_SAFETY_ON_NULL_RETURN_VAL(stats, NULL);
81
82 if (e_bindings_swipe_available())
83 {
84 stats->visuals.win = elm_notify_add(e_comp->elm);
85 elm_notify_align_set(stats->visuals.win, 0.5, 0.5);
86 elm_object_tree_focus_allow_set(stats->visuals.win, EINA_FALSE);
87 evas_object_layer_set(stats->visuals.win, E_LAYER_CLIENT_PRIO);
88 evas_object_show(stats->visuals.win);
89
90 stats->visuals.visuals = elm_progressbar_add(stats->visuals.win);
91 elm_object_text_set(stats->visuals.visuals, "Progress of visuals");
92 evas_object_size_hint_min_set(stats->visuals.visuals, 300, 50);
93 evas_object_show(stats->visuals.visuals);
94 elm_object_content_set(stats->visuals.win, stats->visuals.visuals);
95 }
96
97
98 eina_hash_add(active_gestures, dev, stats);
99
100 return stats;
101}
102
103static void
104_end_swipe_gesture_recognizition(struct libinput_device *dev)
105{
106 eina_hash_del_by_key(active_gestures, dev);
107}
108
109static double
110_config_angle(Eina_Vector2 pos)
111{
112 double res = atan(pos.y/pos.x);
113
114 if (res < 0) res += M_PI;
115 if (pos.y < 0) res += M_PI;
116 return res;
117}
118
119static Eina_Bool
120_cb_input_dispatch(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED)
121{
122 struct libinput *li = data;
123 struct libinput_event *event;
124
125 if (libinput_dispatch(li) != 0)
126 printf("Failed to dispatch libinput events");
127
128 while((event = libinput_get_event(li)))
129 {
130 E_Bindings_Swipe_Live_Update live_update = e_bindings_swipe_live_update_hook_get();
131
132 enum libinput_event_type type = libinput_event_get_type(event);
133 struct libinput_device *dev = libinput_event_get_device(event);
134 if (type == LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN)
135 {
136 struct libinput_event_gesture *gesture = libinput_event_get_gesture_event(event);
137
138 Swipe_Stats *stats = _start_swipe_gesture_recognizition(dev);
139 stats->fingers = libinput_event_gesture_get_finger_count(gesture);
140 stats->pos.x = stats->pos.y = 0;
141 }
142 else if (type == LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE)
143 {
144 struct libinput_event_gesture *gesture = libinput_event_get_gesture_event(event);
145 Swipe_Stats *stats = _find_swipe_gesture_recognizition(dev);
146
147 stats->pos.x += libinput_event_gesture_get_dx(gesture);
148 stats->pos.y += libinput_event_gesture_get_dy(gesture);
149 if (live_update)
150 {
151 live_update(e_bindings_swipe_live_update_hook_data_get(), EINA_FALSE, _config_angle(stats->pos), eina_vector2_length_get(&stats->pos), 0.8, stats->fingers);
152 }
153 else if (stats->visuals.win)
154 {
155 Eina_Inarray *res = e_bindings_swipe_find_candidates(E_BINDING_CONTEXT_NONE, _config_angle (stats->pos), eina_vector2_length_get(&stats->pos), stats->fingers);
156 E_Binding_Swipe_Candidate *itr;
157 double total = 0.0f;
158 unsigned int len = 0;
159
160 EINA_INARRAY_FOREACH(res, itr)
161 {
162 total += itr->acceptance;
163 len ++;
164 }
165
166 if (len > 0)
167 {
168 char text_buffer[1000];
169
170 snprintf(text_buffer, sizeof(text_buffer), "%d gestures possible", len);
171 elm_progressbar_value_set(stats->visuals.visuals, total/len);
172 elm_object_text_set(stats->visuals.visuals, text_buffer);
173 }
174 else
175 {
176 elm_progressbar_value_set(stats->visuals.visuals, 0.0f);
177 elm_object_text_set(stats->visuals.visuals, "No gesture found");
178 }
179
180 eina_inarray_free(res);
181 }
182 }
183 else if (type == LIBINPUT_EVENT_GESTURE_SWIPE_END)
184 {
185 Swipe_Stats *stats = _find_swipe_gesture_recognizition(dev);
186
187 if (live_update)
188 live_update(e_bindings_swipe_live_update_hook_data_get(), EINA_TRUE, _config_angle(stats->pos), eina_vector2_length_get(&stats->pos), 0.8, stats->fingers);
189 else
190 e_bindings_swipe_handle(E_BINDING_CONTEXT_NONE, NULL, _config_angle(stats->pos), eina_vector2_length_get(&stats->pos), stats->fingers);
191
192 _end_swipe_gesture_recognizition(dev);
193 }
194 libinput_event_destroy(event);
195 }
196 return EINA_TRUE;
197}
198
199static void
200_setup_libinput(void)
201{
202 gesture_recognition_ctx = libinput_path_create_context(&interface, NULL);
203
204 _find_all_touch_input_devices("/dev/input/", gesture_recognition_ctx);
205
206 fd_listener = ecore_main_fd_handler_add(libinput_get_fd(gesture_recognition_ctx), ECORE_FD_READ, _cb_input_dispatch, gesture_recognition_ctx, NULL, NULL);
207}
208
209
210static void
211_tear_down_libinput(void)
212{
213 ecore_main_fd_handler_del(fd_listener);
214 libinput_unref(gesture_recognition_ctx);
215}
216
217static Eina_Bool
218_user_part_of_input(void)
219{
220 uid_t user = getuid();
221 struct passwd *user_pw = getpwuid(user);
222 gid_t *gids = NULL;
223 int number_of_groups = 0;
224 struct group *input_group = getgrnam("input");
225
226 EINA_SAFETY_ON_NULL_RETURN_VAL(user_pw, EINA_FALSE);
227 EINA_SAFETY_ON_NULL_RETURN_VAL(input_group, EINA_FALSE);
228
229 if (getgrouplist(user_pw->pw_name, getgid(), NULL, &number_of_groups) != -1)
230 {
231 ERR("Failed to enumerate groups of user");
232 return EINA_FALSE;
233 }
234 number_of_groups ++;
235 gids = alloca((number_of_groups) * sizeof(gid_t));
236 if (getgrouplist(user_pw->pw_name, getgid(), gids, &number_of_groups) == -1)
237 {
238 ERR("Failed to get groups of user");
239 return EINA_FALSE;
240 }
241
242 for (int i = 0; i < number_of_groups; ++i)
243 {
244 if (gids[i] == input_group->gr_gid)
245 return EINA_TRUE;
246 }
247 return EINA_FALSE;
248}
249
250static void
251_stats_free(void *ptr)
252{
253 Swipe_Stats *stats = ptr;
254
255 evas_object_del(stats->visuals.win);
256 free(stats);
257}
258
259E_API int
260e_modapi_init(E_Module *m EINA_UNUSED)
261{
262 if (!_user_part_of_input())
263 {
264 e_module_dialog_show(m, "Gesture Recognition", "Your user is not part of the input group, libinput cannot be used.");
265
266 return 0;
267 }
268 active_gestures = eina_hash_pointer_new(_stats_free);
269 _setup_libinput();
270
271 return 1;
272}
273
274E_API int
275e_modapi_shutdown(E_Module *m EINA_UNUSED)
276{
277 _tear_down_libinput();
278 return 1;
279}
280
281E_API int
282e_modapi_save(E_Module *m EINA_UNUSED)
283{
284
285 return 1;
286}
287
diff --git a/src/modules/gesture_recognition/meson.build b/src/modules/gesture_recognition/meson.build
new file mode 100644
index 000000000..5a007ee8e
--- /dev/null
+++ b/src/modules/gesture_recognition/meson.build
@@ -0,0 +1,5 @@
1src = files(
2 'e_mod_main.c',
3)
4deps += [dependency('libinput')]
5desktop_only = true
diff --git a/src/modules/gesture_recognition/module.desktop b/src/modules/gesture_recognition/module.desktop
new file mode 100644
index 000000000..8136450cb
--- /dev/null
+++ b/src/modules/gesture_recognition/module.desktop
@@ -0,0 +1,6 @@
1[Desktop Entry]
2Type=Link
3Name=Gesture Recognition
4Comment=Gesture recognition using libinput
5Icon=e-module-start
6X-Enlightenment-ModuleType=utils
diff --git a/src/modules/meson.build b/src/modules/meson.build
index 21a8f1a23..735cd0e77 100644
--- a/src/modules/meson.build
+++ b/src/modules/meson.build
@@ -45,6 +45,7 @@ mods = [
45 'tiling', 45 'tiling',
46 'packagekit', 46 'packagekit',
47 'vkbd', 47 'vkbd',
48 'gesture_recognition',
48# modules have a custom binary as well 49# modules have a custom binary as well
49 'battery', 50 'battery',
50 'cpufreq', 51 'cpufreq',