Recording: support new EFL input events

During recording, hooking on Evas functions can't work anymore as they
are no more invoked internally.
The new way to catch the events is to listen to them on the canvas.
Additionally, regular mouse events are now multi events whose tool (device id)
is 0, as well as key events with and without keycode are now always
considered with a keycode that can be 0.

Previous events catching has been kept to support legacy applications.
This commit is contained in:
Daniel Zaoui 2016-09-22 07:28:56 +03:00
parent fefa31d7b2
commit 95327a0f7c
4 changed files with 282 additions and 65 deletions

View File

@ -76,6 +76,9 @@ _event_specific_info_get(const Variant_st *v, char output[1024])
case TSUITE_EVENT_MULTI_DOWN: case TSUITE_EVENT_MULTI_UP:
{
multi_event *t = v->data;
if (!t->d)
sprintf(output, "Button %d Flags %d", t->b, t->flags);
else
sprintf(output, "D %d X %d Y %d Rad %f RadX %f RadY %f Pres %f Ang %f FX %f FY %f Flags %d",
t->d, t->x, t->y, t->rad, t->radx, t->rady, t->pres, t->ang, t->fx, t->fy, t->flags);
break;
@ -83,6 +86,9 @@ _event_specific_info_get(const Variant_st *v, char output[1024])
case TSUITE_EVENT_MULTI_MOVE:
{
multi_move *t = v->data;
if (!t->d)
sprintf(output, "X %d Y %d", t->x, t->y);
else
sprintf(output, "D %d X %d Y %d Rad %f RadX %f RadY %f Pres %f Ang %f FX %f FY %f",
t->d, t->x, t->y, t->rad, t->radx, t->rady, t->pres, t->ang, t->fx, t->fy);
break;

View File

@ -1,4 +1,7 @@
#define _GNU_SOURCE 1
#define EFL_EO_API_SUPPORT
#define EFL_BETA_API_SUPPORT
#include <Eo.h>
#include <Eet.h>
#include <Evas.h>
#include <Ecore.h>
@ -43,6 +46,94 @@ static Tsuite_Data ts;
static Eina_List *evas_list = NULL; /* List of Evas pointers */
static int ignore_evas_new = 0; /* Counter to know if we should ignore evas new or not. */
static Tsuite_Event_Type
tsuite_event_pointer_type_get(Efl_Pointer_Action t)
{
switch(t)
{
case EFL_POINTER_ACTION_IN: return TSUITE_EVENT_MOUSE_IN;
case EFL_POINTER_ACTION_OUT: return TSUITE_EVENT_MOUSE_OUT;
case EFL_POINTER_ACTION_DOWN: return TSUITE_EVENT_MULTI_DOWN;
case EFL_POINTER_ACTION_UP: return TSUITE_EVENT_MULTI_UP;
case EFL_POINTER_ACTION_MOVE: return TSUITE_EVENT_MULTI_MOVE;
case EFL_POINTER_ACTION_WHEEL: return TSUITE_EVENT_MOUSE_WHEEL;
default:
return TSUITE_EVENT_NOT_SUPPORTED;
}
}
#ifdef DEBUG_TSUITE
static const char *
_event_name_get(Tsuite_Event_Type type)
{
switch(type)
{
case TSUITE_EVENT_MOUSE_IN: return "Mouse In";
case TSUITE_EVENT_MOUSE_OUT: return "Mouse Out";
case TSUITE_EVENT_MOUSE_DOWN: return "Mouse Down";
case TSUITE_EVENT_MOUSE_UP: return "Mouse Up";
case TSUITE_EVENT_MOUSE_MOVE: return "Mouse Move";
case TSUITE_EVENT_MOUSE_WHEEL: return "Mouse Wheel";
case TSUITE_EVENT_MULTI_DOWN: return "Multi Down";
case TSUITE_EVENT_MULTI_UP: return "Multi Up";
case TSUITE_EVENT_MULTI_MOVE: return "Multi Move";
case TSUITE_EVENT_KEY_DOWN: return "Key Down";
case TSUITE_EVENT_KEY_UP: return "Key Up";
case TSUITE_EVENT_KEY_DOWN_WITH_KEYCODE: return "Key Down with Keycode";
case TSUITE_EVENT_KEY_UP_WITH_KEYCODE: return "Key Up with Keycode";
case TSUITE_EVENT_TAKE_SHOT: return "Take shot";
default: return NULL;
}
}
#endif
static Eina_Bool
_is_hook_duplicate(const Variant_st *v, Tsuite_Event_Type ev_type, const void *info, int len)
{
if (v->t.type == tsuite_event_mapping_type_str_get(ev_type) &&
!memcmp(v->data, info, len)) return EINA_TRUE;
return EINA_FALSE;
}
/* Adding variant to list, this list is later written to EET file */
#define ADD_TO_LIST(EVT_TYPE, EVT_STRUCT_NAME, INFO) \
do { /* This macro will add event to EET data list */ \
if (vr_list && _hook_setting->recording) \
{ \
const Variant_st *prev_v = eina_list_last_data_get(vr_list->variant_list); \
if (!prev_v || !_is_hook_duplicate(prev_v, EVT_TYPE, &INFO, sizeof(EVT_STRUCT_NAME))) \
{ \
printf("Recording %s\n", tsuite_event_mapping_type_str_get(EVT_TYPE)); \
Variant_st *v = malloc(sizeof(Variant_st)); \
v->data = malloc(sizeof(EVT_STRUCT_NAME)); \
_variant_type_set(tsuite_event_mapping_type_str_get(EVT_TYPE), \
&v->t, EINA_FALSE); \
memcpy(v->data, &INFO, sizeof(EVT_STRUCT_NAME)); \
vr_list->variant_list = eina_list_append(vr_list->variant_list, v); \
} \
} \
} while (0)
static int
evas_list_find(void *ptr)
{ /* We just compare the pointers */
Eina_List *l;
void *data;
int n = 0;
EINA_LIST_FOREACH(evas_list, l, data)
{ /* Get the nuber of Evas Pointer */
if (ptr == data)
{
return n;
}
n++;
}
return -1;
}
static void
_tsuite_verbosef(const char *fmt, ...)
{
@ -326,6 +417,138 @@ ecore_shutdown(void)
return _ecore_shutdown();
}
static void
_event_pointer_cb(void *data, const Efl_Event *event)
{
Eo *eo_e = data;
Eo *evp = event->info;
if (!evp) return;
int timestamp = efl_input_timestamp_get(evp);
int n_evas = evas_list_find(eo_e);
Efl_Pointer_Action action = efl_input_pointer_action_get(evp);
Tsuite_Event_Type evt = tsuite_event_pointer_type_get(action);
if (!timestamp) return;
#ifdef DEBUG_TSUITE
printf("Calling \"%s\" timestamp=<%u>\n", _event_name_get(evt), timestamp);
#endif
switch (action)
{
case EFL_POINTER_ACTION_MOVE:
{
double rad = 0, radx = 0, rady = 0, pres = 0, ang = 0, fx = 0, fy = 0;
int tool = efl_input_pointer_tool_get(evp);
int x = 0, y = 0;
efl_input_pointer_position_get(evp, &x, &y);
multi_move t = { tool, x, y, rad, radx, rady, pres, ang, fx, fy, timestamp, n_evas };
if (t.n_evas >= 0) ADD_TO_LIST(evt, multi_move, t);
break;
}
case EFL_POINTER_ACTION_DOWN: case EFL_POINTER_ACTION_UP:
{
double rad = 0, radx = 0, rady = 0, pres = 0, ang = 0, fx = 0, fy = 0;
int b = efl_input_pointer_button_get(evp);
int tool = efl_input_pointer_tool_get(evp);
int x = 0, y = 0;
efl_input_pointer_position_get(evp, &x, &y);
Efl_Pointer_Flags flags = efl_input_pointer_button_flags_get(evp);
multi_event t = { tool, b, x, y, rad, radx, rady, pres, ang,
fx, fy, flags, timestamp, n_evas };
if (t.n_evas >= 0) ADD_TO_LIST(evt, multi_event, t);
break;
}
case EFL_POINTER_ACTION_IN: case EFL_POINTER_ACTION_OUT:
{
mouse_in_mouse_out t = { timestamp, n_evas };
if (t.n_evas >= 0) ADD_TO_LIST(evt, mouse_in_mouse_out, t);
break;
}
case EFL_POINTER_ACTION_WHEEL:
{
int direction = efl_input_pointer_wheel_direction_get(evp);
int z = efl_input_pointer_wheel_delta_get(evp);
mouse_wheel t = { direction, z, timestamp, n_evas };
if (t.n_evas >= 0) ADD_TO_LIST(evt, mouse_wheel, t);
break;
}
default:
break;
}
}
static void
_event_key_cb(void *data, const Efl_Event *event)
{
Efl_Input_Key *evk = event->info;
Eo *eo_e = data;
if (!evk) return;
const char *key = efl_input_key_name_get(evk);
int timestamp = efl_input_timestamp_get(evk);
int n_evas = evas_list_find(eo_e);
Tsuite_Event_Type evt = TSUITE_EVENT_KEY_UP_WITH_KEYCODE;
if (efl_input_key_pressed_get(evk))
{
if (!strcmp(key, shot_key))
{
#ifdef DEBUG_TSUITE
printf("Take Screenshot: %s timestamp=<%u>\n", __func__, timestamp);
#endif
take_screenshot t = { timestamp, n_evas };
if (t.n_evas >= 0)
ADD_TO_LIST(TSUITE_EVENT_TAKE_SHOT, take_screenshot, t);
return;
}
if (!strcmp(key, SAVE_KEY_STR))
{
if (_hook_setting)
{
if (vr_list && _hook_setting->recording)
write_events(_hook_setting->file_name, vr_list);
#ifdef DEBUG_TSUITE
printf("Save events: %s timestamp=<%u>\n", __func__, timestamp);
#endif
}
return;
}
evt = TSUITE_EVENT_KEY_DOWN_WITH_KEYCODE;
}
else
{
if (!strcmp(key, shot_key) || !strcmp(key, SAVE_KEY_STR)) return;
}
if (vr_list && _hook_setting->recording)
{ /* Construct duplicate strings, free them when list if freed */
key_down_key_up_with_keycode t;
t.timestamp = timestamp;
t.keyname = eina_stringshare_add(key);
t.key = eina_stringshare_add(efl_input_key_get(evk));
t.string = eina_stringshare_add(efl_input_key_string_get(evk));
t.compose = eina_stringshare_add(efl_input_key_compose_get(evk));
t.keycode = efl_input_key_code_get(evk);
t.n_evas = n_evas;
if (t.n_evas >= 0) ADD_TO_LIST(evt, key_down_key_up_with_keycode, t);
}
}
// note: "hold" event comes from above (elm), not below (ecore)
EFL_CALLBACKS_ARRAY_DEFINE(_event_pointer_callbacks,
{ EFL_EVENT_POINTER_MOVE, _event_pointer_cb },
{ EFL_EVENT_POINTER_DOWN, _event_pointer_cb },
{ EFL_EVENT_POINTER_UP, _event_pointer_cb },
{ EFL_EVENT_POINTER_IN, _event_pointer_cb },
{ EFL_EVENT_POINTER_OUT, _event_pointer_cb },
{ EFL_EVENT_POINTER_WHEEL, _event_pointer_cb },
{ EFL_EVENT_FINGER_MOVE, _event_pointer_cb },
{ EFL_EVENT_FINGER_DOWN, _event_pointer_cb },
{ EFL_EVENT_FINGER_UP, _event_pointer_cb },
{ EFL_EVENT_KEY_DOWN, _event_key_cb },
{ EFL_EVENT_KEY_UP, _event_key_cb }
)
EAPI Evas *
evas_new(void)
{
@ -336,6 +559,7 @@ evas_new(void)
if (ignore_evas_new == 0)
{
evas_list = eina_list_append(evas_list, evas);
efl_event_callback_array_add(evas, _event_pointer_callbacks(), evas);
#ifdef DEBUG_TSUITE
printf("Appended EVAS=<%p> list size=<%d>\n", evas, eina_list_count(evas_list));
#endif
@ -475,10 +699,19 @@ tsuite_feed_event(void *data)
#ifdef DEBUG_TSUITE
printf("%s evas_event_feed_multi_down timestamp=<%u>, t->n_evas=<%d>\n", __func__, t->timestamp,t->n_evas);
#endif
if (!t->d)
{
evas_event_feed_mouse_down(eina_list_nth(evas_list, t->n_evas),
t->b, t->flags, time(NULL), NULL);
if (rect) evas_object_color_set(rect, 255, 255, 0, 255);
}
else
{
evas_event_feed_multi_down(eina_list_nth(evas_list, t->n_evas),
t->d, t->x, t->y, t->rad,
t->radx, t->rady, t->pres, t->ang, t->fx, t->fy,
t->flags, time(NULL), NULL);
}
break;
}
@ -489,10 +722,19 @@ tsuite_feed_event(void *data)
#ifdef DEBUG_TSUITE
printf("%s evas_event_feed_multi_up timestamp=<%u> t->n_evas=<%d>\n", __func__, t->timestamp,t->n_evas);
#endif
if (!t->d)
{
evas_event_feed_mouse_up(eina_list_nth(evas_list, t->n_evas),
t->b, t->flags, time(NULL), NULL);
if (rect) evas_object_color_set(rect, 255, 0, 0, 255);
}
else
{
evas_event_feed_multi_up(eina_list_nth(evas_list, t->n_evas),
t->d, t->x, t->y, t->rad,
t->radx, t->rady, t->pres, t->ang, t->fx, t->fy,
t->flags, time(NULL), NULL);
}
break;
}
@ -503,10 +745,23 @@ tsuite_feed_event(void *data)
#ifdef DEBUG_TSUITE
printf("%s evas_event_feed_multi_move timestamp=<%u> t->n_evas=<%d>\n", __func__, t->timestamp, t->n_evas);
#endif
if (!t->d)
{
evas_event_feed_mouse_move(eina_list_nth(evas_list, t->n_evas),
t->x, t->y, time(NULL), NULL);
if (rect)
{
evas_object_move(rect, t->x, t->y);
evas_object_color_set(rect, 255, 0, 0, 255);
}
}
else
{
evas_event_feed_multi_move(eina_list_nth(evas_list, t->n_evas),
t->d, t->x, t->y, t->rad,
t->radx, t->rady, t->pres, t->ang, t->fx, t->fy,
time(NULL), NULL);
}
break;
}
@ -657,52 +912,6 @@ ecore_main_loop_begin(void)
return _ecore_main_loop_begin();
}
static Eina_Bool
_is_hook_duplicate(const Variant_st *v, Tsuite_Event_Type ev_type, const void *info, int len)
{
if (v->t.type == tsuite_event_mapping_type_str_get(ev_type) &&
!memcmp(v->data, info, len)) return EINA_TRUE;
return EINA_FALSE;
}
/* Adding variant to list, this list is later written to EET file */
#define ADD_TO_LIST(EVT_TYPE, EVT_STRUCT_NAME, INFO) \
do { /* This macro will add event to EET data list */ \
if (vr_list && _hook_setting->recording) \
{ \
const Variant_st *prev_v = eina_list_last_data_get(vr_list->variant_list); \
if (!prev_v || !_is_hook_duplicate(prev_v, EVT_TYPE, &INFO, sizeof(EVT_STRUCT_NAME))) \
{ \
printf("Recording %s\n", tsuite_event_mapping_type_str_get(EVT_TYPE)); \
Variant_st *v = malloc(sizeof(Variant_st)); \
v->data = malloc(sizeof(EVT_STRUCT_NAME)); \
_variant_type_set(tsuite_event_mapping_type_str_get(EVT_TYPE), \
&v->t, EINA_FALSE); \
memcpy(v->data, &INFO, sizeof(EVT_STRUCT_NAME)); \
vr_list->variant_list = eina_list_append(vr_list->variant_list, v); \
} \
} \
} while (0)
static int evas_list_find(void *ptr)
{ /* We just compare the pointers */
Eina_List *l;
void *data;
int n = 0;
EINA_LIST_FOREACH(evas_list, l, data)
{ /* Get the nuber of Evas Pointer */
if (ptr == data)
{
return n;
}
n++;
}
return -1;
}
static Tsuite_Event_Type
tsuite_event_type_get(Evas_Callback_Type t)
{
@ -877,7 +1086,7 @@ evas_event_feed_multi_down(Evas *e, int d, int x, int y,
#ifdef DEBUG_TSUITE
printf("Calling %s timestamp=<%u>\n", __func__, timestamp);
#endif
multi_event t = { d, x, y, rad, radx, rady, pres, ang,
multi_event t = { d, 0, x, y, rad, radx, rady, pres, ang,
fx, fy, flags, timestamp, evas_list_find(e)};
int evt = tsuite_event_type_get(EVAS_CALLBACK_MULTI_DOWN);
@ -902,7 +1111,7 @@ evas_event_feed_multi_up(Evas *e, int d, int x, int y,
#ifdef DEBUG_TSUITE
printf("Calling %s timestamp=<%u>\n", __func__, timestamp);
#endif
multi_event t = { d, x, y, rad, radx, rady, pres, ang, fx, fy, flags, timestamp, evas_list_find(e) };
multi_event t = { d, 0, x, y, rad, radx, rady, pres, ang, fx, fy, flags, timestamp, evas_list_find(e) };
int evt = tsuite_event_type_get(EVAS_CALLBACK_MULTI_UP);
if (t.n_evas >= 0)
ADD_TO_LIST(evt, multi_event, t);

View File

@ -681,6 +681,7 @@ multi_event_desc_make(void)
_d = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_event, "d", d, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_event, "b", b, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_event, "x", x, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_event, "y", y, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_event, "rad", rad, EET_T_DOUBLE);

View File

@ -147,6 +147,7 @@ struct _key_down_key_up_with_keycode
struct _multi_event
{
int d;
int b; /* In case of simple mouse down/up, corresponds to the button */
int x;
int y;
double rad;