Introduce a remote actions injection mechanism

By executing an application under the player (option
--external-injection), actions can be remotely forwarded.
The communication is done via Eina Debug channel. Therefore, efl_debugd
must be run before the application.
An injection tool has been implemented to show how to communicate with
the application.
This commit is contained in:
Daniel Zaoui 2018-03-20 00:04:44 +02:00
parent 0c30b92bc6
commit 9c3fe1b118
3 changed files with 767 additions and 50 deletions

View File

@ -1,6 +1,6 @@
MAINTAINERCLEANFILES = Makefile.in
bin_PROGRAMS = exactness exactness_inspect exactness_play exactness_record
bin_PROGRAMS = exactness exactness_inspect exactness_play exactness_record exactness_inject
exactness_SOURCES = exactness.c ../lib/tsuite_file_data.c ../lib/tsuite_common.c
@ -10,6 +10,8 @@ exactness_play_SOURCES = player.c ../lib/tsuite_file_data.c ../lib/tsuite_common
exactness_record_SOURCES = recorder.c ../lib/tsuite_file_data.c ../lib/tsuite_common.c ../lib/file.c
exactness_inject_SOURCES = injector.c ../lib/tsuite_file_data.c ../lib/file.c
exactness_LDADD = @EFL_LIBS@
exactness_inspect_LDADD = @EFL_LIBS@
@ -18,6 +20,8 @@ exactness_play_LDADD = @EFL_LIBS@
exactness_record_LDADD = @EFL_LIBS@
exactness_inject_LDADD = @EFL_LIBS@
exactness_CFLAGS = \
@EFL_CFLAGS@ \
-I$(top_srcdir)/src/lib \
@ -29,3 +33,6 @@ exactness_inspect_CFLAGS = @EFL_CFLAGS@ -I$(top_srcdir)/src/lib
exactness_play_CFLAGS = @EFL_CFLAGS@ -I$(top_srcdir)/src/lib
exactness_record_CFLAGS = @EFL_CFLAGS@ -I$(top_srcdir)/src/lib
exactness_inject_CFLAGS = @EFL_CFLAGS@ -I$(top_srcdir)/src/lib

464
src/bin/injector.c Normal file
View File

