Compare commits

...

1 Commits

Author SHA1 Message Date
Marcel Hollerbach 304afe7ea3 Introduce gesture recognition 2 years ago
  1. 4
      meson_options.txt
  2. 141
      src/bin/e_bindings.c
  3. 30
      src/bin/e_bindings.h
  4. 28
      src/bin/e_config.c
  5. 12
      src/bin/e_config.h
  6. 978
      src/modules/conf_bindings/e_int_config_swipebindings.c
  7. 4
      src/modules/conf_bindings/e_mod_main.c
  8. 2
      src/modules/conf_bindings/e_mod_main.h
  9. 1
      src/modules/conf_bindings/meson.build
  10. 287
      src/modules/gesture_recognition/e_mod_main.c
  11. 5
      src/modules/gesture_recognition/meson.build
  12. 6
      src/modules/gesture_recognition/module.desktop
  13. 1
      src/modules/meson.build

@ -297,3 +297,7 @@ option('conf-window-remembers',
type: 'boolean',
value: true,
description: 'enable conf-window-remembers module: (default=true)')
option('gesture-recognition',
type: 'boolean',
value: true,
description: 'Enable gesture recognition using libinput, needed to get swipe bindings beeing detected.')

@ -7,6 +7,7 @@ static void _e_bindings_edge_free(E_Binding_Edge *bind);
static void _e_bindings_signal_free(E_Binding_Signal *bind);
static void _e_bindings_wheel_free(E_Binding_Wheel *bind);
static void _e_bindings_acpi_free(E_Binding_Acpi *bind);
static void _e_bindings_swipe_free(E_Binding_Swipe *bind);
static Eina_Bool _e_bindings_edge_cb_timer(void *data);
/* local subsystem globals */
@ -17,9 +18,13 @@ static Eina_List *edge_bindings = NULL;
static Eina_List *signal_bindings = NULL;
static Eina_List *wheel_bindings = NULL;
static Eina_List *acpi_bindings = NULL;
static Eina_List *swipe_bindings = NULL;
static unsigned int bindings_disabled = 0;
static E_Bindings_Swipe_Live_Update live_update;
static E_Bindings_Swipe_Live_Update live_update_data;
EINTERN E_Action *(*e_binding_key_list_cb)(E_Binding_Context, Ecore_Event_Key*, E_Binding_Modifier, E_Binding_Key **);
typedef struct _E_Binding_Edge_Data E_Binding_Edge_Data;
@ -43,6 +48,7 @@ e_bindings_init(void)
E_Config_Binding_Edge *ebe;
E_Config_Binding_Key *ebk;
E_Config_Binding_Acpi *eba;
E_Config_Binding_Acpi *ebsw;
Eina_List *l;
EINA_LIST_FOREACH(e_bindings->mouse_bindings, l, ebm)
@ -86,6 +92,8 @@ e_bindings_init(void)
e_bindings_acpi_add(eba->context, eba->type, eba->status,
eba->action, eba->params);
e_bindings_swipe_reset();
return 1;
}
@ -98,6 +106,7 @@ e_bindings_shutdown(void)
E_FREE_LIST(signal_bindings, _e_bindings_signal_free);
E_FREE_LIST(wheel_bindings, _e_bindings_wheel_free);
E_FREE_LIST(acpi_bindings, _e_bindings_acpi_free);
E_FREE_LIST(swipe_bindings, _e_bindings_swipe_free);
return 1;
}
@ -324,6 +333,18 @@ e_bindings_key_reset(void)
e_comp_canvas_keys_grab();
}
E_API void
e_bindings_swipe_reset(void)
{
E_Config_Binding_Swipe *eswipe;
Eina_List *l;
E_FREE_LIST(swipe_bindings, _e_bindings_swipe_free);
EINA_LIST_FOREACH(e_bindings->swipe_bindings, l, eswipe)
e_bindings_swipe_add(eswipe->context, eswipe->direction, eswipe->length, eswipe->fingers, eswipe->error, eswipe->action, eswipe->params);
}
E_API void
e_bindings_reset(void)
{
@ -332,6 +353,7 @@ e_bindings_reset(void)
e_bindings_wheel_reset();
e_bindings_edge_reset();
e_bindings_key_reset();
e_bindings_swipe_reset();
}
E_API void
@ -1514,6 +1536,14 @@ _e_bindings_acpi_free(E_Binding_Acpi *binding)
E_FREE(binding);
}
static void
_e_bindings_swipe_free(E_Binding_Swipe *binding)
{
if (binding->action) eina_stringshare_del(binding->action);
if (binding->params) eina_stringshare_del(binding->params);
E_FREE(binding);
}
E_API int
e_bindings_context_match(E_Binding_Context bctxt, E_Binding_Context ctxt)
{
@ -1583,3 +1613,114 @@ _e_bindings_edge_cb_timer(void *data)
return ECORE_CALLBACK_CANCEL;
}
E_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)
{
E_Binding_Swipe *binding = E_NEW(E_Binding_Swipe, 1);
binding->ctxt = ctxt;
binding->direction = direction;
binding->length = length;
binding->fingers = fingers;
binding->error = error;
if (action)
binding->action = eina_stringshare_add(action);
if (params)
binding->params = eina_stringshare_add(params);
swipe_bindings = eina_list_append(swipe_bindings, binding);
}
E_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)
{
E_Binding_Swipe *binding;
Eina_List *n;
EINA_LIST_FOREACH(swipe_bindings, n, binding)
{
if (binding->ctxt == ctxt &&
binding->action == action &&
binding->params == params &&
EINA_DBL_EQ(direction, binding->direction) &&
EINA_DBL_EQ(length, binding->length) &&
EINA_DBL_EQ(fingers, binding->fingers) &&
EINA_DBL_EQ(error, binding->error))
{
_e_bindings_swipe_free(binding);
swipe_bindings = eina_list_remove_list(swipe_bindings, n);
break;
}
}
}
E_API Eina_Bool
e_bindings_swipe_available(void)
{
return eina_list_count(swipe_bindings) > 0;
}
E_API E_Action*
e_bindings_swipe_handle(E_Binding_Context ctxt, E_Object *obj, double direction, double length, unsigned int fingers)
{
E_Binding_Swipe *binding;
Eina_List *n;
E_Action *act = NULL;
EINA_LIST_FOREACH(swipe_bindings, n, binding)
{
if (binding->ctxt == ctxt &&
binding->length < length &&
EINA_DBL_EQ(fingers, binding->fingers) &&
fmod(binding->direction - binding->error, 2*M_PI) < direction &&
fmod(binding->direction + binding->error, 2*M_PI) > direction)
{
act = e_action_find(binding->action);
act->func.go(obj, binding->params);
}
}
return act;
}
E_API Eina_Inarray*
e_bindings_swipe_find_candidates(E_Binding_Context ctxt, double direction, double length, unsigned int fingers)
{
Eina_Inarray *ret = eina_inarray_new(sizeof(E_Binding_Swipe_Candidate), 10);
E_Binding_Swipe *binding;
Eina_List *n;
EINA_LIST_FOREACH(swipe_bindings, n, binding)
{
if (binding->ctxt == ctxt &&
EINA_DBL_EQ(fingers, binding->fingers) &&
fmod(binding->direction - binding->error, 2*M_PI) < direction &&
fmod(binding->direction + binding->error, 2*M_PI) > direction)
{
E_Binding_Swipe_Candidate cad = {binding->action, length / binding->length};
eina_inarray_push(ret, &cad);
}
}
return ret;
}
E_API void
e_bindings_swipe_live_update_hook_set(E_Bindings_Swipe_Live_Update update, void *data)
{
live_update = update;
live_update_data = data;
}
E_API E_Bindings_Swipe_Live_Update
e_bindings_swipe_live_update_hook_get(void)
{
return live_update;
}
E_API void*
e_bindings_swipe_live_update_hook_data_get(void)
{
return live_update_data;
}

@ -35,6 +35,7 @@ typedef struct _E_Binding_Edge E_Binding_Edge;
typedef struct _E_Binding_Signal E_Binding_Signal;
typedef struct _E_Binding_Wheel E_Binding_Wheel;
typedef struct _E_Binding_Acpi E_Binding_Acpi;
typedef struct _E_Binding_Swipe E_Binding_Swipe;
typedef struct E_Binding_Event_Mouse_Button E_Binding_Event_Mouse_Button;
typedef struct E_Binding_Event_Wheel E_Binding_Event_Wheel;
@ -131,6 +132,15 @@ struct _E_Binding_Acpi
const char *action, *params;
};
struct _E_Binding_Swipe
{
E_Binding_Context ctxt;
double direction, length, error;
unsigned int fingers;
const char *action, *params;
};
EINTERN int e_bindings_init(void);
EINTERN int e_bindings_shutdown(void);
@ -139,6 +149,7 @@ E_API void e_bindings_key_reset(void);
E_API void e_bindings_wheel_reset(void);
E_API void e_bindings_edge_reset(void);
E_API void e_bindings_signal_reset(void);
E_API void e_bindings_swipe_reset(void);
E_API void e_bindings_reset(void);
E_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
E_API E_Action *e_bindings_acpi_find(E_Binding_Context ctxt, E_Event_Acpi *ev, E_Binding_Acpi **bind_ret);
E_API E_Action *e_bindings_acpi_event_handle(E_Binding_Context ctxt, E_Object *obj, E_Event_Acpi *ev);
typedef struct {
const char *name;
double acceptance; //0 to 1
} E_Binding_Swipe_Candidate;
typedef void (*E_Bindings_Swipe_Live_Update)(void *data, Eina_Bool end, double direction, double length, double error, unsigned int fingers);
/**
* Direction is in radiens, 0 is pointing to the right. Going clockwise. (Only positive range)
*/
E_API Eina_Bool e_bindings_swipe_available(void);
E_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);
E_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);
E_API E_Action* e_bindings_swipe_handle(E_Binding_Context ctxt, E_Object *obj, double direction, double length, unsigned int fingers);
E_API Eina_Inarray/*<E_Bindings_Swipe_Candidate>*/* e_bindings_swipe_find_candidates(E_Binding_Context ctxt, double direction, double lenght, unsigned int fingers);
E_API void e_bindings_swipe_live_update_hook_set(E_Bindings_Swipe_Live_Update update, void *data);
E_API E_Bindings_Swipe_Live_Update e_bindings_swipe_live_update_hook_get(void);
E_API void* e_bindings_swipe_live_update_hook_data_get(void);
E_API int e_bindings_evas_modifiers_convert(Evas_Modifier *modifiers);
E_API int e_bindings_modifiers_to_ecore_convert(E_Binding_Modifier modifiers);
E_API void e_bindings_evas_event_mouse_button_convert(const Evas_Event_Mouse_Down *ev, E_Binding_Event_Mouse_Button *event);