@ -0,0 +1,464 @@
#define _GNU_SOURCE 1
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <unistd.h>
#include "config.h"
#ifndef EFL_EO_API_SUPPORT
#define EFL_EO_API_SUPPORT
#endif
#include <Eina.h>
#include <Eet.h>
#include <Ecore.h>
#include <Ecore_Getopt.h>
#include <Elementary.h>
#include <Exactness.h>
#include "exactness_private.h"
typedef struct
{
Eina_Debug_Session *session;
int srcid;
void *buffer;
unsigned int size;
} _Main_Loop_Info;
#define WRAPPER_TO_XFER_MAIN_LOOP(foo) \
static void \
_intern_main_loop ## foo(void *data) \
{ \
_Main_Loop_Info *info = data; \
_main_loop ## foo(info->session, info->srcid, info->buffer, info->size); \
free(info->buffer); \
free(info); \
} \
static Eina_Bool \
foo(Eina_Debug_Session *session, int srcid, void *buffer, int size) \
{ \
_Main_Loop_Info *info = calloc(1, sizeof(*info)); \
info->session = session; \
info->srcid = srcid; \
info->size = size; \
if (info->size) \
{ \
info->buffer = malloc(info->size); \
memcpy(info->buffer, buffer, info->size); \
} \
ecore_main_loop_thread_safe_call_async(_intern_main_loop ## foo, info); \
return EINA_TRUE; \
}
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define SWAP_64(x) x
#define SWAP_32(x) x
#define SWAP_16(x) x
#define SWAP_DBL(x) x
#else
#define SWAP_64(x) eina_swap64(x)
#define SWAP_32(x) eina_swap32(x)
#define SWAP_16(x) eina_swap16(x)
#define SWAP_DBL(x) SWAP_64(x)
#endif
#define EXTRACT_INT(_buf) \
({ \
int __i; \
memcpy(&__i, _buf, sizeof(int)); \
_buf += sizeof(int); \
SWAP_32(__i); \
})
#define STORE_INT(_buf, __i) \
{ \
int __i2 = SWAP_32(__i); \
memcpy(_buf, &__i2, sizeof(int)); \
_buf += sizeof(int); \
}
#define STORE_DOUBLE(_buf, __d) \
{ \
double __d2 = SWAP_DBL(__d); \
memcpy(_buf, &__d2, sizeof(double)); \
_buf += sizeof(double); \
}
#define STORE_STRING(_buf, __s) \
{ \
int __len = (__s ? strlen(__s) : 0) + 1; \
if (__s) memcpy(_buf, __s, __len); \
else *_buf = '\0'; \
_buf += __len; \
}
static Eina_Stringshare *_src_filename = NULL;
static Exactness_Unit *_src_unit = NULL;
static int _verbose = 0;
static Eina_Debug_Session *_session = NULL;
static int _cid = -1, _pid = -1;
static Eina_List *_cur_event_list = NULL;
static unsigned int _last_event_time = 0;
static int _all_apps_get_op = EINA_DEBUG_OPCODE_INVALID;
static int _mouse_in_op = EINA_DEBUG_OPCODE_INVALID;
static int _mouse_out_op = EINA_DEBUG_OPCODE_INVALID;
static int _mouse_wheel_op = EINA_DEBUG_OPCODE_INVALID;
static int _multi_down_op = EINA_DEBUG_OPCODE_INVALID;
static int _multi_up_op = EINA_DEBUG_OPCODE_INVALID;
static int _multi_move_op = EINA_DEBUG_OPCODE_INVALID;
static int _key_down_op = EINA_DEBUG_OPCODE_INVALID;
static int _key_up_op = EINA_DEBUG_OPCODE_INVALID;
static int _take_shot_op = EINA_DEBUG_OPCODE_INVALID;
static int _finish_op = EINA_DEBUG_OPCODE_INVALID;
static Eina_Bool _all_apps_get_cb(Eina_Debug_Session *, int , void *, int);
EINA_DEBUG_OPCODES_ARRAY_DEFINE(_debug_ops,
{"Daemon/Client/register_observer", &_all_apps_get_op, NULL},
{"Daemon/Client/added", NULL, &_all_apps_get_cb},
{"Exactness/Actions/Mouse In", &_mouse_in_op, NULL},
{"Exactness/Actions/Mouse Out", &_mouse_out_op, NULL},
{"Exactness/Actions/Mouse Wheel", &_mouse_wheel_op, NULL},
{"Exactness/Actions/Multi Down", &_multi_down_op, NULL},
{"Exactness/Actions/Multi Up", &_multi_up_op, NULL},
{"Exactness/Actions/Multi Move", &_multi_move_op, NULL},
{"Exactness/Actions/Key Down", &_key_down_op, NULL},
{"Exactness/Actions/Key Up", &_key_up_op, NULL},
{"Exactness/Actions/Take Shot", &_take_shot_op, NULL},
{"Exactness/Actions/Finish", &_finish_op, NULL},
{NULL, NULL, NULL}
);
static void
_printf(int verbose, const char *fmt, ...)
{
va_list ap;
if (!_verbose || verbose > _verbose) return;
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
}
static void
_feed_event(Exactness_Action_Type type, unsigned int n_evas, void *data)
{
switch (type)
{
case EXACTNESS_ACTION_MOUSE_IN:
{
_printf(1, "Mouse in\n");
_printf(2, "%s evas_event_feed_mouse_in n_evas=<%d>\n", __func__, n_evas);
eina_debug_session_send(_session, _cid, _mouse_in_op, &n_evas, sizeof(int));
break;
}
case EXACTNESS_ACTION_MOUSE_OUT:
{
_printf(1, "Mouse out\n");
_printf(2, "%s evas_event_feed_mouse_out n_evas=<%d>\n", __func__, n_evas);
eina_debug_session_send(_session, _cid, _mouse_out_op, &n_evas, sizeof(int));
break;
}
case EXACTNESS_ACTION_MOUSE_WHEEL:
{
Exactness_Action_Mouse_Wheel *t = data;
int len = 3*sizeof(int);
char *buf = malloc(len), *tmp = buf;
_printf(1, "Mouse wheel\n");
_printf(2, "%s evas_event_feed_mouse_wheel n_evas=<%d>\n", __func__, n_evas);
STORE_INT(tmp, n_evas);
STORE_INT(tmp, t->direction);
STORE_INT(tmp, t->z);
eina_debug_session_send(_session, _cid, _mouse_wheel_op, buf, len);
break;
}
case EXACTNESS_ACTION_MULTI_DOWN:
case EXACTNESS_ACTION_MULTI_UP:
{
Exactness_Action_Multi_Event *t = data;
int len = 5*sizeof(int)+7*sizeof(double)+sizeof(int);
char *buf = malloc(len), *tmp = buf;
_printf(2, "%s %s n_evas=<%d>\n", __func__,
type == EXACTNESS_ACTION_MULTI_DOWN ? "evas_event_feed_multi_down" :
"evas_event_feed_multi_up", n_evas);
STORE_INT(tmp, n_evas);
STORE_INT(tmp, t->d);
STORE_INT(tmp, t->b);
STORE_INT(tmp, t->x);
STORE_INT(tmp, t->y);
STORE_DOUBLE(tmp, t->rad);
STORE_DOUBLE(tmp, t->radx);
STORE_DOUBLE(tmp, t->rady);
STORE_DOUBLE(tmp, t->pres);
STORE_DOUBLE(tmp, t->ang);
STORE_DOUBLE(tmp, t->fx);
STORE_DOUBLE(tmp, t->fy);
STORE_INT(tmp, t->flags);
eina_debug_session_send(_session, _cid,
type == EXACTNESS_ACTION_MULTI_DOWN ? _multi_down_op : _multi_up_op,
buf, len);
break;
}
case EXACTNESS_ACTION_MULTI_MOVE:
{
Exactness_Action_Multi_Move *t = data;
int len = 4*sizeof(int)+7*sizeof(double);
char *buf = malloc(len), *tmp = buf;
_printf(2, "%s evas_event_feed_multi_move n_evas=<%d>\n", __func__, n_evas);
STORE_INT(tmp, n_evas);
STORE_INT(tmp, t->d);
STORE_INT(tmp, t->x);
STORE_INT(tmp, t->y);
STORE_DOUBLE(tmp, t->rad);
STORE_DOUBLE(tmp, t->radx);
STORE_DOUBLE(tmp, t->rady);
STORE_DOUBLE(tmp, t->pres);
STORE_DOUBLE(tmp, t->ang);
STORE_DOUBLE(tmp, t->fx);
STORE_DOUBLE(tmp, t->fy);
eina_debug_session_send(_session, _cid, _multi_move_op, buf, len);
break;
}
case EXACTNESS_ACTION_KEY_DOWN:
case EXACTNESS_ACTION_KEY_UP:
{
Exactness_Action_Key_Down_Up *t = data;
int len = 2*sizeof(int) + 4;
len += t->keyname ? strlen(t->keyname) : 0;
len += t->key ? strlen(t->key) : 0;
len += t->string ? strlen(t->string) : 0;
len += t->compose ? strlen(t->compose) : 0;
char *buf = malloc(len), *tmp = buf;
_printf(2, "%s %s n_evas=<%d>\n", __func__,
type == EXACTNESS_ACTION_KEY_DOWN ? "evas_event_feed_key_down " :
"evas_event_feed_key_up", n_evas);
STORE_INT(tmp, n_evas);
STORE_STRING(tmp, t->keyname);
STORE_STRING(tmp, t->key);
STORE_STRING(tmp, t->string);
STORE_STRING(tmp, t->compose);
STORE_INT(tmp, t->keycode);
eina_debug_session_send(_session, _cid,
type == EXACTNESS_ACTION_KEY_DOWN ? _key_down_op : _key_up_op,
buf, len);
break;
}
case EXACTNESS_ACTION_TAKE_SHOT:
{
_printf(2, "%s take shot n_evas=<%d>\n", __func__, n_evas);
eina_debug_session_send(_session, _cid, _take_shot_op, &n_evas, sizeof(int));
break;
}
default: /* All non-input events are not handeled */
break;
}
}
static Eina_Bool
_feed_event_timer_cb(void *data EINA_UNUSED)
{
Exactness_Action *act = eina_list_data_get(_cur_event_list);
_feed_event(act->type, act->n_evas, act->data);
time_t evt_time = act->timestamp;
_cur_event_list = eina_list_next(_cur_event_list);
if (!_cur_event_list)
{ /* Finished reading all events */
eina_debug_session_send(_session, _cid, _finish_op, NULL, 0);
ecore_main_loop_quit();
}
else
{
double timer_time;
Exactness_Action *cur_act = eina_list_data_get(_cur_event_list);
unsigned int current_event_time = cur_act->timestamp;
_last_event_time = evt_time;
if (current_event_time < _last_event_time) /* Could happen with refeed event */
current_event_time = _last_event_time;
_printf(2, " %s _last_event_time=<%u> current_event_time=<%u>\n", __func__, _last_event_time, current_event_time);
timer_time = (current_event_time - _last_event_time) / 1000.0;
if (!_last_event_time) timer_time = 0.0;
_printf(2, " %s timer_time=<%f>\n", __func__, timer_time);
ecore_timer_add(timer_time, _feed_event_timer_cb, NULL);
}
return ECORE_CALLBACK_CANCEL;
}
static Eina_Bool
_src_open()
{
double diff_time = 0; /* Time to wait before feeding the first event */
_printf(2, "<%s> Source file is <%s>\n", __func__, _src_filename);
if (!strcmp(_src_filename + strlen(_src_filename) - 4,".exu"))
{
_src_unit = exactness_unit_file_read(_src_filename);
}
else if (!strcmp(_src_filename + strlen(_src_filename) - 4,".rec"))
{
_src_unit = legacy_rec_file_read(_src_filename);
}
if (!_src_unit) return EINA_FALSE;
_cur_event_list = _src_unit->actions;
Exactness_Action *act = eina_list_data_get(_cur_event_list);
/* Calculate the time to wait before feeding the first event */
unsigned int current_event_time = act->timestamp;
_printf(2, "%s current_event_time=<%u>\n", __func__, current_event_time);
if (current_event_time)
{
_printf(2, " Waiting <%f>\n", diff_time);
ecore_timer_add(current_event_time / 1000.0, _feed_event_timer_cb, NULL);
}
else
{
_feed_event_timer_cb(NULL);
}
return EINA_TRUE;
}
static void
_main_loop_all_apps_get_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
{
char *buf = buffer;
int chosen_cid = -1;
if (_cid != -1) return;
while (size > 0)
{
int cid, pid, len;
cid = EXTRACT_INT(buf);
pid = EXTRACT_INT(buf);
if (_pid != -1)
{
if (_pid == pid)
{
_cid = cid;
_src_open();
return;
}
}
else
{
if (!strcmp(buf, "exactness_play"))
{
if (chosen_cid != -1)
{
fprintf(stderr, "Need to specify a PID - too much choice\n");
return;
}
chosen_cid = cid;
}
}
len = strlen(buf) + 1;
buf += len;
size -= (2 * sizeof(int) + len);
}
if (chosen_cid != -1)
{
_cid = chosen_cid;
_src_open();
}
}
WRAPPER_TO_XFER_MAIN_LOOP(_all_apps_get_cb)
static void
_ops_ready_cb(void *data EINA_UNUSED, Eina_Bool status)
{
static Eina_Bool on = EINA_FALSE;
if (status)
{
if (!on)
{
eina_debug_session_send(_session, 0, _all_apps_get_op, NULL, 0);
}
on = EINA_TRUE;
}
}
static const Ecore_Getopt optdesc = {
"exactness_inject",
"%prog [options] <-v|-p|-t|-h> command",
PACKAGE_VERSION,
"(C) 2018 Enlightenment",
"BSD",
"A scenario events injector for EFL based applications.",
1,
{
ECORE_GETOPT_STORE_STR('t', "test", "Test to run on the given application"),
ECORE_GETOPT_STORE_INT('p', "pid", "PID of the application to connect to"),
ECORE_GETOPT_STORE_INT('r', "remote-port", "Port to connect remotely to the daemon. Local connection if not specified"),
ECORE_GETOPT_COUNT('v', "verbose", "Turn verbose messages on."),
ECORE_GETOPT_LICENSE('L', "license"),
ECORE_GETOPT_COPYRIGHT('C', "copyright"),
ECORE_GETOPT_VERSION('V', "version"),
ECORE_GETOPT_HELP('h', "help"),
ECORE_GETOPT_SENTINEL
}
};
int main(int argc, char **argv)
{
int opt_args = 0, real__, port = -1;
char *src = NULL;
Eina_Value *ret__;
Eina_Bool want_quit = EINA_FALSE;
Ecore_Getopt_Value values[] = {
ECORE_GETOPT_VALUE_STR(src),
ECORE_GETOPT_VALUE_INT(_pid),
ECORE_GETOPT_VALUE_INT(port),
ECORE_GETOPT_VALUE_INT(_verbose),
ECORE_GETOPT_VALUE_BOOL(want_quit),
ECORE_GETOPT_VALUE_BOOL(want_quit),
ECORE_GETOPT_VALUE_BOOL(want_quit),
ECORE_GETOPT_VALUE_BOOL(want_quit),
ECORE_GETOPT_VALUE_NONE
};
eina_init();
eet_init();
ecore_init();
opt_args = ecore_getopt_parse(&optdesc, values, argc, argv);
if (opt_args < 0)
{
fprintf(stderr, "Failed parsing arguments.\n");
goto end;
}
if (want_quit) goto end;
if (!src)
{
fprintf(stderr, "no test file specified\n");
goto end;
}
_src_filename = eina_stringshare_add(src);
if (port == -1)
_session = eina_debug_local_connect(EINA_TRUE);
else
_session = eina_debug_remote_connect(port);
eina_debug_opcodes_register(_session, _debug_ops(), _ops_ready_cb, NULL);
elm_init(argc, argv);
ret__ = efl_loop_begin(efl_main_loop_get());
real__ = efl_loop_exit_code_process(ret__);
elm_shutdown();
end:
eet_shutdown();
eina_shutdown();
return real__;
}

View File

@ -27,12 +27,82 @@
#define MAX_PATH 1024
#define IMAGE_FILENAME_EXT ".png"
typedef struct
{
Eina_Debug_Session *session;
int srcid;
void *buffer;
unsigned int size;
} _Main_Loop_Info;
#define WRAPPER_TO_XFER_MAIN_LOOP(foo) \
static void \
_intern_main_loop ## foo(void *data) \
{ \
_Main_Loop_Info *info = data; \
_main_loop ## foo(info->session, info->srcid, info->buffer, info->size); \
free(info->buffer); \
free(info); \
} \
static Eina_Bool \
foo(Eina_Debug_Session *session, int srcid, void *buffer, int size) \
{ \
_Main_Loop_Info *info = calloc(1, sizeof(*info)); \
info->session = session; \
info->srcid = srcid; \
info->size = size; \
if (info->size) \
{ \
info->buffer = malloc(info->size); \
memcpy(info->buffer, buffer, info->size); \
} \
ecore_main_loop_thread_safe_call_async(_intern_main_loop ## foo, info); \
return EINA_TRUE; \
}
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define SWAP_64(x) x
#define SWAP_32(x) x
#define SWAP_16(x) x
#define SWAP_DBL(x) x
#else
#define SWAP_64(x) eina_swap64(x)
#define SWAP_32(x) eina_swap32(x)
#define SWAP_16(x) eina_swap16(x)
#define SWAP_DBL(x) SWAP_64(x)
#endif
#define EXTRACT_INT(_buf) \
({ \
int __i; \
memcpy(&__i, _buf, sizeof(int)); \
_buf += sizeof(int); \
SWAP_32(__i); \
})
#define EXTRACT_DOUBLE(_buf) \
({ \
double __d; \
memcpy(&__d, _buf, sizeof(double)); \
_buf += sizeof(double); \
SWAP_DBL(__d); \
})
#define EXTRACT_STRING(_buf) \
({ \
char *__s = _buf ? strdup(_buf) : NULL; \
int __len = (__s ? strlen(__s) : 0) + 1; \
_buf += __len; \
__s; \
})
typedef enum
{
FTYPE_UNKNOWN,
FTYPE_DIR,
FTYPE_REC = FTYPE_DIR,
FTYPE_EXU
FTYPE_EXU,
FTYPE_REMOTE
} File_Type;
static File_Type _dest_type = FTYPE_UNKNOWN;
@ -170,17 +240,15 @@ _shot_do(Evas *e)
}
}
static Eina_Bool
_feed_event(void *data EINA_UNUSED)
static void
_feed_event(Exactness_Action_Type type, unsigned int n_evas, void *data)
{
static Evas_Object *rect = NULL;
static unsigned int rect_evas;
Exactness_Action *act = eina_list_data_get(_cur_event_list);
Eo *e = eina_list_nth(_evas_list, act->n_evas);
time_t evt_time = act->timestamp;
Eo *e = eina_list_nth(_evas_list, n_evas);
if (rect && rect_evas != act->n_evas)
if (rect && rect_evas != n_evas)
{
efl_del(rect);
rect = NULL;
@ -193,38 +261,38 @@ _feed_event(void *data EINA_UNUSED)
evas_object_resize(rect, 15, 15);
evas_object_layer_set(rect, 100);
evas_object_show(rect);
rect_evas = act->n_evas;
rect_evas = n_evas;
}
switch (act->type)
switch (type)
{
case EXACTNESS_ACTION_MOUSE_IN:
{
_printf(1, "Mouse in\n");
_printf(2, "%s evas_event_feed_mouse_in timestamp=<%u> n_evas=<%d>\n", __func__, act->timestamp, act->n_evas);
_printf(2, "%s evas_event_feed_mouse_in n_evas=<%d>\n", __func__, n_evas);
if (e) evas_event_feed_mouse_in(e, time(NULL), NULL);
break;
}
case EXACTNESS_ACTION_MOUSE_OUT:
{
_printf(1, "Mouse out\n");
_printf(2, "%s evas_event_feed_mouse_out timestamp=<%u> n_evas=<%d>\n", __func__, act->timestamp,act->n_evas);
_printf(2, "%s evas_event_feed_mouse_out n_evas=<%d>\n", __func__, n_evas);
if (e) evas_event_feed_mouse_out(e, time(NULL), NULL);
break;
}
case EXACTNESS_ACTION_MOUSE_WHEEL:
{
Exactness_Action_Mouse_Wheel *t = act->data;
Exactness_Action_Mouse_Wheel *t = data;
_printf(1, "Mouse wheel\n");
_printf(2, "%s evas_event_feed_mouse_wheel timestamp=<%u> n_evas=<%d>\n", __func__, act->timestamp, act->n_evas);
_printf(2, "%s evas_event_feed_mouse_wheel n_evas=<%d>\n", __func__, n_evas);
if (e) evas_event_feed_mouse_wheel(e, t->direction, t->z, time(NULL), NULL);
break;
}
case EXACTNESS_ACTION_MULTI_DOWN:
{
Exactness_Action_Multi_Event *t = act->data;
_printf(2, "%s evas_event_feed_multi_down timestamp=<%u>, n_evas=<%d>\n", __func__, act->timestamp, act->n_evas);
Exactness_Action_Multi_Event *t = data;
_printf(2, "%s evas_event_feed_multi_down n_evas=<%d>\n", __func__, n_evas);
if (!t->d)
{
if (e) evas_event_feed_mouse_down(e, t->b, t->flags, time(NULL), NULL);
@ -242,8 +310,8 @@ _feed_event(void *data EINA_UNUSED)
}
case EXACTNESS_ACTION_MULTI_UP:
{
Exactness_Action_Multi_Event *t = act->data;
_printf(2, "%s evas_event_feed_multi_up timestamp=<%u> n_evas=<%d>\n", __func__, act->timestamp,act->n_evas);
Exactness_Action_Multi_Event *t = data;
_printf(2, "%s evas_event_feed_multi_up n_evas=<%d>\n", __func__, n_evas);
if (!t->d)
{
if (e) evas_event_feed_mouse_up(e, t->b, t->flags, time(NULL), NULL);
@ -261,8 +329,8 @@ _feed_event(void *data EINA_UNUSED)
}
case EXACTNESS_ACTION_MULTI_MOVE:
{
Exactness_Action_Multi_Move *t = act->data;
_printf(2, "%s evas_event_feed_multi_move timestamp=<%u> n_evas=<%d>\n", __func__, act->timestamp, act->n_evas);
Exactness_Action_Multi_Move *t = data;
_printf(2, "%s evas_event_feed_multi_move n_evas=<%d>\n", __func__, n_evas);
if (!t->d)
{
if (e) evas_event_feed_mouse_move(e, t->x, t->y, time(NULL), NULL);
@ -284,8 +352,8 @@ _feed_event(void *data EINA_UNUSED)
}
case EXACTNESS_ACTION_KEY_DOWN:
{
Exactness_Action_Key_Down_Up *t = act->data;
_printf(2, "%s evas_event_feed_key_down timestamp=<%u> n_evas=<%d>\n", __func__, act->timestamp, act->n_evas);
Exactness_Action_Key_Down_Up *t = data;
_printf(2, "%s evas_event_feed_key_down n_evas=<%d>\n", __func__, n_evas);
if (e)
evas_event_feed_key_down_with_keycode(e,
t->keyname, t->key, t->string,
@ -294,8 +362,8 @@ _feed_event(void *data EINA_UNUSED)
}
case EXACTNESS_ACTION_KEY_UP:
{
Exactness_Action_Key_Down_Up *t = act->data;
_printf(2, "%s evas_event_feed_key_up timestamp=<%u> n_evas=<%d>\n", __func__, act->timestamp, act->n_evas);
Exactness_Action_Key_Down_Up *t = data;
_printf(2, "%s evas_event_feed_key_up n_evas=<%d>\n", __func__, n_evas);
if (e) evas_event_feed_key_up_with_keycode(e,
t->keyname, t->key, t->string,
t->compose, time(NULL), NULL, t->keycode);
@ -304,7 +372,7 @@ _feed_event(void *data EINA_UNUSED)
}
case EXACTNESS_ACTION_TAKE_SHOT:
{
_printf(2, "%s take shot timestamp=<%u> n_evas=<%d>\n", __func__, act->timestamp, act->n_evas);
_printf(2, "%s take shot n_evas=<%d>\n", __func__, n_evas);
if (rect) evas_object_color_set(rect, 0, 0, 255, 255);
_cur_shot_id++;
if (_dest_type != FTYPE_UNKNOWN && e) _shot_do(e);
@ -313,6 +381,14 @@ _feed_event(void *data EINA_UNUSED)
default: /* All non-input events are not handeled */
break;
}
}
static Eina_Bool
_feed_event_timer_cb(void *data EINA_UNUSED)
{
Exactness_Action *act = eina_list_data_get(_cur_event_list);
_feed_event(act->type, act->n_evas, act->data);
time_t evt_time = act->timestamp;
_cur_event_list = eina_list_next(_cur_event_list);
@ -336,13 +412,170 @@ _feed_event(void *data EINA_UNUSED)
if (!_last_event_time) timer_time = 0.0;
_printf(2, " %s timer_time=<%f>\n", __func__, timer_time);
ecore_timer_add(timer_time, _feed_event, NULL);
ecore_timer_add(timer_time, _feed_event_timer_cb, NULL);
}
return ECORE_CALLBACK_CANCEL;
}
static void
_main_loop_mouse_in_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
{
char *buf = buffer;
int n_evas = EXTRACT_INT(buf);
_feed_event(EXACTNESS_ACTION_MOUSE_IN, n_evas, NULL);
}
static void
_main_loop_mouse_out_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
{
char *buf = buffer;
int n_evas = EXTRACT_INT(buf);
_feed_event(EXACTNESS_ACTION_MOUSE_OUT, n_evas, NULL);
}
static void
_main_loop_mouse_wheel_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
{
char *buf = buffer;
Exactness_Action_Mouse_Wheel t;
int n_evas = EXTRACT_INT(buf);
t.direction = EXTRACT_INT(buf);
t.z = EXTRACT_INT(buf);
_feed_event(EXACTNESS_ACTION_MOUSE_WHEEL, n_evas, &t);
}
static void
_main_loop_multi_down_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
{
char *buf = buffer;
Exactness_Action_Multi_Event t;
int n_evas = EXTRACT_INT(buf);
t.d = EXTRACT_INT(buf);
t.b = EXTRACT_INT(buf);
t.x = EXTRACT_INT(buf);
t.y = EXTRACT_INT(buf);
t.rad = EXTRACT_DOUBLE(buf);
t.radx = EXTRACT_DOUBLE(buf);
t.rady = EXTRACT_DOUBLE(buf);
t.pres = EXTRACT_DOUBLE(buf);
t.ang = EXTRACT_DOUBLE(buf);
t.fx = EXTRACT_DOUBLE(buf);
t.fy = EXTRACT_DOUBLE(buf);
t.flags = EXTRACT_INT(buf);
_feed_event(EXACTNESS_ACTION_MULTI_DOWN, n_evas, &t);
}
static void
_main_loop_multi_up_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
{
char *buf = buffer;
Exactness_Action_Multi_Event t;
int n_evas = EXTRACT_INT(buf);
t.d = EXTRACT_INT(buf);
t.b = EXTRACT_INT(buf);
t.x = EXTRACT_INT(buf);
t.y = EXTRACT_INT(buf);
t.rad = EXTRACT_DOUBLE(buf);
t.radx = EXTRACT_DOUBLE(buf);
t.rady = EXTRACT_DOUBLE(buf);
t.pres = EXTRACT_DOUBLE(buf);
t.ang = EXTRACT_DOUBLE(buf);
t.fx = EXTRACT_DOUBLE(buf);
t.fy = EXTRACT_DOUBLE(buf);
t.flags = EXTRACT_INT(buf);
_feed_event(EXACTNESS_ACTION_MULTI_UP, n_evas, &t);
}
static void
_main_loop_multi_move_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
{
char *buf = buffer;
Exactness_Action_Multi_Move t;
int n_evas = EXTRACT_INT(buf);
t.d = EXTRACT_INT(buf);
t.x = EXTRACT_INT(buf);
t.y = EXTRACT_INT(buf);
t.rad = EXTRACT_DOUBLE(buf);
t.radx = EXTRACT_DOUBLE(buf);
t.rady = EXTRACT_DOUBLE(buf);
t.pres = EXTRACT_DOUBLE(buf);
t.ang = EXTRACT_DOUBLE(buf);
t.fx = EXTRACT_DOUBLE(buf);
t.fy = EXTRACT_DOUBLE(buf);
_feed_event(EXACTNESS_ACTION_MULTI_MOVE, n_evas, &t);
}
static void
_main_loop_key_down_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
{
char *buf = buffer;
Exactness_Action_Key_Down_Up t;
int n_evas = EXTRACT_INT(buf);
t.keyname = EXTRACT_STRING(buf);
t.key = EXTRACT_STRING(buf);
t.string = EXTRACT_STRING(buf);
t.compose = EXTRACT_STRING(buf);
t.keycode = EXTRACT_INT(buf);
_feed_event(EXACTNESS_ACTION_KEY_DOWN, n_evas, &t);
}
static void
_main_loop_key_up_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
{
char *buf = buffer;
Exactness_Action_Key_Down_Up t;
int n_evas = EXTRACT_INT(buf);
t.keyname = EXTRACT_STRING(buf);
t.key = EXTRACT_STRING(buf);
t.string = EXTRACT_STRING(buf);
t.compose = EXTRACT_STRING(buf);
t.keycode = EXTRACT_INT(buf);
_feed_event(EXACTNESS_ACTION_KEY_UP, n_evas, &t);
}
static void
_main_loop_take_shot_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
{
char *buf = buffer;
int n_evas = EXTRACT_INT(buf);
_feed_event(EXACTNESS_ACTION_TAKE_SHOT, n_evas, NULL);
}
static void
_main_loop_finish_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer EINA_UNUSED, int size EINA_UNUSED)
{
ecore_main_loop_quit();
}
WRAPPER_TO_XFER_MAIN_LOOP(_mouse_in_cb)
WRAPPER_TO_XFER_MAIN_LOOP(_mouse_out_cb)
WRAPPER_TO_XFER_MAIN_LOOP(_mouse_wheel_cb)
WRAPPER_TO_XFER_MAIN_LOOP(_multi_down_cb)
WRAPPER_TO_XFER_MAIN_LOOP(_multi_up_cb)
WRAPPER_TO_XFER_MAIN_LOOP(_multi_move_cb)
WRAPPER_TO_XFER_MAIN_LOOP(_key_down_cb)
WRAPPER_TO_XFER_MAIN_LOOP(_key_up_cb)
WRAPPER_TO_XFER_MAIN_LOOP(_take_shot_cb)
WRAPPER_TO_XFER_MAIN_LOOP(_finish_cb)
EINA_DEBUG_OPCODES_ARRAY_DEFINE(_debug_ops,
{"Exactness/Actions/Mouse In", NULL, &_mouse_in_cb},
{"Exactness/Actions/Mouse Out", NULL, &_mouse_out_cb},
{"Exactness/Actions/Mouse Wheel", NULL, &_mouse_wheel_cb},
{"Exactness/Actions/Multi Down", NULL, &_multi_down_cb},
{"Exactness/Actions/Multi Up", NULL, &_multi_up_cb},
{"Exactness/Actions/Multi Move", NULL, &_multi_move_cb},
{"Exactness/Actions/Key Down", NULL, &_key_down_cb},
{"Exactness/Actions/Key Up", NULL, &_key_up_cb},
{"Exactness/Actions/Take Shot", NULL, &_take_shot_cb},
{"Exactness/Actions/Finish", NULL, &_finish_cb},
{NULL, NULL, NULL}
);
static Eina_Bool
_src_open()
{
if (_src_type != FTYPE_REMOTE)
{
double diff_time = 0; /* Time to wait before feeding the first event */
_printf(2, "<%s> Source file is <%s>\n", __func__, _src_filename);
@ -366,11 +599,16 @@ _src_open()
if (current_event_time)
{
_printf(2, " Waiting <%f>\n", diff_time);
ecore_timer_add(current_event_time / 1000.0, _feed_event, NULL);
ecore_timer_add(current_event_time / 1000.0, _feed_event_timer_cb, NULL);
}
else
{
_feed_event(NULL);
_feed_event_timer_cb(NULL);
}
}
else
{
eina_debug_opcodes_register(NULL, _debug_ops(), NULL, NULL);
}
return EINA_TRUE;
}
@ -516,6 +754,7 @@ static const Ecore_Getopt optdesc = {
ECORE_GETOPT_STORE_STR('t', "test", "Test to run on the given application"),
ECORE_GETOPT_STORE_TRUE('s', "show-on-screen", "Show on screen."),
ECORE_GETOPT_STORE_TRUE(0, "scan-objects", "Extract information of all the objects at every shot."),
ECORE_GETOPT_STORE_TRUE(0, "external-injection", "Expect events injection via Eina debug channel."),
ECORE_GETOPT_COUNT('v', "verbose", "Turn verbose messages on."),
ECORE_GETOPT_LICENSE('L', "license"),
@ -531,13 +770,14 @@ int main(int argc, char **argv)
int pret = 1, opt_args = 0;
char *src = NULL, *dest = NULL, *eq;
Eina_Bool show_on_screen = EINA_FALSE;
Eina_Bool want_quit = EINA_FALSE;
Eina_Bool want_quit = EINA_FALSE, external_injection = EINA_FALSE;
Ecore_Getopt_Value values[] = {
ECORE_GETOPT_VALUE_STR(dest),
ECORE_GETOPT_VALUE_STR(src),
ECORE_GETOPT_VALUE_BOOL(show_on_screen),
ECORE_GETOPT_VALUE_BOOL(_scan_objects),
ECORE_GETOPT_VALUE_BOOL(external_injection),
ECORE_GETOPT_VALUE_INT(_verbose),
ECORE_GETOPT_VALUE_BOOL(want_quit),
@ -598,12 +838,18 @@ int main(int argc, char **argv)
}
}
}
if (!src)
if (!src && !external_injection)
{
fprintf(stderr, "no test file specified\n");
goto end;
}
else
if (src && external_injection)
{
fprintf(stderr, "Cannot inject events from a source file and from outside simultaneously\n");
goto end;
}
if (external_injection) _src_type = FTYPE_REMOTE;
if (src)
{
_src_filename = eina_stringshare_add(src);
if (!strcmp(_src_filename + strlen(_src_filename) - 4,".exu"))
@ -669,7 +915,7 @@ int main(int argc, char **argv)
if (_dest && _dest_unit)
{
_dest_unit->actions = _src_unit->actions;
if (_src_unit) _dest_unit->actions = _src_unit->actions;
exactness_unit_file_write(_dest_unit, _dest);
}