@ -28,6 +28,7 @@ static E_Config_DD *_e_config_bindings_edge_edd = NULL;
static E_Config_DD *_e_config_bindings_signal_edd = NULL;
static E_Config_DD *_e_config_bindings_wheel_edd = NULL;
static E_Config_DD *_e_config_bindings_acpi_edd = NULL;
static E_Config_DD *_e_config_bindings_swipe_edd = NULL;
static E_Config_DD *_e_config_path_append_edd = NULL;
static E_Config_DD *_e_config_desktop_bg_edd = NULL;
static E_Config_DD *_e_config_desklock_bg_edd = NULL;
@ -460,6 +461,7 @@ _e_config_edd_init(Eina_Bool old)
E_CONFIG_LIST(D, T, signal_bindings, _e_config_bindings_signal_edd); /**/
E_CONFIG_LIST(D, T, wheel_bindings, _e_config_bindings_wheel_edd); /**/
E_CONFIG_LIST(D, T, acpi_bindings, _e_config_bindings_acpi_edd); /**/
E_CONFIG_LIST(D, T, swipe_bindings, _e_config_bindings_swipe_edd); /**/
E_CONFIG_LIST(D, T, path_append_data, _e_config_path_append_edd); /**/
E_CONFIG_LIST(D, T, path_append_images, _e_config_path_append_edd); /**/
E_CONFIG_LIST(D, T, path_append_fonts, _e_config_path_append_edd); /**/
@ -924,6 +926,21 @@ e_config_init(void)
E_CONFIG_VAL(D, T, action, STR);
E_CONFIG_VAL(D, T, params, STR);
_e_config_bindings_swipe_edd = E_CONFIG_DD_NEW("E_Config_Binding_Swipe",
E_Config_Binding_Swipe);
#undef T
#undef D
#define T E_Config_Binding_Swipe
#define D _e_config_bindings_swipe_edd
E_CONFIG_VAL(D, T, context, INT);
E_CONFIG_VAL(D, T, fingers, UINT);
E_CONFIG_VAL(D, T, direction, DOUBLE);
E_CONFIG_VAL(D, T, length, DOUBLE);
E_CONFIG_VAL(D, T, error, DOUBLE);
E_CONFIG_VAL(D, T, action, STR);
E_CONFIG_VAL(D, T, params, STR);
_e_config_edd_init(EINA_FALSE);
_e_config_binding_edd = E_CONFIG_DD_NEW("E_Config_Bindings", E_Config_Bindings);
@ -938,6 +955,7 @@ e_config_init(void)
E_CONFIG_LIST(D, T, signal_bindings, _e_config_bindings_signal_edd); /**/
E_CONFIG_LIST(D, T, wheel_bindings, _e_config_bindings_wheel_edd); /**/
E_CONFIG_LIST(D, T, acpi_bindings, _e_config_bindings_acpi_edd); /**/
E_CONFIG_LIST(D, T, swipe_bindings, _e_config_bindings_swipe_edd); /**/
e_config_load();
@ -2257,6 +2275,16 @@ e_config_mode_changed(void)
ecore_event_add(E_EVENT_CONFIG_MODE_CHANGED, NULL, NULL, NULL);
}
E_API void
e_config_binding_swipe_free(E_Config_Binding_Swipe *eba)
{
if (!eba) return;
eina_stringshare_del(eba->action);
eina_stringshare_del(eba->params);
free(eba);
}
E_API void
e_config_binding_acpi_free(E_Config_Binding_Acpi *eba)
{

@ -10,6 +10,7 @@ typedef struct _E_Config_Binding_Edge E_Config_Binding_Edge;
typedef struct _E_Config_Binding_Signal E_Config_Binding_Signal;
typedef struct _E_Config_Binding_Wheel E_Config_Binding_Wheel;
typedef struct _E_Config_Binding_Acpi E_Config_Binding_Acpi;
typedef struct _E_Config_Binding_Swipe E_Config_Binding_Swipe;
typedef struct _E_Config_Desktop_Background E_Config_Desktop_Background;
typedef struct _E_Config_Desklock_Background E_Config_Desklock_Background;
typedef struct _E_Config_Desktop_Name E_Config_Desktop_Name;
@ -87,6 +88,7 @@ struct _E_Config
Eina_List *signal_bindings; // GUI
Eina_List *wheel_bindings; // GUI
Eina_List *acpi_bindings; // GUI
Eina_List *swipe_bindings; // GUI
Eina_List *path_append_data; // GUI
Eina_List *path_append_images; // GUI
@ -452,6 +454,7 @@ struct E_Config_Bindings
Eina_List *signal_bindings; // GUI
Eina_List *wheel_bindings; // GUI
Eina_List *acpi_bindings; // GUI
Eina_List *swipe_bindings;
};
struct _E_Config_Desklock_Background
@ -542,6 +545,14 @@ struct _E_Config_Binding_Acpi
const char *action, *params;
};
struct _E_Config_Binding_Swipe
{
int context;
unsigned int fingers;
double direction, length, error;
const char *action, *params;
};
struct _E_Config_Desktop_Background
{
int zone;
@ -675,6 +686,7 @@ E_API void e_config_binding_mouse_free(E_Config_Binding_Mouse *ebm);
E_API void e_config_binding_edge_free(E_Config_Binding_Edge *ebe);
E_API void e_config_binding_key_free(E_Config_Binding_Key *ebk);
E_API void e_config_binding_acpi_free(E_Config_Binding_Acpi *eba);
E_API void e_config_binding_swipe_free(E_Config_Binding_Swipe *eba);
extern E_API E_Config *e_config;
extern E_API E_Config_Bindings *e_bindings;

@ -0,0 +1,978 @@
#include "e.h"
#define TEXT_NO_PARAMS _("<None>")
struct _E_Config_Dialog_Data
{
Evas *evas;
struct
{
Eina_List *swipe;
} binding;
struct
{
const char *binding, *action;
char *params;
const char *cur;
int button;
int cur_act;
const char *swipe;
const char *source;
E_Dialog *dia;
double degree;
double error;
double length;
unsigned int fingers;
} locals;
struct
{
Evas_Object *o_add, *o_del, *o_del_all;
Evas_Object *o_binding_list, *o_action_list;
Evas_Object *o_params, *o_selector;
} gui;
const char *params;
int fullscreen_flip;
int multiscreen_flip;
E_Config_Dialog *cfd;
};
static E_Config_Binding_Swipe *
_swipe_binding_copy(E_Config_Binding_Swipe *bi)
{
E_Config_Binding_Swipe *bi2;
if (!bi) return NULL;
bi2 = E_NEW(E_Config_Binding_Swipe, 1);
bi2->context = bi->context;
bi2->direction = bi->direction;
bi2->length = bi->length;
bi2->fingers = bi->fingers;
bi2->error = bi->error;
bi2->action = bi->action;
bi2->params = bi->params;
return bi2;
}
static void
_swipe_binding_free(E_Config_Binding_Swipe *bi)
{
if (!bi) return;
eina_stringshare_del(bi->action);
eina_stringshare_del(bi->params);
free(bi);
}
static void
_auto_apply_changes(E_Config_Dialog_Data *cfdata)
{
int n, g, a, ok;
E_Config_Binding_Swipe *bi;
E_Action_Group *actg;
E_Action_Description *actd;
if ((!cfdata->locals.cur) || (!cfdata->locals.cur[0]) ||
(!cfdata->locals.action) || (!cfdata->locals.action[0])) return;
if (sscanf(cfdata->locals.cur, "s%d", &n) != 1)
return;
if (sscanf(cfdata->locals.action, "%d %d", &g, &a) != 2)
return;
bi = eina_list_nth(cfdata->binding.swipe, n);
if (!bi) return;
actg = eina_list_nth(e_action_groups_get(), g);
if (!actg) return;
actd = eina_list_nth(actg->acts, a);
if (!actd) return;
eina_stringshare_del(bi->action);
bi->action = NULL;
if (actd->act_cmd) bi->action = eina_stringshare_add(actd->act_cmd);
eina_stringshare_del(bi->params);
bi->params = NULL;
if (actd->act_params)
bi->params = eina_stringshare_add(actd->act_params);
else
{
ok = 1;
if (cfdata->locals.params)
{
if (!strcmp(cfdata->locals.params, TEXT_NO_PARAMS))
ok = 0;
if ((actd->param_example) && (!strcmp(cfdata->locals.params, actd->param_example)))
ok = 0;
}
else
ok = 0;
if (ok)
bi->params = eina_stringshare_add(cfdata->locals.params);
}
}
static void
_fill_data(E_Config_Dialog_Data *cfdata)
{
E_Config_Binding_Swipe *bi, *bi2;
Eina_List *l;
cfdata->locals.params = strdup("");
cfdata->locals.action = eina_stringshare_add("");
cfdata->locals.binding = eina_stringshare_add("");
cfdata->locals.swipe = eina_stringshare_add("");
cfdata->locals.source = eina_stringshare_add("");
cfdata->locals.cur = NULL;
cfdata->locals.dia = NULL;
cfdata->binding.swipe = NULL;
EINA_LIST_FOREACH(e_bindings->swipe_bindings, l, bi)
{
if (!bi) continue;
bi2 = _swipe_binding_copy(bi);
cfdata->binding.swipe = eina_list_append(cfdata->binding.swipe, bi2);
}
}
static void *
_create_data(E_Config_Dialog *cfd)
{
E_Config_Dialog_Data *cfdata;
cfdata = E_NEW(E_Config_Dialog_Data, 1);
cfdata->cfd = cfd;
_fill_data(cfdata);
return cfdata;
}
static void
_free_data(E_Config_Dialog *cfd EINA_UNUSED, E_Config_Dialog_Data *cfdata)
{
E_FREE_LIST(cfdata->binding.swipe, _swipe_binding_free);
eina_stringshare_del(cfdata->locals.cur);
eina_stringshare_del(cfdata->params);
eina_stringshare_del(cfdata->locals.binding);
eina_stringshare_del(cfdata->locals.action);
eina_stringshare_del(cfdata->locals.swipe);
eina_stringshare_del(cfdata->locals.source);
if (cfdata->locals.dia) e_object_del(E_OBJECT(cfdata->locals.dia));
free(cfdata->locals.params);
E_FREE(cfdata);
}
static void
_update_action_params(E_Config_Dialog_Data *cfdata)
{
int g, a, b;
E_Action_Group *actg;
E_Action_Description *actd;
E_Config_Binding_Swipe *bi;
const char *action, *params;
#define SIGNAL_EXAMPLE_PARAMS \
if ((!actd->param_example) || (!actd->param_example[0])) \
e_widget_entry_text_set(cfdata->gui.o_params, TEXT_NO_PARAMS); \
else \
e_widget_entry_text_set(cfdata->gui.o_params, actd->param_example)
if ((!cfdata->locals.action) || (!cfdata->locals.action[0]))
{
e_widget_disabled_set(cfdata->gui.o_params, 1);
e_widget_entry_clear(cfdata->gui.o_params);
return;
}
if (sscanf(cfdata->locals.action, "%d %d", &g, &a) != 2)
return;
actg = eina_list_nth(e_action_groups_get(), g);
if (!actg) return;
actd = eina_list_nth(actg->acts, a);
if (!actd) return;
if (actd->act_params)
{
e_widget_disabled_set(cfdata->gui.o_params, 1);
e_widget_entry_text_set(cfdata->gui.o_params, actd->act_params);
return;
}
if ((!cfdata->locals.cur) || (!cfdata->locals.cur[0]))
{
e_widget_disabled_set(cfdata->gui.o_params, 1);
SIGNAL_EXAMPLE_PARAMS;
return;
}
if (!actd->editable)
e_widget_disabled_set(cfdata->gui.o_params, 1);
else
e_widget_disabled_set(cfdata->gui.o_params, 0);
if (cfdata->locals.cur[0] == 's')
{
if (sscanf(cfdata->locals.cur, "s%d", &b) != 1)
{
e_widget_disabled_set(cfdata->gui.o_params, 1);
SIGNAL_EXAMPLE_PARAMS;
return;
}
bi = eina_list_nth(cfdata->binding.swipe, b);
if (!bi)
{
e_widget_disabled_set(cfdata->gui.o_params, 1);
SIGNAL_EXAMPLE_PARAMS;
return;
}
action = bi->action;
params = bi->params;
}
else
{
e_widget_disabled_set(cfdata->gui.o_params, 1);
SIGNAL_EXAMPLE_PARAMS;
return;
}
if (action)
{
if (!strcmp(action, actd->act_cmd))
{
if ((!params) || (!params[0]))
SIGNAL_EXAMPLE_PARAMS;
else
e_widget_entry_text_set(cfdata->gui.o_params, params);
}
else
SIGNAL_EXAMPLE_PARAMS;
}
else
SIGNAL_EXAMPLE_PARAMS;
}
static void
_action_change_cb(void *data)
{
E_Config_Dialog_Data *cfdata;
cfdata = data;
_update_action_params(cfdata);
}
static int
_swipe_binding_sort_cb(E_Config_Binding_Swipe *a, E_Config_Binding_Swipe *b)
{
int finger_diff = (a->fingers == b->fingers)*-1;
if (!finger_diff)
{
return a->direction - b->direction;
}
return finger_diff;
}
static void
_update_buttons(E_Config_Dialog_Data *cfdata)
{
if (e_widget_ilist_count(cfdata->gui.o_binding_list))
e_widget_disabled_set(cfdata->gui.o_del_all, 0);
else
e_widget_disabled_set(cfdata->gui.o_del_all, 1);
if (!cfdata->locals.cur)
{
e_widget_disabled_set(cfdata->gui.o_del, 1);
return;
}
e_widget_disabled_set(cfdata->gui.o_del, 0);
}
static void
_find_swipe_binding_action(const char *action, const char *params, int *g, int *a, int *n)
{
Eina_List *l, *l2;
int gg = -1, aa = -1, nn = -1, found;
E_Action_Group *actg;
E_Action_Description *actd;
if (g) *g = -1;
if (a) *a = -1;
if (n) *n = -1;
found = 0;
for (l = e_action_groups_get(), gg = 0, nn = 0; l; l = l->next, gg++)
{
actg = l->data;
for (l2 = actg->acts, aa = 0; l2; l2 = l2->next, aa++)
{
actd = l2->data;
if (!strcmp((!action ? "" : action), (!actd->act_cmd ? "" : actd->act_cmd)))
{
if (!params || !params[0])
{
if ((!actd->act_params) || (!actd->act_params[0]))
{
if (g) *g = gg;
if (a) *a = aa;
if (n) *n = nn;
return;
}
else
continue;
}
else
{
if ((!actd->act_params) || (!actd->act_params[0]))
{
if (g) *g = gg;
if (a) *a = aa;
if (n) *n = nn;
found = 1;
}
else
{
if (!strcmp(params, actd->act_params))
{
if (g) *g = gg;
if (a) *a = aa;
if (n) *n = nn;
return;
}
}
}
}
nn++;
}
if (found) break;
}
if (!found)
{
if (g) *g = -1;
if (a) *a = -1;
if (n) *n = -1;
}
}
static void
_update_action_list(E_Config_Dialog_Data *cfdata)
{
E_Config_Binding_Swipe *bi;
int j = -1, i, n;
const char *action, *params;
if (!cfdata->locals.cur) return;
if (cfdata->locals.cur[0] == 's')
{
if (sscanf(cfdata->locals.cur, "s%d", &n) != 1)
return;
bi = eina_list_nth(cfdata->binding.swipe, n);
if (!bi)
{
e_widget_ilist_unselect(cfdata->gui.o_action_list);
e_widget_entry_clear(cfdata->gui.o_params);
e_widget_disabled_set(cfdata->gui.o_params, 1);
return;
}
action = bi->action;
params = bi->params;
}
else
return;
_find_swipe_binding_action(action, params, NULL, NULL, &j);
if (j >= 0)
{
for (i = 0; i < e_widget_ilist_count(cfdata->gui.o_action_list); i++)
{
if (i > j) break;
if (e_widget_ilist_nth_is_header(cfdata->gui.o_action_list, i)) j++;
}
}
if (j >= 0)
{
if (j == e_widget_ilist_selected_get(cfdata->gui.o_action_list))
_update_action_params(cfdata);
else
e_widget_ilist_selected_set(cfdata->gui.o_action_list, j);
}
else
{
e_widget_ilist_unselect(cfdata->gui.o_action_list);
eina_stringshare_del(cfdata->locals.action);
cfdata->locals.action = eina_stringshare_add("");
e_widget_entry_clear(cfdata->gui.o_params);
}
}
static void
_binding_change_cb(void *data)
{
E_Config_Dialog_Data *cfdata;
cfdata = data;
_auto_apply_changes(cfdata);
if (cfdata->locals.cur) eina_stringshare_del(cfdata->locals.cur);
cfdata->locals.cur = NULL;
if ((!cfdata->locals.binding) || (!cfdata->locals.binding[0])) return;
cfdata->locals.cur = eina_stringshare_ref(cfdata->locals.binding);
_update_buttons(cfdata);
_update_action_list(cfdata);
}
static int
_basic_apply_data(E_Config_Dialog *cfd EINA_UNUSED, E_Config_Dialog_Data *cfdata)
{
Eina_List *l;
E_Config_Binding_Swipe *bi, *bi2;
_auto_apply_changes(cfdata);
E_FREE_LIST(e_bindings->swipe_bindings, _swipe_binding_free);
EINA_LIST_FOREACH(cfdata->binding.swipe, l, bi2)
{
bi = _swipe_binding_copy(bi2);
e_bindings->swipe_bindings = eina_list_append(e_bindings->swipe_bindings, bi);
}
e_bindings_swipe_reset();
e_config_save_queue();
return 1;
}
static Evas_Object*
create_visualisation(Evas *e, double direction, double error)
{
Evas_Vg_Container *vg = NULL;
Evas_Vg_Shape *container, *shape, *viewport = NULL;
double center_x = 15, center_y = 15;
vg = evas_object_vg_add(e);
evas_object_vg_viewbox_set(vg, EINA_RECT(0, 0, 50, 50));
container = evas_vg_container_add(vg);
viewport = evas_vg_shape_add(container);
evas_vg_shape_append_rect(viewport, 0, 0, 51, 51, 0, 0);
evas_vg_shape_stroke_cap_set(viewport, EVAS_VG_CAP_SQUARE);
evas_vg_shape_stroke_color_set(viewport, 0, 0, 0, 0);
evas_vg_shape_stroke_width_set(viewport, 1);
shape = evas_vg_shape_add(container);
evas_vg_shape_append_rect(shape, 1, 1, 29, 29, 0, 0);
evas_vg_shape_stroke_cap_set(shape, EVAS_VG_CAP_SQUARE);
evas_vg_shape_stroke_color_set(shape, 100, 100, 100, 255);
evas_vg_shape_stroke_width_set(shape, 1);
shape = evas_vg_shape_add(container);
evas_vg_shape_append_line_to(shape, center_x, center_y);
evas_vg_shape_append_line_to(shape, center_x + cos(direction - error)*11, center_y + sin(direction - error)*11);
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);
evas_vg_shape_append_line_to(shape, center_x, center_y);
evas_vg_shape_stroke_cap_set(shape, EVAS_VG_CAP_ROUND);
evas_vg_shape_stroke_color_set(shape, 255, 0, 0, 255);
evas_vg_shape_stroke_width_set(shape, 2);
evas_object_vg_root_node_set(vg, container);
evas_object_show(vg);
return vg;
}
static void
_update_swipe_binding_list(E_Config_Dialog_Data *cfdata)
{
int i = 0;
char b2[64], b3[64];
Eina_List *l;
E_Config_Binding_Swipe *bi;
unsigned int previous_fingers = 0;
evas_event_freeze(evas_object_evas_get(cfdata->gui.o_binding_list));
edje_freeze();
e_widget_ilist_freeze(cfdata->gui.o_binding_list);
e_widget_ilist_clear(cfdata->gui.o_binding_list);
e_widget_ilist_go(cfdata->gui.o_binding_list);
if (cfdata->binding.swipe)
cfdata->binding.swipe = eina_list_sort(cfdata->binding.swipe, 0, (Eina_Compare_Cb)_swipe_binding_sort_cb);
EINA_LIST_FOREACH(cfdata->binding.swipe, l, bi)
{
Evas_Object *vis;
vis = create_visualisation(evas_object_evas_get(cfdata->gui.o_binding_list), bi->direction, bi->error);
if (bi->fingers != previous_fingers)
{
snprintf(b3, sizeof(b3), "%d Fingers", bi->fingers);
previous_fingers = bi->fingers;
e_widget_ilist_header_append(cfdata->gui.o_binding_list, NULL, b3);
}
snprintf(b2, sizeof(b2), "s%d", i);
snprintf(b3, sizeof(b3), "Length: %.2f Error: %.2f", bi->length, bi->error);
e_widget_ilist_append(cfdata->gui.o_binding_list, vis, b3, _binding_change_cb, cfdata, b2);
i++;
}
e_widget_ilist_go(cfdata->gui.o_binding_list);
e_widget_ilist_thaw(cfdata->gui.o_binding_list);
edje_thaw();
evas_event_thaw(evas_object_evas_get(cfdata->gui.o_binding_list));
if (eina_list_count(cfdata->binding.swipe))
e_widget_disabled_set(cfdata->gui.o_del_all, 0);
else
e_widget_disabled_set(cfdata->gui.o_del_all, 1);
}
static void
_fill_actions_list(E_Config_Dialog_Data *cfdata)
{
char buf[1024];
Eina_List *l, *l2;
E_Action_Group *actg;
E_Action_Description *actd;
int g, a;
evas_event_freeze(evas_object_evas_get(cfdata->gui.o_action_list));
edje_freeze();
e_widget_ilist_freeze(cfdata->gui.o_action_list);
e_widget_ilist_clear(cfdata->gui.o_action_list);
for (l = e_action_groups_get(), g = 0; l; l = l->next, g++)
{
actg = l->data;
if (!actg->acts) continue;
e_widget_ilist_header_append(cfdata->gui.o_action_list, NULL, _(actg->act_grp));
for (l2 = actg->acts, a = 0; l2; l2 = l2->next, a++)
{
actd = l2->data;
snprintf(buf, sizeof(buf), "%d %d", g, a);
e_widget_ilist_append(cfdata->gui.o_action_list, NULL, _(actd->act_name),
_action_change_cb, cfdata, buf);
}
}
e_widget_ilist_go(cfdata->gui.o_action_list);
e_widget_ilist_thaw(cfdata->gui.o_action_list);
edje_thaw();
evas_event_thaw(evas_object_evas_get(cfdata->gui.o_action_list));
}
static void
_flush_binding_swipe(E_Config_Dialog_Data *cfdata)
{
E_Config_Binding_Swipe *bi;
bi = E_NEW(E_Config_Binding_Swipe, 1);
bi->context = E_BINDING_CONTEXT_NONE;
bi->length = cfdata->locals.length;
bi->direction = cfdata->locals.degree;
bi->error = cfdata->locals.error;
bi->fingers = cfdata->locals.fingers;
cfdata->binding.swipe = eina_list_append(cfdata->binding.swipe, bi);
_update_swipe_binding_list(cfdata);
}
static void
_swipe_add_cb_ok(void *data, E_Dialog *dia)
{
E_Config_Dialog_Data *cfdata = data;
_flush_binding_swipe(cfdata);
e_object_del(E_OBJECT(dia));
}
static void
_swipe_add_cb_cancel(void *data EINA_UNUSED, E_Dialog *dia)
{
e_object_del(E_OBJECT(dia));
}
static void
_swipe_add_del(void *data)
{
E_Dialog *dia = data;
E_Config_Dialog_Data *cfdata;
if (!dia->data) return;
cfdata = dia->data;
cfdata->locals.dia = NULL;
}
static void
_double_getter(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
{
double *container = data;
double tmp = elm_spinner_value_get(obj);
*container = tmp;
}
static void
_int_getter(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
{
unsigned int *container = data;
double tmp = elm_spinner_value_get(obj);
*container = tmp;
}
static void
_swipe_add_show(E_Config_Dialog_Data *cfdata)
{
Evas_Object *o, *obg, *ol, *entry;
Evas *evas;
int w, h;
if (cfdata->locals.dia) return;
cfdata->locals.dia = e_dialog_new(cfdata->cfd->dia->win, "E", "_swipebind_new_dialog");
e_dialog_resizable_set(cfdata->locals.dia, 1);
e_dialog_title_set(cfdata->locals.dia, _("Add Swipe Binding"));
e_dialog_icon_set(cfdata->locals.dia, "enlightenment/swipes", 48);
e_dialog_button_add(cfdata->locals.dia, _("OK"), NULL, _swipe_add_cb_ok, cfdata);
e_dialog_button_add(cfdata->locals.dia, _("Cancel"), NULL, _swipe_add_cb_cancel, cfdata);
e_object_del_attach_func_set(E_OBJECT(cfdata->locals.dia), _swipe_add_del);
cfdata->locals.dia->data = cfdata;
elm_win_center(cfdata->locals.dia->win, 1, 1);
evas = evas_object_evas_get(cfdata->locals.dia->win);
obg = e_widget_list_add(evas, 1, 0);
ol = e_widget_framelist_add(evas, _("Direction:"), 0);
entry = o = elm_spinner_add(cfdata->locals.dia->win);
evas_object_smart_callback_add(o, "changed", _double_getter, &cfdata->locals.degree);
elm_spinner_min_max_set(o, 0, 2*M_PI);
elm_spinner_label_format_set(o, "%f");
elm_spinner_step_set(o, 0.1);
elm_spinner_editable_set(o, EINA_TRUE);
e_widget_framelist_object_append(ol, o);
e_widget_list_object_append(obg, ol, 1, 0, 0.5);
ol = e_widget_framelist_add(evas, _("Error:"), 0);
entry = o = elm_spinner_add(cfdata->locals.dia->win);
evas_object_smart_callback_add(o, "changed", _double_getter, &cfdata->locals.error);
elm_spinner_min_max_set(o, 0, 2*M_PI);
elm_spinner_label_format_set(o, "%f");
elm_spinner_step_set(o, 0.1);
elm_spinner_editable_set(o, EINA_TRUE);
e_widget_framelist_object_append(ol, o);
e_widget_list_object_append(obg, ol, 1, 0, 0.5);
ol = e_widget_framelist_add(evas, _("Length:"), 0);
entry = o = elm_spinner_add(cfdata->locals.dia->win);
evas_object_smart_callback_add(o, "changed", _double_getter, &cfdata->locals.length);
elm_spinner_min_max_set(o, 0, 200);
elm_spinner_step_set(o, 5);
elm_spinner_editable_set(o, EINA_TRUE);
e_widget_framelist_object_append(ol, o);
e_widget_list_object_append(obg, ol, 1, 0, 0.5);
cfdata->locals.fingers = 3;
ol = e_widget_framelist_add(evas, _("Fingers:"), 0);
entry = o = elm_spinner_add(cfdata->locals.dia->win);
evas_object_smart_callback_add(o, "changed", _int_getter, &cfdata->locals.fingers);
elm_spinner_min_max_set(o, 3, 10);
elm_spinner_value_set(o, 3.0);
elm_spinner_editable_set(o, EINA_TRUE);
e_widget_framelist_object_append(ol, o);
e_widget_list_object_append(obg, ol, 1, 0, 0.5);
e_widget_size_min_get(obg, &w, &h);
e_dialog_content_set(cfdata->locals.dia, obg, MAX(w, 200), MAX(h, 100));
e_dialog_show(cfdata->locals.dia);
e_widget_focus_set(entry, 1);
}
static void
_add_swipe_binding_cb(void *data, void *data2 EINA_UNUSED)
{
E_Config_Dialog_Data *cfdata = data;
_auto_apply_changes(cfdata);
_swipe_add_show(cfdata);
}
static void
_update_swipe_cb(void *data, Eina_Bool end, double direction, double length, double error, unsigned int fingers)
{
E_Config_Dialog_Data *cfdata = data;
if (end)
{
e_object_del(E_OBJECT(cfdata->locals.dia));
cfdata->locals.dia = NULL;
cfdata->locals.degree = direction;
cfdata->locals.length = length;
cfdata->locals.error = error;
cfdata->locals.fingers = fingers;
_flush_binding_swipe(cfdata);
e_bindings_swipe_live_update_hook_set(NULL, NULL);
}
else
{
char text_buf[1000];
Evas_Object *vis;
vis = create_visualisation(evas_object_evas_get(cfdata->locals.dia->win), direction, error);
evas_object_size_hint_align_set(vis, 0.0, 0.5);
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);
e_dialog_text_set(cfdata->locals.dia, text_buf);
elm_object_part_content_set(cfdata->locals.dia->bg_object, "e.swallow.icon", vis);
evas_object_size_hint_min_set(vis, 30 * e_scale, 30 * e_scale);
elm_layout_signal_emit(cfdata->locals.dia->bg_object, "e,state,icon", "e");
elm_layout_signal_emit(cfdata->locals.dia->bg_object, "e,icon,enabled", "e");
}
}
static void
_add_swipe_binding_by_sample_cb(void *data, void *data2 EINA_UNUSED)
{
E_Config_Dialog_Data *cfdata = data;
cfdata->locals.dia = e_dialog_new(cfdata->cfd->dia->win, "E", "_swipe_recognition");
e_dialog_title_set(cfdata->locals.dia, "Swipe recognition");
e_dialog_text_set(cfdata->locals.dia, "Do your swipe gesture.<br>");
elm_win_center(cfdata->locals.dia->win, 1, 1);
elm_win_borderless_set(cfdata->locals.dia->win, 1);
e_dialog_resizable_set(cfdata->locals.dia, 0);
e_dialog_show(cfdata->locals.dia);
evas_object_layer_set(e_win_client_get(cfdata->locals.dia->win)->frame, E_LAYER_CLIENT_PRIO);
e_bindings_swipe_live_update_hook_set(_update_swipe_cb, data);
}
static void
_delete_swipe_binding_cb(void *data, void *data2 EINA_UNUSED)
{
Eina_List *l = NULL;
int sel, n;
E_Config_Dialog_Data *cfdata;
cfdata = data;
sel = e_widget_ilist_selected_get(cfdata->gui.o_binding_list);
if (cfdata->locals.binding[0] == 's')
{
if (sscanf(cfdata->locals.binding, "s%d", &n) != 1)
return;
l = eina_list_nth_list(cfdata->binding.swipe, n);
if (l)
{
_swipe_binding_free(eina_list_data_get(l));
cfdata->binding.swipe = eina_list_remove_list(cfdata->binding.swipe, l);
}
}
_update_swipe_binding_list(cfdata);
if (sel >= e_widget_ilist_count(cfdata->gui.o_binding_list))
sel = e_widget_ilist_count(cfdata->gui.o_binding_list) - 1;
eina_stringshare_del(cfdata->locals.cur);
cfdata->locals.cur = NULL;
e_widget_ilist_selected_set(cfdata->gui.o_binding_list, sel);
if (sel < 0)
{
e_widget_ilist_unselect(cfdata->gui.o_action_list);
e_widget_entry_clear(cfdata->gui.o_params);
e_widget_disabled_set(cfdata->gui.o_params, 1);
_update_buttons(cfdata);
}
}
static void
_delete_all_swipe_binding_cb(void *data, void *data2 EINA_UNUSED)
{
E_Config_Binding_Swipe *bi;
E_Config_Dialog_Data *cfdata;
cfdata = data;
EINA_LIST_FREE(cfdata->binding.swipe, bi)
_swipe_binding_free(bi);
eina_stringshare_del(cfdata->locals.cur);
cfdata->locals.cur = NULL;
e_widget_ilist_clear(cfdata->gui.o_binding_list);
e_widget_ilist_go(cfdata->gui.o_binding_list);
e_widget_ilist_unselect(cfdata->gui.o_action_list);
e_widget_entry_clear(cfdata->gui.o_params);
e_widget_disabled_set(cfdata->gui.o_params, 1);
_update_buttons(cfdata);
}
static void
_restore_swipe_binding_defaults_cb(void *data, void *data2 EINA_UNUSED)
{
E_Config_Bindings *ecb;
Eina_Stringshare *prof;
E_Config_Dialog_Data *cfdata = data;
ecb = e_config_domain_system_load("e_bindings", e_config_descriptor_find("E_Config_Bindings"));
if (!ecb)
{
const char *type;
prof = eina_stringshare_ref(e_config_profile_get());
switch (e_config->config_type)
{
case E_CONFIG_PROFILE_TYPE_DESKTOP:
type = "standard";
break;
case E_CONFIG_PROFILE_TYPE_MOBILE:
type = "mobile";
break;
//case E_CONFIG_PROFILE_TYPE_TABLET: FIXME - not used
default:
type = "default";
break;
}
e_config_profile_set(type);
ecb = e_config_domain_system_load("e_bindings", e_config_descriptor_find("E_Config_Bindings"));