Compare commits

...

8 Commits

Author SHA1 Message Date
Stefan Schmidt 580b73d1fd TO BE REVERTED. JUST FOR FASTER TESTING. 2020-01-31 14:17:09 +01:00
Stefan Schmidt 6872bb7ef2 ci:travis: add build job for exactness 2020-01-31 14:16:39 +01:00
Stefan Schmidt 87a7252912 exactness: cleanup some coding style isues
Just a few that I spotted when looking over the code.
2020-01-31 14:14:01 +01:00
Stefan Schmidt 3def8bf571 exactness: fix shutdown handling of efl components in various binaries
The shutdown handling for efl libraries was a bit sloppy in the
exactness binaries. Make sure we shutdown what we init.
2020-01-31 14:14:01 +01:00
Stefan Schmidt 5ba73b0107 exactness: remove unused code
Either commented out, blank lines or no needed includes.
2020-01-31 14:14:01 +01:00
Stefan Schmidt 9f85df4d2e exactnes: remove no longer needed EO and BETA APi defines 2020-01-31 14:14:01 +01:00
Stefan Schmidt ba0983849a exactness: print out statistics at the end of the run
Given a better overview after the wall of text we are seeing from
starting and stopping jobs in parallel.

Differential Revision: https://phab.enlightenment.org/D11122
2020-01-31 14:14:01 +01:00
Daniel Zaoui 9a8078cb79 Exactness: code importation
Differential Revision: https://phab.enlightenment.org/D7590
2020-01-31 14:14:01 +01:00
16 changed files with 7273 additions and 12 deletions

View File

@ -32,6 +32,11 @@ if [ "$DISTRO" != "" ] ; then
if [ $tries != ${NUM_TRIES} ] ; then echo "tests failed, trying again!" ; fi
false
done
if [ "$1" = "exactness" ] ; then
docker exec --env EIO_MONITOR_POLL=1 $(cat $HOME/cid) sh -c 'cd /; git clone https://git.enlightenment.org/tools/exactness-elm-data.git' # How should we cache this?
docker exec --env EIO_MONITOR_POLL=1 $(cat $HOME/cid) sh -c 'cd /exactness-elm-data; git checkout origin/devs/stefan/init-shots-docker-travis-ci -b docker'
docker exec --env EIO_MONITOR_POLL=1 --env LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib:/usr/local/lib64 --env EINA_LOG_LEVELS_GLOB=eina_*:0,ecore*:0,efreet*:0,eldbus:0,elementary:0 $(cat $HOME/cid) exactness -j 20 -b /exactness-elm-data/default-profile -p /exactness-elm-data/default-profile/tests.txt
fi
fi
ret=$?
travis_endfold check

View File

@ -48,6 +48,8 @@ jobs:
- os: osx
- os: linux
env: DISTRO=Fedora31-mingw CI_BUILD_TYPE=mingw
- os: linux
env: DISTRO=Fedora31 CI_BUILD_TYPE=exactness
- os: linux
env: DISTRO=Fedora31 CI_BUILD_TYPE=options-enabled
- os: linux
@ -126,15 +128,3 @@ before_cache:
else
mv $HOME/Library/Caches/Homebrew $HOME/cachedir/Homebrew
fi
notifications:
irc:
channels:
- "chat.freenode.net#edevelop"
on_success: change
on_failure: always
template:
- "TravisCI build %{build_number} in branch %{branch}: %{result} - %{message} (%{elapsed_time})"
- "Commit: %{commit_subject} (%{commit}) from %{author}"
- "Change view : %{compare_url}"
- "Build details : %{build_url}"

View File

@ -335,6 +335,7 @@ subprojects = [
['elua' ,['elua'] , false, true, true, false, true, false, ['eina', 'luajit'], []],
['ecore_wayland' ,['wl-deprecated'] , false, true, false, false, false, false, ['eina'], []],
['ecore_drm' ,['drm-deprecated'] , false, true, false, false, false, false, ['eina'], []],
['exactness' ,[] , false, true, true, false, false, false, ['eina, evas, eet'], []],
]
# We generate Efl_Config.h and config.h later, they will be available here

5
src/bin/exactness/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
/exactness
/exactness_inject
/exactness_inspect
/exactness_play
/exactness_record

View File

@ -0,0 +1,675 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Ecore.h>
#include <Ecore_Getopt.h>
#include <Ecore_Evas.h>
#include <Ecore_File.h>
#include "exactness_private.h"
#ifdef _WIN32
# include <evil_private.h> /* mkdir */
#endif
#define SCHEDULER_CMD_SIZE 1024
#define ORIG_SUBDIR "orig"
#define CURRENT_SUBDIR "current"
#define EXACTNESS_PATH_MAX 1024
#define BUF_SIZE 1024
typedef struct
{
EINA_INLIST;
char *name;
const char *command;
} List_Entry;
typedef enum
{
RUN_SIMULATION,
RUN_PLAY,
RUN_INIT
} Run_Mode;
static unsigned short _running_jobs = 0, _max_jobs = 1;
static Eina_List *_base_dirs = NULL;
static char *_dest_dir;
static char *_wrap_command = NULL, *_fonts_dir = NULL;
static int _verbose = 0;
static Eina_Bool _scan_objs = EINA_FALSE, _disable_screenshots = EINA_FALSE, _stabilize_shots = EINA_FALSE;
static Run_Mode _mode;
static List_Entry *_next_test_to_run = NULL;
static unsigned int _tests_executed = 0;
static Eina_List *_errors;
static Eina_List *_compare_errors;
static Eina_Bool _job_consume();
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 Exactness_Image *
_image_load(const char *filename)
{
int w, h;
Evas_Load_Error err;
Ecore_Evas *ee = ecore_evas_new(NULL, 0, 0, 100, 100, NULL);
Eo *e = ecore_evas_get(ee);
Eo *img = evas_object_image_add(e);
evas_object_image_file_set(img, filename, NULL);
err = evas_object_image_load_error_get(img);
if (err != EVAS_LOAD_ERROR_NONE)
{
fprintf(stderr, "could not load image '%s'. error string is \"%s\"\n",
filename, evas_load_error_str(err));
return NULL;
}
Exactness_Image *ex_img = malloc(sizeof(*ex_img));
int len;
evas_object_image_size_get(img, &w, &h);
ex_img->w = w;
ex_img->h = h;
len = w * h * 4;
ex_img->pixels = malloc(len);
memcpy(ex_img->pixels, evas_object_image_data_get(img, EINA_FALSE), len);
ecore_evas_free(ee);
return ex_img;
}
static void
_image_save(Exactness_Image *ex_img, const char *output)
{
Ecore_Evas *ee;
Eo *e, *img;
ee = ecore_evas_new(NULL, 0, 0, 100, 100, NULL);
e = ecore_evas_get(ee);
img = evas_object_image_add(e);
evas_object_image_size_set(img, ex_img->w, ex_img->h);
evas_object_image_data_set(img, ex_img->pixels);
evas_object_image_save(img, output, NULL, NULL);
ecore_evas_free(ee);
}
static Eina_Bool
_file_compare(const char *orig_dir, const char *ent_name)
{
Eina_Bool result = EINA_FALSE;
Exactness_Image *img1, *img2, *imgO = NULL;
char *filename1 = alloca(strlen(orig_dir) + strlen(ent_name) + 20);
char *filename2 = alloca(strlen(_dest_dir) + strlen(ent_name) + 20);
sprintf(filename1, "%s/%s", orig_dir, ent_name);
sprintf(filename2, "%s/%s/%s", _dest_dir, CURRENT_SUBDIR, ent_name);
img1 = _image_load(filename1);
img2 = _image_load(filename2);
if (exactness_image_compare(img1, img2, &imgO))
{
char *buf = alloca(strlen(_dest_dir) + strlen(ent_name));
sprintf(buf, "%s/%s/comp_%s", _dest_dir, CURRENT_SUBDIR, ent_name);
_image_save(imgO, buf);
_compare_errors = eina_list_append(_compare_errors, strdup(ent_name));
result = EINA_TRUE;
}
exactness_image_free(img1);
exactness_image_free(img2);
exactness_image_free(imgO);
return result;
}
static void
_exu_imgs_unpack(const char *exu_path, const char *dir, const char *ent_name)
{
Exactness_Unit *unit = exactness_unit_file_read(exu_path);
Exactness_Image *img;
Eina_List *itr;
Ecore_Evas *ee = ecore_evas_new(NULL, 0, 0, 100, 100, NULL);
Eo *e = ecore_evas_get(ee);
int n = 1;
if (!unit) return;
EINA_LIST_FOREACH(unit->imgs, itr, img)
{
Eo *o = evas_object_image_add(e);
char *filename = alloca(strlen(dir) + strlen(ent_name) + 20);
snprintf(filename, EXACTNESS_PATH_MAX, "%s/%s%c%.3d.png",
dir, ent_name, SHOT_DELIMITER, n++);
evas_object_image_size_set(o, img->w, img->h);
evas_object_image_data_set(o, img->pixels);
if (!evas_object_image_save(o, filename, NULL, NULL))
{
printf("Cannot save widget to <%s>\n", filename);
}
efl_del(o);
}
efl_del(e);
ecore_evas_free(ee);
}
static void
_run_test_compare(const List_Entry *ent)
{
char *path = alloca(EXACTNESS_PATH_MAX);
char *origdir = alloca(strlen(_dest_dir) + 20);
const char *base_dir;
Eina_List *itr;
int n = 1, nb_fails = 0;
printf("STATUS %s: COMPARE\n", ent->name);
EINA_LIST_FOREACH(_base_dirs, itr, base_dir)
{
sprintf(path, "%s/%s.exu", base_dir, ent->name);
if (ecore_file_exists(path))
{
char *currentdir;
sprintf(origdir, "%s/%s/%s", _dest_dir, CURRENT_SUBDIR, ORIG_SUBDIR);
mkdir(origdir, 0744);
_exu_imgs_unpack(path, origdir, ent->name);
sprintf(path, "%s/%s/%s.exu", _dest_dir, CURRENT_SUBDIR, ent->name);
currentdir = alloca(strlen(_dest_dir) + 20);
sprintf(currentdir, "%s/%s", _dest_dir, CURRENT_SUBDIR);
_exu_imgs_unpack(path, currentdir, ent->name);
goto found;
}
else
{
sprintf(path, "%s/%s.rec", base_dir, ent->name);
if (ecore_file_exists(path))
{
sprintf(origdir, "%s/%s", _dest_dir, ORIG_SUBDIR);
goto found;
}
}
}
found:
do
{
sprintf(path, "%s/%s%c%.3d.png", origdir, ent->name, SHOT_DELIMITER, n);
if (ecore_file_exists(path))
{
sprintf(path, "%s%c%.3d.png", ent->name, SHOT_DELIMITER, n);
if (_file_compare(origdir, path)) nb_fails++;
}
else break;
n++;
} while (EINA_TRUE);
if (!nb_fails)
printf("STATUS %s: END - SUCCESS\n", ent->name);
else
printf("STATUS %s: END - FAIL (%d/%d)\n", ent->name, nb_fails, n - 1);
}
#define CONFIG "ELM_SCALE=1 ELM_FINGER_SIZE=10 "
static Eina_Bool
_run_command_prepare(const List_Entry *ent, char *buf)
{
char scn_path[EXACTNESS_PATH_MAX];
Eina_Strbuf *sbuf;
const char *base_dir;
Eina_List *itr;
Eina_Bool is_exu;
EINA_LIST_FOREACH(_base_dirs, itr, base_dir)
{
is_exu = EINA_TRUE;
sprintf(scn_path, "%s/%s.exu", base_dir, ent->name);
if (ecore_file_exists(scn_path)) goto ok;
else
{
is_exu = EINA_FALSE;
sprintf(scn_path, "%s/%s.rec", base_dir, ent->name);
if (ecore_file_exists(scn_path)) goto ok;
}
}
fprintf(stderr, "Test %s not found in the provided base directories\n", ent->name);
return EINA_FALSE;
ok:
sbuf = eina_strbuf_new();
printf("STATUS %s: START\n", ent->name);
eina_strbuf_append_printf(sbuf,
"%s exactness_play %s %s%s %s%.*s %s%s%s-t '%s' ",
_wrap_command ? _wrap_command : "",
_mode == RUN_SIMULATION ? "-s" : "",
_fonts_dir ? "-f " : "", _fonts_dir ? _fonts_dir : "",
_verbose ? "-" : "", _verbose, "vvvvvvvvvv",
_scan_objs ? "--scan-objects " : "",
_disable_screenshots ? "--disable-screenshots " : "",
_stabilize_shots ? "--stabilize-shots " : "",
scn_path
);
if (is_exu)
{
if (_mode == RUN_PLAY)
eina_strbuf_append_printf(sbuf, "-o '%s/%s/%s.exu' ", _dest_dir, CURRENT_SUBDIR, ent->name);
if (_mode == RUN_INIT)
eina_strbuf_append_printf(sbuf, "-o '%s' ", scn_path);
}
else
{
if (_mode == RUN_PLAY)
eina_strbuf_append_printf(sbuf, "-o '%s/%s' ", _dest_dir, CURRENT_SUBDIR);
if (_mode == RUN_INIT)
eina_strbuf_append_printf(sbuf, "-o '%s/%s' ", _dest_dir, ORIG_SUBDIR);
}
if (ent->command)
{
eina_strbuf_append(sbuf, "-- ");
eina_strbuf_append(sbuf, CONFIG);
eina_strbuf_append(sbuf, ent->command);
}
strncpy(buf, eina_strbuf_string_get(sbuf), SCHEDULER_CMD_SIZE-1);
eina_strbuf_free(sbuf);
_printf(1, "Command: %s\n", buf);
return EINA_TRUE;
}
static void
_job_compare(void *data)
{
_run_test_compare(data);
_running_jobs--;
_job_consume();
/* If all jobs are done. */
if (!_running_jobs) ecore_main_loop_quit();
}
static Eina_Bool
_job_deleted_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
Ecore_Exe_Event_Del *msg = (Ecore_Exe_Event_Del *) event;
List_Entry *ent = ecore_exe_data_get(msg->exe);
if ((msg->exit_code != 0) || (msg->exit_signal != 0))
{
_errors = eina_list_append(_errors, ent);
}
if (_mode == RUN_PLAY)
{
ecore_job_add(_job_compare, ent);
}
else
{
_running_jobs--;
_job_consume();
if (!_running_jobs) ecore_main_loop_quit();
}
return ECORE_CALLBACK_RENEW;
}
static Eina_Bool
_job_consume()
{
static Ecore_Event_Handler *job_del_callback_handler = NULL;
char buf[SCHEDULER_CMD_SIZE];
List_Entry *ent = _next_test_to_run;
if (_running_jobs == _max_jobs) return EINA_FALSE;
if (!ent) return EINA_FALSE;
if (_run_command_prepare(ent, buf))
{
_running_jobs++;
_tests_executed++;
if (!job_del_callback_handler)
{
job_del_callback_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
_job_deleted_cb, NULL);
}
if (!ecore_exe_pipe_run(buf, ECORE_EXE_TERM_WITH_PARENT, ent))
{
fprintf(stderr, "Failed executing test '%s'\n", ent->name);
}
}
_next_test_to_run = EINA_INLIST_CONTAINER_GET(
EINA_INLIST_GET(ent)->next, List_Entry);
return EINA_TRUE;
}
static void
_scheduler_run()
{
while (_job_consume());
}
static List_Entry *
_list_file_load(const char *filename)
{
List_Entry *ret = NULL;
char buf[BUF_SIZE] = "";
FILE *file;
file = fopen(filename, "r");
if (!file)
{
perror("Failed opening list file");
return NULL;
}
while (fgets(buf, BUF_SIZE, file))
{
/* Skip comment/empty lines. */
if ((*buf == '#') || (*buf == '\n') || (!*buf))
continue;
char *tmp;
List_Entry *cur = calloc(1, sizeof(*cur));
cur->name = strdup(buf);
/* Set the command to the second half and put a \0 in between. */
tmp = strchr(cur->name, ' ');
if (tmp)
{
*tmp = '\0';
cur->command = tmp + 1;
}
else
{
/* FIXME: error. */
cur->command = "";
}
/* Replace the newline char with a \0. */
tmp = strchr(cur->command, '\n');
if (tmp)
{
*tmp = '\0';
}
ret = EINA_INLIST_CONTAINER_GET(
eina_inlist_append(EINA_INLIST_GET(ret), EINA_INLIST_GET(cur)),
List_Entry);
}
return ret;
}
static void
_list_file_free(List_Entry *list)
{
while (list)
{
List_Entry *ent = list;
list = EINA_INLIST_CONTAINER_GET(EINA_INLIST_GET(list)->next,
List_Entry);
free(ent->name);
free(ent);
/* we don't free ent->command because it's allocated together. */
}
}
static int
_errors_sort_cb(List_Entry *a, List_Entry *b)
{
return strcmp(a->name, b->name);
}
static const Ecore_Getopt optdesc = {
"exactness",
"%prog [options] <-r|-p|-i|-s> <list file>",
PACKAGE_VERSION,
"(C) 2013 Enlightenment",
"BSD",
"A pixel perfect test suite for EFL based applications.",
0,
{
ECORE_GETOPT_APPEND('b', "base-dir", "The location of the exu/rec files.", ECORE_GETOPT_TYPE_STR),
ECORE_GETOPT_STORE_STR('o', "output", "The location of the images."),
ECORE_GETOPT_STORE_STR('w', "wrap", "Use a custom command to launch the tests (e.g valgrind)."),
ECORE_GETOPT_STORE_USHORT('j', "jobs", "The number of jobs to run in parallel."),
ECORE_GETOPT_STORE_TRUE('p', "play", "Run in play mode."),
ECORE_GETOPT_STORE_TRUE('i', "init", "Run in init mode."),
ECORE_GETOPT_STORE_TRUE('s', "simulation", "Run in simulation mode."),
ECORE_GETOPT_STORE_TRUE(0, "scan-objects", "Extract information of all the objects at every shot."),
ECORE_GETOPT_STORE_TRUE(0, "disable-screenshots", "Disable screenshots."),
ECORE_GETOPT_STORE_STR('f', "fonts-dir", "Specify a directory of the fonts that should be used."),
ECORE_GETOPT_STORE_TRUE(0, "stabilize-shots", "Wait for the frames to be stable before taking the shots."),
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 ret = 0;
List_Entry *test_list;
int args = 0;
const char *list_file;
Eina_List *itr;
const char *base_dir;
char tmp[EXACTNESS_PATH_MAX];
Eina_Bool mode_play = EINA_FALSE, mode_init = EINA_FALSE, mode_simulation = EINA_FALSE;
Eina_Bool want_quit = EINA_FALSE, scan_objs = EINA_FALSE;
Ecore_Getopt_Value values[] = {
ECORE_GETOPT_VALUE_LIST(_base_dirs),
ECORE_GETOPT_VALUE_STR(_dest_dir),
ECORE_GETOPT_VALUE_STR(_wrap_command),
ECORE_GETOPT_VALUE_USHORT(_max_jobs),
ECORE_GETOPT_VALUE_BOOL(mode_play),
ECORE_GETOPT_VALUE_BOOL(mode_init),
ECORE_GETOPT_VALUE_BOOL(mode_simulation),
ECORE_GETOPT_VALUE_BOOL(scan_objs),
ECORE_GETOPT_VALUE_BOOL(_disable_screenshots),
ECORE_GETOPT_VALUE_STR(_fonts_dir),
ECORE_GETOPT_VALUE_BOOL(_stabilize_shots),
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
};
ecore_init();
ecore_evas_init();
evas_init();
_dest_dir = "./";
_scan_objs = scan_objs;
args = ecore_getopt_parse(&optdesc, values, argc, argv);
if (args < 0)
{
fprintf(stderr, "Failed parsing arguments.\n");
ret = 1;
goto end;
}
else if (want_quit)
{
ret = 1;
goto end;
}
else if (args == argc)
{
fprintf(stderr, "Expected test list as the last argument..\n");
ecore_getopt_help(stderr, &optdesc);
ret = 1;
goto end;
}
else if (mode_play + mode_init + mode_simulation != 1)
{
fprintf(stderr, "At least and only one of the running modes can be set.\n");
ecore_getopt_help(stderr, &optdesc);
ret = 1;
goto end;
}
if (!_base_dirs) _base_dirs = eina_list_append(NULL, "./recordings");
list_file = argv[args];
/* Load the list file and start iterating over the records. */
test_list = _list_file_load(list_file);
_next_test_to_run = test_list;
if (!test_list)
{
fprintf(stderr, "No matching tests found in '%s'\n", list_file);
ret = 1;
goto end;
}
/* Pre-run summary */
fprintf(stderr, "Running with settings:\n");
fprintf(stderr, "\tConcurrent jobs: %d\n", _max_jobs);
fprintf(stderr, "\tTest list: %s\n", list_file);
fprintf(stderr, "\tBase dirs:\n");
EINA_LIST_FOREACH(_base_dirs, itr, base_dir)
fprintf(stderr, "\t\t%s\n", base_dir);
fprintf(stderr, "\tDest dir: %s\n", _dest_dir);
if (mode_play)
{
_mode = RUN_PLAY;
if (snprintf(tmp, EXACTNESS_PATH_MAX, "%s/%s", _dest_dir, CURRENT_SUBDIR)
>= EXACTNESS_PATH_MAX)
{
fprintf(stderr, "Path too long: %s", tmp);
ret = 1;
goto end;
}
mkdir(tmp, 0744);
}
else if (mode_init)
{
_mode = RUN_INIT;
if (snprintf(tmp, EXACTNESS_PATH_MAX, "%s/%s", _dest_dir, ORIG_SUBDIR)
>= EXACTNESS_PATH_MAX)
{
fprintf(stderr, "Path too long: %s", tmp);
ret = 1;
goto end;
}
mkdir(tmp, 0744);
}
else if (mode_simulation)
{
_mode = RUN_SIMULATION;
}
_scheduler_run();
ecore_main_loop_begin();
/* Results */
printf("*******************************************************\n");
if (mode_play && EINA_FALSE)
{
List_Entry *list_itr;
EINA_INLIST_FOREACH(test_list, list_itr)
{
_run_test_compare(list_itr);
}
}
printf("Finished executing %u out of %u tests.\n",
_tests_executed,
eina_inlist_count(EINA_INLIST_GET(test_list)));
printf("%u tests executed\n", _tests_executed);
printf("%u tests had execution errors\n", eina_list_count(_errors));
printf("%u screenshots failed comparison\n", eina_list_count(_compare_errors));
/* Sort the errors and the compare_errors. */
_errors = eina_list_sort(_errors, 0, (Eina_Compare_Cb) _errors_sort_cb);
_compare_errors = eina_list_sort(_compare_errors, 0, (Eina_Compare_Cb) strcmp);
if (_errors || _compare_errors)
{
FILE *report_file;
char report_filename[EXACTNESS_PATH_MAX] = "";
/* Generate the filename. */
snprintf(report_filename, EXACTNESS_PATH_MAX,
"%s/%s/errors.html",
_dest_dir, mode_init ? ORIG_SUBDIR : CURRENT_SUBDIR);
report_file = fopen(report_filename, "w+");
if (report_file)
{
fprintf(report_file,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"
"<html xmlns=\"http://www.w3.org/1999/xhtml\"><head><title>Exactness report</title></head><body>");
if (_errors)
{
fprintf(report_file,
"<h1>Tests that failed execution:</h1><ul>");
List_Entry *ent;
printf("List of tests that failed execution:\n");
EINA_LIST_FOREACH(_errors, itr, ent)
{
printf("\t* %s\n", ent->name);
fprintf(report_file, "<li>%s</li>", ent->name);
}
fprintf(report_file, "</ul>");
}
if (_compare_errors)
{
fprintf(report_file,
"<h1>Images that failed comparison: (Original, Current, Diff)</h1><ul>");
char *test_name;
printf("List of images that failed comparison:\n");
EINA_LIST_FREE(_compare_errors, test_name)
{
Eina_Bool is_from_exu;
char origpath[EXACTNESS_PATH_MAX];
snprintf(origpath, EXACTNESS_PATH_MAX, "%s/%s/orig/%s",
_dest_dir, CURRENT_SUBDIR, test_name);
is_from_exu = ecore_file_exists(origpath);
printf("\t* %s\n", test_name);
fprintf(report_file, "<li><h2>%s</h2> <img src='%sorig/%s' alt='Original' /> <img src='%s' alt='Current' /> <img src='comp_%s' alt='Diff' /></li>",
test_name, is_from_exu ? "" : "../",
test_name, test_name, test_name);
free(test_name);
}
fprintf(report_file, "</ul>");
}
fprintf(report_file,
"</body></html>");
printf("Report html: %s\n", report_filename);
ret = 1;
}
else
{
perror("Failed opening report file");
}
}
_list_file_free(test_list);
end:
evas_shutdown();
ecore_evas_shutdown();
ecore_shutdown();
return ret;
}

View File

@ -0,0 +1,471 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <unistd.h>
#include <Eina.h>
#include <Eet.h>
#include <Ecore.h>
#include <Ecore_Getopt.h>
#include <Elementary.h>
#include <Exactness.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; \
}
#ifndef WORDS_BIGENDIAN
#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 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 _efl_event_op = EINA_DEBUG_OPCODE_INVALID;
static int _click_on_op = EINA_DEBUG_OPCODE_INVALID;
static int _stabilize_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/EFL Event", &_efl_event_op, NULL},
{"Exactness/Actions/Click On", &_click_on_op, NULL},
{"Exactness/Actions/Stabilize", &_stabilize_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;
}
case EXACTNESS_ACTION_EFL_EVENT:
{
Exactness_Action_Efl_Event *t = data;
int len = 0;
len += t->wdg_name ? strlen(t->wdg_name) : 0;
len += t->event_name ? strlen(t->event_name) : 0;
char *buf = malloc(len), *tmp = buf;
_printf(2, "%s %s\n", __func__, "EFL event");
STORE_STRING(tmp, t->wdg_name);
STORE_STRING(tmp, t->event_name);
eina_debug_session_send(_session, _cid, _efl_event_op, buf, len);
break;
}
case EXACTNESS_ACTION_CLICK_ON:
{
Exactness_Action_Click_On *t = data;
int len = 0;
len += t->wdg_name ? strlen(t->wdg_name) : 0;
char *buf = malloc(len), *tmp = buf;
_printf(2, "%s %s\n", __func__, "Click On");
STORE_STRING(tmp, t->wdg_name);
eina_debug_session_send(_session, _cid, _click_on_op, buf, len);
break;
}
case EXACTNESS_ACTION_STABILIZE:
{
_printf(2, "%s stabilize\n", __func__);
eina_debug_session_send(_session, _cid, _stabilize_op, NULL, 0);
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);
_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
{
Exactness_Action *cur_act = eina_list_data_get(_cur_event_list);
ecore_timer_add(cur_act->delay_ms / 1000.0, _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);
if (act->delay_ms)
{
_printf(2, " Waiting <%f>\n", diff_time);
ecore_timer_add(act->delay_ms / 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)
{
if (status)
eina_debug_session_send(_session, 0, _all_apps_get_op, NULL, 0);
}
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__ = 1, 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:
ecore_shutdown();
eet_shutdown();
eina_shutdown();
return real__;
}

1649
src/bin/exactness/inspect.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,42 @@
exactness_bin = executable('exactness',
[ 'exactness.c' ],
dependencies: [ ecore, ecore_evas, ecore_file, exactness ],
install: true,
)
exactness_inject_bin = executable('exactness_inject',
[ 'injector.c' ],
dependencies: [ elementary, exactness ],
install: true,
)
exactness_inspect_bin = executable('exactness_inspect',
[ 'inspect.c' ],
dependencies: [ elementary, exactness ],
install: true,
)
edjs = custom_target('player_entry',
input : 'player_entry.edc',
output : 'player_entry.edj',
install : true,
install_dir : 'share/exactness',
command : edje_cc_exe + [
'-id', join_paths(meson.source_root(), 'data', 'elementary', 'themes', 'img'),
'-sd', join_paths(meson.source_root(), 'data', 'elementary', 'themes', 'snd'),
'@INPUT@', '@OUTPUT@'],
depends : edje_cc)
exactness_play_bin = executable('exactness_play',
[ 'player.c', edjs ],
dependencies: [ elementary, exactness ],
c_args: '-DDATA_DIR="'+join_paths(dir_data, 'exactness')+'"',
install: true,
)
exactness_record_bin = executable('exactness_record',
[ 'recorder.c' ],
dependencies: [ elementary, exactness ],
install: true,
)

1369
src/bin/exactness/player.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,932 @@
collections {
#include "../../../data/elementary/themes/fonts.edc"
group { name: "elm/entry/cursor/default";
min: 1 0;
images.image: "white_bar_vert_glow.png" COMP;
parts {
part { name: "cursor"; mouse_events: 0;
clip_to: "clipper";
description { state: "default" 0.0;
rel1.offset: -4 -4;
rel2.offset: 3 3;
image.normal: "white_bar_vert_glow.png";
image.border: 4 4 4 4;
fill.smooth: 0;
color: 255 255 255 0;
color_class: "entry_cursor";
min: 9 10;
}
description { state: "visible" 0.0;
inherit: "default" 0.0;
color: 255 255 255 255;
}
}
part { name: "clipper"; type: RECT;
description { state: "default" 0.0;
rel1.to: "cursor";
rel2.to: "cursor";
fixed: 1 1;
}
description { state: "hidden" 0.0;
inherit: "default" 0.0;
visible: 0;
}
}
}
programs {
program {
signal: "selection,changed"; source: "elm.text";
action: STATE_SET "hidden" 0.0;
target: "clipper";
}
program {
signal: "selection,cleared"; source: "elm.text";
action: STATE_SET "default" 0.0;
target: "clipper";
}
program {
signal: "selection,reset"; source: "elm.text";
action: STATE_SET "default" 0.0;
target: "clipper";
}
program {
signal: "elm,action,focus"; source: "elm";
action: ACTION_STOP;
target: "cursor_show";
target: "cursor_hide";
target: "cursor_show_timer";
target: "cursor_hide_timer";
after: "cursor_show";
}
program {
signal: "elm,action,unfocus"; source: "elm";
action: ACTION_STOP;
target: "cursor_show";
target: "cursor_hide";
target: "cursor_show_timer";
target: "cursor_hide_timer";
after: "cursor_hide_stop";
}
program {
signal: "elm,action,show,cursor"; source: "elm";
action: ACTION_STOP;
target: "cursor_show";
target: "cursor_hide";
target: "cursor_show_timer";
target: "cursor_hide_timer";
after: "cursor_show";
}
program { name: "cursor_hide_stop";
action: STATE_SET "default" 0.0;
target: "cursor";
}
program { name: "cursor_show";
action: STATE_SET "default" 0.0;
target: "cursor";
after: "cursor_show_timer";
}
program { name: "cursor_hide";
action: STATE_SET "default" 0.0;
target: "cursor";
transition: SINUSOIDAL 0.2;
after: "cursor_hide_timer";
}
program { name: "cursor_show_timer";
in: 0.5 0.0;
after: "cursor_hide";
}
program { name: "cursor_hide_timer";
in: 0.2 0.0;
after: "cursor_show";
}
}
}
group { name: "elm/entry/selection/default";
parts {
part { name: "base"; type: RECT;
description { state: "default" 0.0;
color: 51 153 255 255;
}
}
}
}
group { name: "elm/entry/anchor/default";
images.image: "horizontal_separated_bar_small_glow.png" COMP;
parts {
part { name: "bar";
description { state: "default" 0.0;
image.normal: "horizontal_separated_bar_small_glow.png";
image.border: 4 4 4 4;
fill.smooth: 0;
fixed: 0 1;
rel1.relative: 0.0 1.0;
rel1.offset: -3 -5;
rel2.offset: 2 4;
}
}
}
}
group { name: "elm/entry/base/default";
sounds {
sample { name: "key-tap1" LOSSY 64;
source: "kbd-tap.wav";
}
sample { name: "key-tap2" LOSSY 64;
source: "kbd-tap2.wav";
}
sample { name: "key-tap3" LOSSY 64;
source: "kbd-tap3.wav";
}
sample { name: "key-tap4" LOSSY 64;
source: "kbd-tap4.wav";
}
sample { name: "key-tap5" LOSSY 64;
source: "kbd-tap5.wav";
}
}
styles {
style { name: "entry_style";
base: "font="FN" font_size=10 color=#ffffff style=shadow,bottom shadow_color=#00000080 wrap=word text_class=entry_text color_class=entry_text left_margin=2 right_margin=2";
ENABLED_TEXTBLOCK_TAGS
}
style { name: "entry_nowrap_style";
base: "font="FN" font_size=10 color=#ffffff style=shadow,bottom shadow_color=#00000080 text_class=entry_text color_class=entry_text left_margin=2 right_margin=2";
ENABLED_TEXTBLOCK_TAGS
}
style { name: "entry_disabled_style";
base: "font="FN" font_size=10 color=#151515 style=shadow,bottom shadow_color=#ffffff19 wrap=word text_class=entry_text_disabled color_class=entry_text_disabled left_margin=2 right_margin=2";
DISABLED_TEXTBLOCK_TAGS
}
style { name: "entry_nowrap_disabled_style";
base: "font="FN" font_size=10 color=#151515 style=shadow,bottom shadow_color=#ffffff19 text_class=entry_text_disabled color_class=entry_text_disabled left_margin=2 right_margin=2";
DISABLED_TEXTBLOCK_TAGS
}
style { name: "entry_guide_style";
base: "font="FN" font_size=10 color=#000000 style=shadow,bottom shadow_color=#ffffff19 wrap=word text_class=entry_guide_text color_class=entry_guide_text left_margin=2 right_margin=2 ellipsis=0.0";
DISABLED_TEXTBLOCK_TAGS
}
}
// data.item: "context_menu_orientation" "horizontal";
parts {
part { name: "elm.swallow.background"; type: SWALLOW;
description { state: "default" 0.0;
rel1.offset: 1 1;
rel2.offset: -2 -2;
}
}
part { name: "elm.guide"; type: TEXTBLOCK; mouse_events: 0;
scale: 1;
description { state: "default" 0.0;
rel1.to: "elm.text";
rel2.to: "elm.text";
text { style: "entry_guide_style";
min: 0 1;
align: 0.0 0.0;
}
}
description { state: "hidden" 0.0;
inherit: "default" 0.0;
visible: 0;
}
}
part { name: "elm.text"; type: TEXTBLOCK;
scale: 1;
entry_mode: EDITABLE;
select_mode: DEFAULT;
// select_mode: EXPLICIT;
cursor_mode: BEFORE;
multiline: 1;
source: "elm/entry/selection/default"; // selection under
// source2: "X"; // selection over
// source3: "X"; // cursor under
source4: "elm/entry/cursor/default"; // cursorover
// source5: "elm/entry/anchor/default"; // anchor under
source6: "elm/entry/anchor/default"; // anchor over
description { state: "default" 0.0;
/* we gotta use 0 0 here, because of scrolled entries */
fixed: 0 0;
rel1.offset: 2 2;
rel2.offset: -3 -3;
text { style: "entry_style";
min: 0 1;
align: 0.0 0.0;
}
}
description { state: "disabled" 0.0;
inherit: "default" 0.0;
text { style: "entry_disabled_style";
min: 0 1;
}
}
}
}
programs {
program {
signal: "load"; source: "";
action: FOCUS_SET;
target: "elm.text";
}
program {
signal: "elm,state,disabled"; source: "elm";
action: STATE_SET "disabled" 0.0;
target: "elm.text";
}
program {
signal: "elm,state,enabled"; source: "elm";
action: STATE_SET "default" 0.0;
target: "elm.text";
}
program {
signal: "elm,guide,disabled"; source: "elm";
action: STATE_SET "hidden" 0.0;
target: "elm.guide";
}
program {
signal: "elm,guide,enabled"; source: "elm";
action: STATE_SET "default" 0.0;
target: "elm.guide";
}
program { name: "key-down";
signal: "entry,keydown"; source: "elm.text";
script {
new buf[32];
snprintf(buf, 31, "key-down%i", (rand() % 5) + 1);
run_program(get_program_id(buf));
}
}
program { name: "key-down1";
action: PLAY_SAMPLE "key-tap1" 1.0 INPUT;
}
program { name: "key-down2";
action: PLAY_SAMPLE "key-tap2" 1.0 INPUT;
}
program { name: "key-down3";
action: PLAY_SAMPLE "key-tap3" 1.0 INPUT;
}
program { name: "key-down4";
action: PLAY_SAMPLE "key-tap4" 1.0 INPUT;
}
program { name: "key-down5";
action: PLAY_SAMPLE "key-tap5" 1.0 INPUT;
}
}
}
group { name: "elm/entry/base-mixedwrap/default";
inherit: "elm/entry/base/default";
styles {
style { name: "entry_style_mixedwrap";
base: "font="FN" font_size=10 color=#ffffff style=shadow,bottom shadow_color=#00000080 wrap=mixed text_class=entry_text color_class=entry_text left_margin=2 right_margin=2";
ENABLED_TEXTBLOCK_TAGS
}
style { name: "entry_disabled_style_mixedwrap";
base: "font="FN" font_size=10 color=#151515 style=shadow,bottom shadow_color=#ffffff19 wrap=mixed text_class=entry_text_disabled color_class=entry_text_disabled left_margin=2 right_margin=2";
DISABLED_TEXTBLOCK_TAGS
}
style { name: "entry_guide_style_mixedwrap";
base: "font="FN" font_size=10 color=#000000 style=shadow,bottom shadow_color=#ffffff19 wrap=mixed text_class=entry_guide_text color_class=entry_guide_text left_margin=2 right_margin=2 ellipsis=0.0";
DISABLED_TEXTBLOCK_TAGS
}
}
parts {
part { name: "elm.guide"; type: TEXTBLOCK; mouse_events: 0;
scale: 1;
description { state: "default" 0.0;
rel1.to: "elm.text";
rel2.to: "elm.text";
text { style: "entry_guide_style_mixedwrap";
min: 0 1;
align: 0.0 0.0;
}
}
description { state: "hidden" 0.0;
inherit: "default" 0.0;
visible: 0;
}
}
part { name: "elm.text";
description { state: "default" 0.0;
fixed: 1 0;
text { style: "entry_style_mixedwrap";
min: 0 1;
align: 0.0 0.0;
}
}
description { state: "disabled" 0.0;
inherit: "default" 0.0;
text { style: "entry_disabled_style_mixedwrap";
min: 0 1;
}
}
}
}
}
group { name: "elm/entry/base-charwrap/default";
inherit: "elm/entry/base/default";
styles {
style { name: "entry_style_charwrap";
base: "font="FN" font_size=10 color=#ffffff style=shadow,bottom shadow_color=#00000080 wrap=char text_class=entry_text color_class=entry_text left_margin=2 right_margin=2";
ENABLED_TEXTBLOCK_TAGS
}
style { name: "entry_disabled_style_charwrap";
base: "font="FN" font_size=10 color=#151515 style=shadow,bottom shadow_color=#ffffff19 wrap=char text_class=entry_text_disabled color_class=entry_text_disabled left_margin=2 right_margin=2";
DISABLED_TEXTBLOCK_TAGS
}
style { name: "entry_guide_style_charwrap";
base: "font="FN" font_size=10 color=#000000 style=shadow,bottom shadow_color=#ffffff19 wrap=char text_class=entry_guide_text color_class=entry_guide_text left_margin=2 right_margin=2 ellipsis=0.0";
DISABLED_TEXTBLOCK_TAGS
}
}
parts {
part { name: "elm.guide"; type: TEXTBLOCK; mouse_events: 0;
scale: 1;
description { state: "default" 0.0;
rel1.to: "elm.text";
rel2.to: "elm.text";
text { style: "entry_guide_style_charwrap";
min: 0 1;
align: 0.0 0.0;
}
}
description { state: "hidden" 0.0;
inherit: "default" 0.0;
visible: 0;
}
}
part { name: "elm.text";
description { state: "default" 0.0;
fixed: 1 1;
text { style: "entry_style_charwrap";
min: 0 1;
align: 0.0 0.0;
}
}
description { state: "disabled" 0.0;
inherit: "default" 0.0;
text { style: "entry_disabled_style_charwrap";
min: 0 1;
}
}
}
}
}
group { name: "elm/entry/base-nowrap/default";
inherit: "elm/entry/base/default";
parts {
part { name: "elm.guide"; type: TEXTBLOCK; mouse_events: 0;
scale: 1;
description { state: "default" 0.0;
rel1.to: "elm.text";
rel2.to: "elm.text";
text { style: "entry_guide_style";
min: 0 1;
align: 0.0 0.0;
}
}
description { state: "hidden" 0.0;
inherit: "default" 0.0;
visible: 0;
}
}
part { name: "elm.text";
description { state: "default" 0.0;
text { style: "entry_nowrap_style";
min: 1 1;
ellipsis: -1;
align: 0.0 0.0;
}
}
description { state: "disabled" 0.0;
inherit: "default" 0.0;
text { style: "entry_nowrap_disabled_style";
min: 0 1;
}
}
}
}
}
group { name: "elm/entry/base-single/default";
inherit: "elm/entry/base/default";
styles {
style { name: "entry_single_style";
base: "font="FN" font_size=10 color=#ffffff style=shadow,bottom shadow_color=#00000080 wrap=none text_class=entry_text color_class=entry_text left_margin=2 right_margin=2";
ENABLED_TEXTBLOCK_TAGS
}
style { name: "entry_single_disabled_style";
base: "font="FN" font_size=10 color=#151515 style=shadow,bottom shadow_color=#ffffff19 wrap=none text_class=entry_text_disabled color_class=entry_text_disabled left_margin=2 right_margin=2";
DISABLED_TEXTBLOCK_TAGS
}
style { name: "entry_single_guide_style";
base: "font="FN" font_size=10 color=#000000 style=shadow,bottom shadow_color=#ffffff19 wrap=none text_class=entry_guide_text color_class=entry_guide_text left_margin=2 right_margin=2 ellipsis=0.0";
DISABLED_TEXTBLOCK_TAGS
}
}
parts {
part { name: "elm.guide"; type: TEXTBLOCK; mouse_events: 0;
scale: 1;
description { state: "default" 0.0;
rel1.to: "elm.text";
rel2.to: "elm.text";
text { style: "entry_single_guide_style";
min: 0 1;
align: 0.0 0.5;
}
}
description { state: "hidden" 0.0;
inherit: "default" 0.0;
visible: 0;
}
}
part { name: "elm.text";
multiline: 0;
description { state: "default" 0.0;
text { style: "entry_single_style";
min: 1 1;
ellipsis: -1;
max: 0 0;
align: 0.0 0.5;
}
}
description { state: "disabled" 0.0;
inherit: "default" 0.0;
text { style: "entry_single_disabled_style";
}
}
}
}
}
group { name: "elm/entry/base-single/spinner/default";
alias: "elm/entry/base-single/spinner/vertical";
inherit: "elm/entry/base-single/default";
styles {
style { name: "entry_single_spinner_style";
base: "font="FN" font_size=10 color=#ffffff style=shadow,bottom shadow_color=#00000080 align=center wrap=none text_class=entry_text color_class=entry_text left_margin=2 right_margin=2";
ENABLED_TEXTBLOCK_TAGS
}
}
parts {
part { name: "elm.text";
description { state: "default" 0.0;
text.style: "entry_single_spinner_style";
}
}
}
}
group { name: "elm/entry/base-single-noedit/default";
inherit: "elm/entry/base/default";
parts {
part { name: "elm.text";
entry_mode: PLAIN;
multiline: 0;
source: "elm/entry/selection/default"; // selection under
source4: ""; // cursorover
source6: "elm/entry/anchor/default"; // anchor over
description { state: "default" 0.0;
text { style: "entry_single_style";
min: 1 1;
ellipsis: -1;
max: 0 0;
align: 0.0 0.5;
}
}
description { state: "disabled" 0.0;
inherit: "default" 0.0;
text { style: "entry_single_disabled_style";
}
}
}
}
}
group { name: "elm/entry/base-noedit/default";
inherit: "elm/entry/base/default";
parts {
part { name: "elm.text";
entry_mode: PLAIN;
source: "elm/entry/selection/default"; // selection under
source4: ""; // cursorover
source6: "elm/entry/anchor/default"; // anchor over
description { state: "default" 0.0;
fixed: 1 0;
text { style: "entry_style";
min: 0 1;
align: 0.0 0.0;
}
}
description { state: "disabled" 0.0;
inherit: "default" 0.0;
text { style: "entry_disabled_style";
}
}
}
}
}
group { name: "elm/entry/base-noedit-mixedwrap/default";
inherit: "elm/entry/base/default";
parts {
part { name: "elm.text";
entry_mode: PLAIN;
source: "elm/entry/selection/default"; // selection under
source4: ""; // cursorover
source6: "elm/entry/anchor/default"; // anchor over
description { state: "default" 0.0;
fixed: 1 0;
text { style: "entry_style_mixedwrap";
min: 0 1;
align: 0.0 0.0;
}
}
description { state: "disabled" 0.0;
inherit: "default" 0.0;
text { style: "entry_disabled_style_mixedwrap";
}
}
}
}
}
group { name: "elm/entry/base-noedit-charwrap/default";
inherit: "elm/entry/base/default";
parts {
part { name: "elm.text";
entry_mode: PLAIN;
source: "elm/entry/selection/default"; // selection under
source4: ""; // cursorover
source6: "elm/entry/anchor/default"; // anchor under
description { state: "default" 0.0;
fixed: 1 0;
text { style: "entry_style_charwrap";
min: 0 1;
align: 0.0 0.0;
}
}
description { state: "disabled" 0.0;
inherit: "default" 0.0;
text { style: "entry_disabled_style_charwrap";
}
}
}
}
}
group { name: "elm/entry/base-nowrap-noedit/default";
inherit: "elm/entry/base/default";
parts {
part { name: "elm.text";
entry_mode: PLAIN;
source: "elm/entry/selection/default"; // selection under
source4: ""; // cursorover
source6: "elm/entry/anchor/default"; // anchor under
description { state: "default" 0.0;
text { style: "entry_style";
min: 1 1;
ellipsis: -1;
align: 0.0 0.0;
}
}
description { state: "disabled" 0.0;
inherit: "default" 0.0;
text { style: "entry_disabled_style";
}
}
}
}
}
group { name: "elm/entry/base-password/default";
inherit: "elm/entry/base/default";
parts {
part { name: "elm.guide"; type: TEXTBLOCK; mouse_events: 0;
scale: 1;
description { state: "default" 0.0;
rel1.to: "elm.text";
rel2.to: "elm.text";
text { style: "entry_single_guide_style";
min: 0 1;
align: 0.0 0.5;
}
}
description { state: "hidden" 0.0;
inherit: "default" 0.0;
visible: 0;
}
}
part { name: "elm.text";
entry_mode: PASSWORD;
multiline: 0;
source: "elm/entry/selection/default"; // selection under
source4: "elm/entry/cursor/default"; // cursorover
source6: "elm/entry/anchor/default"; // anchor under
description { state: "default" 0.0;
text { style: "entry_single_style";
repch: "*";
min: 1 1;
ellipsis: -1;
max: 0 0;
align: 0.0 0.5;
}
}
description { state: "disabled" 0.0;
inherit: "default" 0.0;
text { style: "entry_single_disabled_style";
}
}
}
}
}
group { name: "elm/entry/magnifier/default";
images.image: "frame_rounded.png" COMP;
parts {
part { name: "bg"; type: RECT; mouse_events: 0;
description { state: "default" 0.0;
rel1.offset: 10 10;
rel1.to: "over";
rel2.offset: -11 -11;
rel2.to: "over";
color: 48 48 48 255;
}
description { state: "hidden" 0.0;
inherit: "default" 0.0;
visible: 0;
}
}
part { name: "elm.swallow.content"; type: SWALLOW; mouse_events: 0;
description { state: "default" 0.0;
rel1.offset: 10 10;
rel1.to: "over";
rel2.offset: -11 -11;
rel2.to: "over";
}
description { state: "hidden" 0.0;
inherit: "default" 0.0;
visible: 0;
}
}
part { name: "over"; mouse_events: 0;
scale: 1;
description { state: "default" 0.0;
min: 128 64;
align: 0 0;
image.normal: "frame_rounded.png";
image.border: 14 14 14 14;
image.middle: 0;
fill.smooth: 0;
}
description { state: "hidden" 0.0;
inherit: "default" 0.0;
visible: 0;
}
}
}
programs {
program { name: "magnifier_show";
signal: "elm,action,show,magnifier"; source: "elm";
action: STATE_SET "default" 0.0;
target: "elm.swallow.content";
target: "bg";
target: "over";
}
program { name: "magnifier_hide";
signal: "elm,action,hide,magnifier"; source: "elm";
action: STATE_SET "hidden" 0.0;
target: "elm.swallow.content";
target: "bg";
target: "over";
}
}
}
group { name: "elm/entry/handler/start/default";
images.image: "handle_pick_up_left.png" COMP;
parts {
part { name: "base"; mouse_events: 0;
scale: 1;
description { state: "default" 0.0;
min: 21 27; // 42 54
image.normal: "handle_pick_up_left.png";
align: (29/42) (11/54);
color_class: "entry_selection_handler";
visible: 0;
}
description { state: "visible" 0.0;
inherit: "default" 0.0;
visible: 1;
}
}
part { name: "event"; type: RECT;
scale: 1;
description { state: "default" 0.0;
color: 0 0 0 0;
rel1.to: "base";
rel2.to: "base";
min: 32 32;
visible: 0;
}
description { state: "visible" 0.0;
inherit: "default" 0.0;
visible: 1;
}
}
}
programs {
program {
signal: "elm,handler,show"; source: "elm";
action: STATE_SET "visible" 0.0;
target: "base";
target: "event";
}
program {
signal: "elm,handler,hide"; source: "elm";
action: STATE_SET "default" 0.0;
target: "base";
target: "event";
}
}
}
group { name: "elm/entry/handler/end/default";
images.image: "handle_pick_up_right.png" COMP;
parts {
part { name: "base"; mouse_events: 0;
scale: 1;
description { state: "default" 0.0;
min: 21 27; // 42 54
image.normal: "handle_pick_up_right.png";
align: (12/42) (11/54);
color_class: "entry_selection_handler";
visible: 0;
}
description { state: "visible" 0.0;
inherit: "default" 0.0;
visible: 1;
}
}
part { name: "event"; type: RECT;
scale: 1;
description { state: "default" 0.0;
color: 0 0 0 0;
rel1.to: "base";
rel2.to: "base";
min: 32 32;
visible: 0;
}
description { state: "visible" 0.0;
inherit: "default" 0.0;
visible: 1;
}
}
}
programs {
program {
signal: "elm,handler,show"; source: "elm";
action: STATE_SET "visible" 0.0;
target: "base";
target: "event";
}
program {
signal: "elm,handler,hide"; source: "elm";
action: STATE_SET "default" 0.0;
target: "base";
target: "event";
}
}
}
///////////////////////////////////////////////////////////////////////////////
// emoticon images from:
// Tanya - Latvia
// http://lazycrazy.deviantart.com/
// http://lazycrazy.deviantart.com/art/Very-Emotional-Emoticons-144461621
group { name: "elm/entry/emoticon/angry/default"; images.image:
"emo-angry.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-angry.png"; } } } }
group { name: "elm/entry/emoticon/angry-shout/default"; images.image:
"emo-angry-shout.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-angry-shout.png"; } } } }
group { name: "elm/entry/emoticon/crazy-laugh/default"; images.image:
"emo-crazy-laugh.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-crazy-laugh.png"; } } } }
group { name: "elm/entry/emoticon/evil-laugh/default"; images.image:
"emo-evil-laugh.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-evil-laugh.png"; } } } }
group { name: "elm/entry/emoticon/evil/default"; images.image:
"emo-evil.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-evil.png"; } } } }
group { name: "elm/entry/emoticon/goggle-smile/default"; images.image:
"emo-goggle-smile.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-goggle-smile.png"; } } } }
group { name: "elm/entry/emoticon/grumpy/default"; images.image:
"emo-grumpy.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-grumpy.png"; } } } }
group { name: "elm/entry/emoticon/grumpy-smile/default"; images.image:
"emo-grumpy-smile.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-grumpy-smile.png"; } } } }
group { name: "elm/entry/emoticon/guilty/default"; images.image:
"emo-guilty.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-guilty.png"; } } } }
group { name: "elm/entry/emoticon/guilty-smile/default"; images.image:
"emo-guilty-smile.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-guilty-smile.png"; } } } }
group { name: "elm/entry/emoticon/haha/default"; images.image:
"emo-haha.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-haha.png"; } } } }
group { name: "elm/entry/emoticon/half-smile/default"; images.image:
"emo-half-smile.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-half-smile.png"; } } } }
group { name: "elm/entry/emoticon/happy-panting/default"; images.image:
"emo-happy-panting.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-happy-panting.png"; } } } }
group { name: "elm/entry/emoticon/happy/default"; images.image:
"emo-happy.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-happy.png"; } } } }
group { name: "elm/entry/emoticon/indifferent/default"; images.image:
"emo-indifferent.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-indifferent.png"; } } } }
group { name: "elm/entry/emoticon/kiss/default"; images.image:
"emo-kiss.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-kiss.png"; } } } }
group { name: "elm/entry/emoticon/knowing-grin/default"; images.image:
"emo-knowing-grin.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-knowing-grin.png"; } } } }
group { name: "elm/entry/emoticon/laugh/default"; images.image:
"emo-laugh.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-laugh.png"; } } } }
group { name: "elm/entry/emoticon/little-bit-sorry/default"; images.image:
"emo-little-bit-sorry.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-little-bit-sorry.png"; } } } }
group { name: "elm/entry/emoticon/love-lots/default"; images.image:
"emo-love-lots.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-love-lots.png"; } } } }
group { name: "elm/entry/emoticon/love/default"; images.image:
"emo-love.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-love.png"; } } } }
group { name: "elm/entry/emoticon/minimal-smile/default"; images.image:
"emo-minimal-smile.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-minimal-smile.png"; } } } }
group { name: "elm/entry/emoticon/not-happy/default"; images.image:
"emo-not-happy.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-not-happy.png"; } } } }
group { name: "elm/entry/emoticon/not-impressed/default"; images.image:
"emo-not-impressed.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-not-impressed.png"; } } } }
group { name: "elm/entry/emoticon/omg/default"; images.image:
"emo-omg.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-omg.png"; } } } }
group { name: "elm/entry/emoticon/opensmile/default"; images.image:
"emo-opensmile.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-opensmile.png"; } } } }
group { name: "elm/entry/emoticon/smile/default"; images.image:
"emo-smile.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-smile.png"; } } } }
group { name: "elm/entry/emoticon/sorry/default"; images.image:
"emo-sorry.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-sorry.png"; } } } }
group { name: "elm/entry/emoticon/squint-laugh/default"; images.image:
"emo-squint-laugh.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-squint-laugh.png"; } } } }
group { name: "elm/entry/emoticon/surprised/default"; images.image:
"emo-surprised.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-surprised.png"; } } } }
group { name: "elm/entry/emoticon/suspicious/default"; images.image:
"emo-suspicious.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-suspicious.png"; } } } }
group { name: "elm/entry/emoticon/tongue-dangling/default"; images.image:
"emo-tongue-dangling.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-tongue-dangling.png"; } } } }
group { name: "elm/entry/emoticon/tongue-poke/default"; images.image:
"emo-tongue-poke.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-tongue-poke.png"; } } } }
group { name: "elm/entry/emoticon/uh/default"; images.image:
"emo-uh.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-uh.png"; } } } }
group { name: "elm/entry/emoticon/unhappy/default"; images.image:
"emo-unhappy.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-unhappy.png"; } } } }
group { name: "elm/entry/emoticon/very-sorry/default"; images.image:
"emo-very-sorry.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-very-sorry.png"; } } } }
group { name: "elm/entry/emoticon/what/default"; images.image:
"emo-what.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-what.png"; } } } }
group { name: "elm/entry/emoticon/wink/default"; images.image:
"emo-wink.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-wink.png"; } } } }
group { name: "elm/entry/emoticon/worried/default"; images.image:
"emo-worried.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-worried.png"; } } } }
group { name: "elm/entry/emoticon/wtf/default"; images.image:
"emo-wtf.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
"emo-wtf.png"; } } } }
//------------------------------------------------------------
}

View File

@ -0,0 +1,529 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/types.h>
#ifdef HAVE_SYS_SYSINFO_H
# include <sys/sysinfo.h>
#endif
#include <Eina.h>
#include <Eo.h>
#include <Evas.h>
#include <Ecore.h>
#include <Ecore_File.h>
#include <Ecore_Getopt.h>
#include <Ecore_Con.h>
#include <Elementary.h>
#include <Exactness.h>
#include <exactness_private.h>
#define MAX_PATH 1024
#define STABILIZE_KEY_STR "F1"
#define SHOT_KEY_STR "F2"
#define SAVE_KEY_STR "F3"
static Evas *(*_evas_new)(void) = NULL;
static const char *_out_filename = NULL;
static const char *_test_name = NULL;
static int _verbose = 0;
static Eina_List *_evas_list = NULL;
static unsigned int _last_evas_id = 0;
static Exactness_Unit *_unit = NULL;
static char *_shot_key = NULL;
static unsigned int _last_timestamp = 0.0;
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 Exactness_Action_Type
_event_pointer_type_get(Efl_Pointer_Action t)
{
switch(t)
{
case EFL_POINTER_ACTION_IN: return EXACTNESS_ACTION_MOUSE_IN;
case EFL_POINTER_ACTION_OUT: return EXACTNESS_ACTION_MOUSE_OUT;
case EFL_POINTER_ACTION_DOWN: return EXACTNESS_ACTION_MULTI_DOWN;
case EFL_POINTER_ACTION_UP: return EXACTNESS_ACTION_MULTI_UP;
case EFL_POINTER_ACTION_MOVE: return EXACTNESS_ACTION_MULTI_MOVE;
case EFL_POINTER_ACTION_WHEEL: return EXACTNESS_ACTION_MOUSE_WHEEL;
default: return EXACTNESS_ACTION_UNKNOWN;
}
}
static void
_output_write()
{
if (_unit) exactness_unit_file_write(_unit, _out_filename);
}
static void
_add_to_list(Exactness_Action_Type type, unsigned int n_evas, unsigned int timestamp, void *data, int len)
{
if (_unit)
{
const Exactness_Action *prev_v = eina_list_last_data_get(_unit->actions);
if (prev_v)
{
if (prev_v->type == type &&
timestamp == _last_timestamp &&
prev_v->n_evas == n_evas &&
(!len || !memcmp(prev_v->data, data, len))) return;
}
_printf(1, "Recording %s\n", _exactness_action_type_to_string_get(type));
Exactness_Action *act = malloc(sizeof(*act));
act->type = type;
act->n_evas = n_evas;
act->delay_ms = timestamp - _last_timestamp;
_last_timestamp = timestamp;
if (len)
{
act->data = malloc(len);
memcpy(act->data, data, len);
}
_unit->actions = eina_list_append(_unit->actions, act);
}
}
static int
_evas_id_get(Evas *e)
{
return (intptr_t)efl_key_data_get(e, "__evas_id");
}
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_id_get(eo_e);
Efl_Pointer_Action action = efl_input_pointer_action_get(evp);
Exactness_Action_Type evt = _event_pointer_type_get(action);
if (!timestamp) return;
_printf(2, "Calling \"%s\" timestamp=<%u>\n", _exactness_action_type_to_string_get(evt), timestamp);
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_touch_id_get(evp);
Eina_Position2D pos = efl_input_pointer_position_get(evp);
Exactness_Action_Multi_Move t = { tool, pos.x, pos.y, rad, radx, rady, pres, ang, fx, fy };
if (n_evas >= 0) _add_to_list(evt, n_evas, timestamp, &t, sizeof(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_touch_id_get(evp);
Eina_Position2D pos = efl_input_pointer_position_get(evp);
Efl_Pointer_Flags flags = efl_input_pointer_button_flags_get(evp);
Exactness_Action_Multi_Event t = { tool, b, pos.x, pos.y, rad, radx, rady, pres, ang,
fx, fy, flags };
if (n_evas >= 0) _add_to_list(evt, n_evas, timestamp, &t, sizeof(t));
break;
}
case EFL_POINTER_ACTION_IN:
case EFL_POINTER_ACTION_OUT:
{
if (n_evas >= 0) _add_to_list(evt, n_evas, timestamp, NULL, 0);
break;
}
case EFL_POINTER_ACTION_WHEEL:
{
Eina_Bool horiz = efl_input_pointer_wheel_horizontal_get(evp);
int z = efl_input_pointer_wheel_delta_get(evp);
Exactness_Action_Mouse_Wheel t = { horiz, z };
if (n_evas >= 0) _add_to_list(evt, n_evas, timestamp, &t, sizeof(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);
unsigned int n_evas = _evas_id_get(eo_e);
Exactness_Action_Type evt = EXACTNESS_ACTION_KEY_UP;
if (efl_input_key_pressed_get(evk))
{
if (!strcmp(key, _shot_key))
{
_printf(2, "Take Screenshot: %s timestamp=<%u>\n", __func__, timestamp);
_add_to_list(EXACTNESS_ACTION_TAKE_SHOT, n_evas, timestamp, NULL, 0);
return;
}
if (!strcmp(key, STABILIZE_KEY_STR))
{
_printf(2, "Stabilize: %s timestamp=<%u>\n", __func__, timestamp);
_add_to_list(EXACTNESS_ACTION_STABILIZE, n_evas, timestamp, NULL, 0);
return;
}
if (!strcmp(key, SAVE_KEY_STR))
{
_output_write();
_printf(2, "Save events: %s timestamp=<%u>\n", __func__, timestamp);
return;
}
evt = EXACTNESS_ACTION_KEY_DOWN;
}
else
{
if (!strcmp(key, _shot_key) || !strcmp(key, SAVE_KEY_STR) || !strcmp(key, STABILIZE_KEY_STR)) return;
}
if (_unit)
{ /* Construct duplicate strings, free them when list if freed */
Exactness_Action_Key_Down_Up t;
t.keyname = eina_stringshare_add(key);
t.key = eina_stringshare_add(efl_input_key_sym_get(evk));
t.string = eina_stringshare_add(efl_input_key_string_get(evk));
t.compose = eina_stringshare_add(efl_input_key_compose_string_get(evk));
t.keycode = efl_input_key_code_get(evk);
_add_to_list(evt, n_evas, timestamp, &t, sizeof(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 }
)
static Evas *
_my_evas_new(int w EINA_UNUSED, int h EINA_UNUSED)
{
Evas *e;
if (!_evas_new) return NULL;
e = _evas_new();
if (e)
{
_printf(1, "New Evas\n");
_evas_list = eina_list_append(_evas_list, e);
efl_key_data_set(e, "__evas_id", (void *)(intptr_t)_last_evas_id++);
efl_event_callback_array_add(e, _event_pointer_callbacks(), e);
}
return e;
}
static int
_prg_invoke(const char *full_path, int argc, char **argv)
{
Eina_Value *ret__;
int real__;
void (*efl_main)(void *data, const Efl_Event *ev);
int (*elm_main)(int argc, char **argv);
int (*c_main)(int argc, char **argv);
Eina_Module *h = eina_module_new(full_path);
if (!h || !eina_module_load(h))
{
fprintf(stderr, "Failed loading %s.\n", full_path);
if (h) eina_module_free(h);
return EINA_FALSE;
}
efl_main = eina_module_symbol_get(h, "efl_main");
elm_main = eina_module_symbol_get(h, "elm_main");
c_main = eina_module_symbol_get(h, "main");
_evas_new = eina_module_symbol_get(h, "evas_new");
if (!_evas_new)
{
fprintf(stderr, "Failed loading symbol 'evas_new' from %s.\n", full_path);
eina_module_free(h);
return 1;
}
if (efl_main)
{
elm_init(argc, argv);
efl_event_callback_add(efl_main_loop_get(), EFL_LOOP_EVENT_ARGUMENTS, efl_main, NULL);
ret__ = efl_loop_begin(efl_main_loop_get());
real__ = efl_loop_exit_code_process(ret__);
elm_shutdown();
}
else if (elm_main)
{
elm_init(argc, argv);
real__ = elm_main(argc, argv);
elm_shutdown();
}
else if (c_main)
{
real__ = c_main(argc, argv);
}
else
{
fprintf(stderr, "Failed loading symbol 'efl_main', 'elm_main' or 'main' from %s.\n", full_path);
eina_module_free(h);
real__ = 1;
}
return real__;
}
static Eina_Stringshare *
_prg_full_path_guess(const char *prg)
{
char full_path[MAX_PATH];
if (strchr(prg, '/')) return eina_stringshare_add(prg);
char *paths = strdup(getenv("PATH"));
Eina_Stringshare *ret = NULL;
while (paths && *paths && !ret)
{
char *real_path;
char *colon = strchr(paths, ':');
if (colon) *colon = '\0';
sprintf(full_path, "%s/%s", paths, prg);
real_path = ecore_file_realpath(full_path);
if (*real_path)
{
ret = eina_stringshare_add(real_path);
// check if executable
}
free(real_path);
paths += strlen(paths);
if (colon) paths++;
}
return ret;
}
static Eina_Bool
_mkdir(const char *dir)
{
if (!ecore_file_exists(dir))
{
const char *cur = dir + 1;
do
{
char *slash = strchr(cur, '/');
if (slash) *slash = '\0';
if (!ecore_file_exists(dir) && !ecore_file_mkdir(dir)) return EINA_FALSE;
if (slash) *slash = '/';
if (slash) cur = slash + 1;
else cur = NULL;
}
while (cur);
}
return EINA_TRUE;
}
static const Ecore_Getopt optdesc = {
"exactness_record",
"%prog [options] <-v|-t|-h> command",
PACKAGE_VERSION,
"(C) 2017 Enlightenment",
"BSD",
"A scenario recorder for EFL based applications.\n"
"\tF1 - Request stabilization\n"
"\tF2 - Request shot\n"
"\tF3 - Request to save the scenario\n",
1,
{
ECORE_GETOPT_STORE_STR('t', "test", "Name of the filename where to store the test."),
ECORE_GETOPT_STORE_STR('f', "fonts-dir", "Specify a directory of the fonts that should be used."),
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)
{
char *dest = NULL, *eq;
char *fonts_dir = NULL;
int pret = 1, opt_args = 0;
Eina_Bool want_quit = EINA_FALSE;
Ecore_Getopt_Value values[] = {
ECORE_GETOPT_VALUE_STR(dest),
ECORE_GETOPT_VALUE_STR(fonts_dir),
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();
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;
/* Check for a sentinel */
if (argv[opt_args] && !strcmp(argv[opt_args], "--")) opt_args++;
/* Check for env variables */
do
{
eq = argv[opt_args] ? strchr(argv[opt_args], '=') : NULL;
if (eq)
{
char *var = malloc(eq - argv[opt_args] + 1);
memcpy(var, argv[opt_args], eq - argv[opt_args]);
var[eq - argv[opt_args]] = '\0';
setenv(var, eq + 1, 1);
opt_args++;
}
} while (eq);
_out_filename = eina_stringshare_add(dest);
if (!_out_filename)
{
fprintf(stderr, "no test file specified\n");
goto end;
}
else
{
char *slash = strrchr(_out_filename, '/');
if (slash) _test_name = strdup(slash + 1);
else _test_name = strdup(_out_filename);
char *dot = strrchr(_test_name, '.');
if (dot) *dot = '\0';
if (slash)
{
*slash = '\0';
if (!_mkdir(_out_filename))
{
fprintf(stderr, "Can't create %s\n", _out_filename);
goto end;
}
*slash = '/';
}
}
if (strcmp(_out_filename + strlen(_out_filename) - 4,".exu"))
{
fprintf(stderr, "A file with a exu extension is required - %s invalid\n", _out_filename);
goto end;
}
if (!argv[opt_args])
{
fprintf(stderr, "no program specified\nUse -h for more information\n");
goto end;
}
efl_object_init();
evas_init();
if (!_unit)
{
_unit = calloc(1, sizeof(*_unit));
}
if (fonts_dir)
{
Eina_Tmpstr *fonts_conf_name = NULL;
if (!ecore_file_exists(fonts_dir))
{
fprintf(stderr, "Unable to find fonts directory %s\n", fonts_dir);
goto cleanup;
}
Eina_List *dated_fonts = ecore_file_ls(fonts_dir);
char *date_dir;
_unit->fonts_path = strdup(eina_list_last_data_get(dated_fonts));
EINA_LIST_FREE(dated_fonts, date_dir) free(date_dir);
if (_unit->fonts_path)
{
int tmp_fd = eina_file_mkstemp("/tmp/fonts_XXXXXX.conf", &fonts_conf_name);
FILE *tmp_f = fdopen(tmp_fd, "wb");
fprintf(tmp_f,
"<?xml version=\"1.0\"?>\n<!DOCTYPE fontconfig SYSTEM \"fonts.dtd\">\n<fontconfig>\n"
"<dir prefix=\"default\">%s/%s</dir>\n</fontconfig>\n",
fonts_dir, _unit->fonts_path);
fclose(tmp_f);
close(tmp_fd);
setenv("FONTCONFIG_FILE", fonts_conf_name, 1);
}
}
/* Replace the current command line to hide the Exactness part */
int len = argv[argc - 1] + strlen(argv[argc - 1]) - argv[opt_args];
memcpy(argv[0], argv[opt_args], len);
memset(argv[0] + len, 0, MAX_PATH - len);
int i;
for (i = opt_args; i < argc; i++)
{
if (i != opt_args)
{
argv[i - opt_args] = argv[0] + (argv[i] - argv[opt_args]);
}
_printf(1, "%s ", argv[i - opt_args]);
}
_printf(1, "\n");
if (!_shot_key) _shot_key = getenv("SHOT_KEY");
if (!_shot_key) _shot_key = SHOT_KEY_STR;
ecore_evas_callback_new_set(_my_evas_new);
_last_timestamp = ecore_time_get() * 1000;
pret = _prg_invoke(_prg_full_path_guess(argv[0]), argc - opt_args, argv);
_output_write();
//free_events(_events_list, EINA_TRUE);
//_events_list = NULL;
pret = 0;
cleanup:
efl_object_shutdown();
evas_shutdown();
end:
ecore_shutdown();
eina_shutdown();
return pret;
}

View File

@ -0,0 +1,268 @@
#ifndef _EXACTNESS_H
#define _EXACTNESS_H
#include <Evas.h>
#ifdef EAPI
# undef EAPI
#endif
#ifdef _WIN32
# ifdef EXACTNESS_BUILD
# ifdef DLL_EXPORT
# define EAPI __declspec(dllexport)
# else
# define EAPI
# endif /* ! DLL_EXPORT */
# else
# define EAPI __declspec(dllimport)
# endif /* ! EXACTNESS_BUILD */
#else
# ifdef __GNUC__
# if __GNUC__ >= 4
# define EAPI __attribute__ ((visibility("default")))
# else
# define EAPI
# endif
# else
# define EAPI
# endif
#endif /* ! _WIN32 */
/**
* @page exactness_main Exactness
*
* @date 2018 (created)
*
* This page describes the public structures and APIs available for Exactness.
*
* @addtogroup Exactness
* @{
*/
/**
* @typedef Exactness_Action_Type
* The type values for an Exactness action.
*/
typedef enum
{
EXACTNESS_ACTION_UNKNOWN = 0,
EXACTNESS_ACTION_MOUSE_IN,
EXACTNESS_ACTION_MOUSE_OUT,
EXACTNESS_ACTION_MOUSE_WHEEL,
EXACTNESS_ACTION_MULTI_DOWN,
EXACTNESS_ACTION_MULTI_UP,
EXACTNESS_ACTION_MULTI_MOVE,
EXACTNESS_ACTION_KEY_DOWN,
EXACTNESS_ACTION_KEY_UP,
EXACTNESS_ACTION_TAKE_SHOT,
EXACTNESS_ACTION_EFL_EVENT,
EXACTNESS_ACTION_CLICK_ON,
EXACTNESS_ACTION_STABILIZE,
EXACTNESS_ACTION_LAST = EXACTNESS_ACTION_STABILIZE
/* Add any supported actions here and update _LAST */
} Exactness_Action_Type;
/**
* @typedef Exactness_Action_Mouse_Wheel
* The type for the Exactness Mouse Wheel action.
*/
typedef struct
{
int direction;
int z;
} Exactness_Action_Mouse_Wheel;
/**
* @typedef Exactness_Action_Key_Down_Up
* The type for the Exactness Key Down Up action.
*/
typedef struct
{
const char *keyname;
const char *key;
const char *string;
const char *compose;
unsigned int keycode;
} Exactness_Action_Key_Down_Up;
/**
* @typedef Exactness_Action_Multi_Event
* The type for the Exactness Multi Event action.
*/
typedef struct
{
int d;
int b; /* In case of simple mouse down/up, corresponds to the button */
int x;
int y;
double rad;
double radx;
double rady;
double pres;
double ang;
double fx;
double fy;
Evas_Button_Flags flags;
} Exactness_Action_Multi_Event;
/**
* @typedef Exactness_Action_Multi_Move
* The type for the Exactness Multi Move action.
*/
typedef struct
{
int d;
int x;
int y;
double rad;
double radx;
double rady;
double pres;
double ang;
double fx;
double fy;
} Exactness_Action_Multi_Move;
/**
* @typedef Exactness_Action_Efl_Event
* The type for the Exactness EFL Event action.
*/
typedef struct
{
char *wdg_name;
char *event_name;
} Exactness_Action_Efl_Event;
/**
* @typedef Exactness_Action_Click_On
* The type for the Exactness Click on (widget) action.
*/
typedef struct
{
char *wdg_name;
} Exactness_Action_Click_On;
/**
* @typedef Exactness_Action
* The type for the Exactness action.
*/
typedef struct
{
Exactness_Action_Type type; /**< The action type */
unsigned int n_evas; /**< The evas number on which the action has to be applied */
unsigned int delay_ms; /**< The delay (in ms) to wait for this action */
void *data; /**< The specific action data */
} Exactness_Action;
/**
* @typedef Exactness_Object
* The type for the Exactness object.
*/
typedef struct
{
long long id; /**< The Eo pointer */
long long parent_id; /**< The Eo parent pointer */
const char *kl_name; /**< The class name */
Eina_List *children; /* NOT EET */
/* Evas stuff */
int x; /**< The X coordinate */
int y; /**< The Y coordinate */
int w; /**< The object width */
int h; /**< The object height */
} Exactness_Object;
/**
* @typedef Exactness_Objects
* The type for the Exactness objects list.
*/
typedef struct
{
Eina_List *objs; /**< List of all the objects */
/* main_objs not in EET */
Eina_List *main_objs; /**< List of the main objects */
} Exactness_Objects;
/**
* @typedef Exactness_Image
* The type for the Exactness Image.
*/
typedef struct
{
unsigned int w; /**< Width of the image */
unsigned int h; /**< Height of the image */
void *pixels; /**< Pixels of the image */
} Exactness_Image;
typedef struct
{
char *language; /**< String describing the language of the content e.g "C"...*/
char *content; /**< Content used as source */
char *command; /**< Command needed to generate the application from the content */
} Exactness_Source_Code;
typedef struct
{
Eina_List *actions; /**< List of Exactness_Action */
/* imgs not in EET */
Eina_List *imgs; /**< List of Exactness_Image */
Eina_List *objs; /**< List of Exactness_Objects */
Eina_List *codes; /**< List of Exactness_Source_Code */
const char *fonts_path; /**< Path to the fonts to use, relative to the fonts dir given in parameter to the player/recorder */
int nb_shots; /**< The number of shots present in the unit */
} Exactness_Unit;
/**
* @brief Read an unit from a given file
*
* @param filename Name of the file containing the unit
*
* @return the unit
*/
EAPI Exactness_Unit *exactness_unit_file_read(const char *filename);
/**
* @brief Write an unit into the given file
*
* @param unit Unit to store
* @param filename Name of the file containing the unit
*
* @return EINA_TRUE on success, EINA_FALSE otherwise
*/
EAPI Eina_Bool exactness_unit_file_write(Exactness_Unit *unit, const char *filename);
/**
* @brief Compare two images
*
* @param img1 first image
* @param img2 second image
* @param imgO pointer for the diff image. Can be NULL
*
* @return EINA_TRUE if the images are different, EINA_FALSE otherwise
*/
EAPI Eina_Bool exactness_image_compare(Exactness_Image *img1, Exactness_Image *img2, Exactness_Image **imgO);
/**
* @brief Free the given image
*
* @param img the image
*
*/
EAPI void exactness_image_free(Exactness_Image *img);
/**
* @brief Read a legacy file and convert it to an unit
*
* @param filename Name of the legacy file
*
* @return the unit
*/
EAPI Exactness_Unit *legacy_rec_file_read(const char *filename);
/**
* @}
*/
#endif /* _EXACTNESS_H */

View File

@ -0,0 +1,10 @@
#ifndef _EXACTNESS_PRIVATE_H
#define _EXACTNESS_PRIVATE_H
#include <Exactness.h>
/* private header */
EAPI const char *_exactness_action_type_to_string_get(Exactness_Action_Type type);
#define SHOT_DELIMITER '+'
#endif

View File

@ -0,0 +1,875 @@
#include <stdio.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <Eina.h>
#include <Eet.h>
#include <Evas.h>
#include "Exactness.h"
#define CACHE_FILE_ENTRY "cache"
enum _Tsuite_Event_Type
{ /* Add any supported events here */
TSUITE_EVENT_NOT_SUPPORTED = 0,
TSUITE_EVENT_MOUSE_IN,
TSUITE_EVENT_MOUSE_OUT,
TSUITE_EVENT_MOUSE_DOWN,
TSUITE_EVENT_MOUSE_UP,
TSUITE_EVENT_MOUSE_MOVE,
TSUITE_EVENT_MOUSE_WHEEL,
TSUITE_EVENT_MULTI_DOWN,
TSUITE_EVENT_MULTI_UP,
TSUITE_EVENT_MULTI_MOVE,
TSUITE_EVENT_KEY_DOWN,
TSUITE_EVENT_KEY_UP,
TSUITE_EVENT_KEY_DOWN_WITH_KEYCODE,
TSUITE_EVENT_KEY_UP_WITH_KEYCODE,
TSUITE_EVENT_TAKE_SHOT
};
typedef enum _Tsuite_Event_Type Tsuite_Event_Type;
struct _eet_event_type_mapping
{
Tsuite_Event_Type t;
const char *name;
};
typedef struct _eet_event_type_mapping eet_event_type_mapping;
struct _Variant_Type_st
{
const char *type;
Eina_Bool unknow : 1;
};
typedef struct _Variant_Type_st Variant_Type_st;
struct _Variant_st
{
Variant_Type_st t;
void *data; /* differently than the union type, we
* don't need to pre-allocate the memory
* for the field*/
};
typedef struct _Variant_st Variant_st;
struct _Timer_Data
{
unsigned int recent_event_time;
Eina_List *current_event;
};
typedef struct _Timer_Data Timer_Data;
struct _Tsuite_Data
{
int serial; /**< Serial number of current-file */
Timer_Data *td;
};
typedef struct _Tsuite_Data Tsuite_Data;
struct _mouse_in_mouse_out
{
unsigned int timestamp;
int n_evas;
};
struct _mouse_down_mouse_up
{
int b;
Evas_Button_Flags flags;
unsigned int timestamp;
int n_evas;
};
struct _mouse_move
{
int x;
int y;
unsigned int timestamp;
int n_evas;
};
struct _mouse_wheel
{
int direction;
int z;
unsigned int timestamp;
int n_evas;
};
struct _key_down_key_up
{
unsigned int timestamp;
const char *keyname;
const char *key;
const char *string;
const char *compose;
int n_evas;
};
struct _key_down_key_up_with_keycode
{
unsigned int timestamp;
const char *keyname;
const char *key;
const char *string;
const char *compose;
int n_evas;
unsigned int 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;
double radx;
double rady;
double pres;
double ang;
double fx;
double fy;
Evas_Button_Flags flags;
unsigned int timestamp;
int n_evas;
};
struct _multi_move
{
int d;
int x;
int y;
double rad;
double radx;
double rady;
double pres;
double ang;
double fx;
double fy;
unsigned int timestamp;
int n_evas;
};
typedef struct _mouse_in_mouse_out mouse_in_mouse_out;
typedef struct _mouse_down_mouse_up mouse_down_mouse_up;
typedef struct _mouse_move mouse_move;
typedef struct _mouse_wheel mouse_wheel;
typedef struct _multi_event multi_event;
typedef struct _multi_move multi_move;
typedef struct _key_down_key_up key_down_key_up;
typedef struct _key_down_key_up_with_keycode key_down_key_up_with_keycode;
typedef struct _mouse_in_mouse_out take_screenshot;
/* START - EET support typedefs */
#define TSUITE_EVENT_MOUSE_IN_STR "tsuite_event_mouse_in"
#define TSUITE_EVENT_MOUSE_OUT_STR "tsuite_event_mouse_out"
#define TSUITE_EVENT_MOUSE_DOWN_STR "tsuite_event_mouse_down"
#define TSUITE_EVENT_MOUSE_UP_STR "tsuite_event_mouse_up"
#define TSUITE_EVENT_MOUSE_MOVE_STR "tsuite_event_mouse_move"
#define TSUITE_EVENT_MOUSE_WHEEL_STR "tsuite_event_mouse_wheel"
#define TSUITE_EVENT_MULTI_DOWN_STR "tsuite_event_multi_down"
#define TSUITE_EVENT_MULTI_UP_STR "tsuite_event_multi_up"
#define TSUITE_EVENT_MULTI_MOVE_STR "tsuite_event_multi_move"
#define TSUITE_EVENT_KEY_DOWN_STR "tsuite_event_key_down"
#define TSUITE_EVENT_KEY_UP_STR "tsuite_event_key_up"
#define TSUITE_EVENT_KEY_DOWN_WITH_KEYCODE_STR "tsuite_event_key_down_with_keycode"
#define TSUITE_EVENT_KEY_UP_WITH_KEYCODE_STR "tsuite_event_key_up_with_keycode"
#define TSUITE_EVENT_TAKE_SHOT_STR "tsuite_event_take_shot"
struct _Lists_st
{
Eina_List *variant_list;
unsigned int first_timestamp;
};
typedef struct _Lists_st Lists_st;
struct _data_desc
{
Eet_Data_Descriptor *take_screenshot;
Eet_Data_Descriptor *mouse_in_mouse_out;
Eet_Data_Descriptor *mouse_down_mouse_up;
Eet_Data_Descriptor *mouse_move;
Eet_Data_Descriptor *mouse_wheel;
Eet_Data_Descriptor *multi_event;
Eet_Data_Descriptor *multi_move;
Eet_Data_Descriptor *key_down_key_up;
Eet_Data_Descriptor *key_down_key_up_with_keycode;
/* list, variant EET desc support */
Eet_Data_Descriptor *lists_descriptor;
Eet_Data_Descriptor *variant_descriptor;
Eet_Data_Descriptor *variant_unified_descriptor;
};
typedef struct _data_desc data_desc;
/* END - EET support typedefs */
static data_desc *_desc = NULL; /* this struct holds descs (alloc on init) */
static eet_event_type_mapping eet_mapping[] = {
{ TSUITE_EVENT_MOUSE_IN, TSUITE_EVENT_MOUSE_IN_STR },
{ TSUITE_EVENT_MOUSE_OUT, TSUITE_EVENT_MOUSE_OUT_STR },
{ TSUITE_EVENT_MOUSE_DOWN, TSUITE_EVENT_MOUSE_DOWN_STR },
{ TSUITE_EVENT_MOUSE_UP, TSUITE_EVENT_MOUSE_UP_STR },
{ TSUITE_EVENT_MOUSE_MOVE, TSUITE_EVENT_MOUSE_MOVE_STR },
{ TSUITE_EVENT_MOUSE_WHEEL, TSUITE_EVENT_MOUSE_WHEEL_STR },
{ TSUITE_EVENT_MULTI_DOWN, TSUITE_EVENT_MULTI_DOWN_STR },
{ TSUITE_EVENT_MULTI_UP, TSUITE_EVENT_MULTI_UP_STR },
{ TSUITE_EVENT_MULTI_MOVE, TSUITE_EVENT_MULTI_MOVE_STR },
{ TSUITE_EVENT_KEY_DOWN, TSUITE_EVENT_KEY_DOWN_STR },
{ TSUITE_EVENT_KEY_UP, TSUITE_EVENT_KEY_UP_STR },
{ TSUITE_EVENT_KEY_DOWN_WITH_KEYCODE, TSUITE_EVENT_KEY_DOWN_WITH_KEYCODE_STR },
{ TSUITE_EVENT_KEY_UP_WITH_KEYCODE, TSUITE_EVENT_KEY_UP_WITH_KEYCODE_STR },
{ TSUITE_EVENT_TAKE_SHOT, TSUITE_EVENT_TAKE_SHOT_STR },
{ TSUITE_EVENT_NOT_SUPPORTED, NULL }
};
static Tsuite_Event_Type
_event_mapping_type_get(const char *name)
{
int i;
for (i = 0; eet_mapping[i].name != NULL; ++i)
if (strcmp(name, eet_mapping[i].name) == 0)
return eet_mapping[i].t;
return TSUITE_EVENT_NOT_SUPPORTED;
}
static unsigned int
_evt_time_get(unsigned int tm, Variant_st *v)
{
if (!v) return tm;
switch(_event_mapping_type_get(v->t.type))
{
case TSUITE_EVENT_MOUSE_IN:
{
mouse_in_mouse_out *t = v->data;
return t->timestamp;
}
case TSUITE_EVENT_MOUSE_OUT:
{
mouse_in_mouse_out *t = v->data;
return t->timestamp;
}
case TSUITE_EVENT_MOUSE_DOWN:
{
mouse_down_mouse_up *t = v->data;
return t->timestamp;
}
case TSUITE_EVENT_MOUSE_UP:
{
mouse_down_mouse_up *t = v->data;
return t->timestamp;
}
case TSUITE_EVENT_MOUSE_MOVE:
{
mouse_move *t = v->data;
return t->timestamp;
}
case TSUITE_EVENT_MOUSE_WHEEL:
{
mouse_wheel *t = v->data;
return t->timestamp;
}
case TSUITE_EVENT_MULTI_DOWN:
{
multi_event *t = v->data;
return t->timestamp;
}
case TSUITE_EVENT_MULTI_UP:
{
multi_event *t = v->data;
return t->timestamp;
}
case TSUITE_EVENT_MULTI_MOVE:
{
multi_move *t = v->data;
return t->timestamp;
}
case TSUITE_EVENT_KEY_DOWN:
{
key_down_key_up *t = v->data;
return t->timestamp;
}
case TSUITE_EVENT_KEY_UP:
{
key_down_key_up *t = v->data;
return t->timestamp;
}
case TSUITE_EVENT_KEY_DOWN_WITH_KEYCODE:
{
key_down_key_up_with_keycode *t = v->data;
return t->timestamp;
}
case TSUITE_EVENT_KEY_UP_WITH_KEYCODE:
{
key_down_key_up_with_keycode *t = v->data;
return t->timestamp;
}
case TSUITE_EVENT_TAKE_SHOT:
{
take_screenshot *t = v->data;
return t->timestamp;
}
default: /* All non-input events are not handeled */
return tm;
break;
}
}
static Lists_st *
_free_events(Lists_st *st)
{
Variant_st *v;
if (!st) goto end;
EINA_LIST_FREE(st->variant_list, v)
{
free(v->data);
free(v);
}
free(st); /* Allocated when reading data from EET file */
end:
return NULL;
}
static const char *
_variant_type_get(const void *data, Eina_Bool *unknow)
{
const Variant_Type_st *type = data;
int i;
if (unknow)
*unknow = type->unknow;
for (i = 0; eet_mapping[i].name != NULL; ++i)
if (strcmp(type->type, eet_mapping[i].name) == 0)
return eet_mapping[i].name;
if (unknow)
*unknow = EINA_FALSE;
return type->type;
} /* _variant_type_get */
static Eina_Bool
_variant_type_set(const char *type,
void *data,
Eina_Bool unknow)
{
Variant_Type_st *vt = data;
vt->type = type;
vt->unknow = unknow;
return EINA_TRUE;
} /* _variant_type_set */
/* START Event struct descriptors */
static Eet_Data_Descriptor *
_take_screenshot_desc_make(void)
{
Eet_Data_Descriptor_Class eddc;
Eet_Data_Descriptor *_d;
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, take_screenshot);
_d = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, take_screenshot, "timestamp",
timestamp, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, take_screenshot, "n_evas",
n_evas, EET_T_INT);
return _d;
}
static Eet_Data_Descriptor *
_mouse_in_mouse_out_desc_make(void)
{
Eet_Data_Descriptor_Class eddc;
Eet_Data_Descriptor *_d;
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, mouse_in_mouse_out);
_d = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, mouse_in_mouse_out, "timestamp",
timestamp, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, mouse_in_mouse_out, "n_evas",
n_evas, EET_T_INT);
return _d;
}
static Eet_Data_Descriptor *
_mouse_down_mouse_up_desc_make(void)
{
Eet_Data_Descriptor_Class eddc;
Eet_Data_Descriptor *_d;
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, mouse_down_mouse_up);
_d = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, mouse_down_mouse_up, "b", b, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, mouse_down_mouse_up, "flags",
flags, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, mouse_down_mouse_up, "timestamp",
timestamp, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, mouse_down_mouse_up, "n_evas",
n_evas, EET_T_INT);
return _d;
}
static Eet_Data_Descriptor *
_mouse_move_desc_make(void)
{
Eet_Data_Descriptor_Class eddc;
Eet_Data_Descriptor *_d;
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, mouse_move);
_d = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, mouse_move, "x", x, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, mouse_move, "y", y, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, mouse_move, "timestamp",
timestamp, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, mouse_move, "n_evas",
n_evas, EET_T_INT);
return _d;
}
static Eet_Data_Descriptor *
_mouse_wheel_desc_make(void)
{
Eet_Data_Descriptor_Class eddc;
Eet_Data_Descriptor *_d;
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, mouse_wheel);
_d = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, mouse_wheel, "direction",
direction, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, mouse_wheel, "z", z, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, mouse_wheel, "timestamp",
timestamp, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, mouse_wheel, "n_evas",
n_evas, EET_T_INT);
return _d;
}
static Eet_Data_Descriptor *
_key_down_key_up_desc_make(void)
{
Eet_Data_Descriptor_Class eddc;
Eet_Data_Descriptor *_d;
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, key_down_key_up);
_d = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, key_down_key_up, "timestamp",
timestamp, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, key_down_key_up, "keyname",
keyname, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, key_down_key_up, "key",
key, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, key_down_key_up, "string",
string, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, key_down_key_up, "compose",
compose, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, key_down_key_up, "n_evas",
n_evas, EET_T_INT);
return _d;
}
static Eet_Data_Descriptor *
_key_down_key_up_with_keycode_desc_make(void)
{
Eet_Data_Descriptor_Class eddc;
Eet_Data_Descriptor *_d;
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, key_down_key_up_with_keycode);
_d = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, key_down_key_up_with_keycode, "timestamp",
timestamp, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, key_down_key_up_with_keycode, "keyname",
keyname, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, key_down_key_up_with_keycode, "key",
key, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, key_down_key_up_with_keycode, "string",
string, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, key_down_key_up_with_keycode, "compose",
compose, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, key_down_key_up_with_keycode, "n_evas",
n_evas, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, key_down_key_up_with_keycode, "keycode",
keycode, EET_T_INT);
return _d;
}
static Eet_Data_Descriptor *
_multi_event_desc_make(void)
{
Eet_Data_Descriptor_Class eddc;
Eet_Data_Descriptor *_d;
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, multi_event);
_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);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_event, "radx", radx, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_event, "rady", rady, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_event, "pres", pres, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_event, "ang", ang, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_event, "fx", fx, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_event, "fy", fy, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_event, "flags", flags, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_event, "timestamp",
timestamp, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_event, "n_evas",
n_evas, EET_T_INT);
return _d;
}
static Eet_Data_Descriptor *
_multi_move_desc_make(void)
{
Eet_Data_Descriptor_Class eddc;
Eet_Data_Descriptor *_d;
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, multi_move);
_d = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_move, "d", d, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_move, "x", x, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_move, "y", y, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_move, "rad", rad, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_move, "radx", radx, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_move, "rady", rady, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_move, "pres", pres, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_move, "ang", ang, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_move, "fx", fx, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_move, "fy", fy, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_move, "timestamp",
timestamp, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, multi_move, "n_evas",
n_evas, EET_T_INT);
return _d;
}
/* declaring types */
static data_desc *
_data_descriptors_init(void)
{
if (_desc) /* Was allocated */
return _desc;
_desc = calloc(1, sizeof(data_desc));
Eet_Data_Descriptor_Class eddc;
EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Lists_st);
_desc->lists_descriptor = eet_data_descriptor_file_new(&eddc);
_desc->take_screenshot = _take_screenshot_desc_make();
_desc->mouse_in_mouse_out = _mouse_in_mouse_out_desc_make();
_desc->mouse_down_mouse_up = _mouse_down_mouse_up_desc_make();
_desc->mouse_move = _mouse_move_desc_make();
_desc->mouse_wheel = _mouse_wheel_desc_make();
_desc->multi_event = _multi_event_desc_make();
_desc->multi_move = _multi_move_desc_make();
_desc->key_down_key_up = _key_down_key_up_desc_make();
_desc->key_down_key_up_with_keycode = _key_down_key_up_with_keycode_desc_make();
/* for variant */
EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Variant_st);
_desc->variant_descriptor = eet_data_descriptor_file_new(&eddc);
eddc.version = EET_DATA_DESCRIPTOR_CLASS_VERSION;
eddc.func.type_get = _variant_type_get;
eddc.func.type_set = _variant_type_set;
_desc->variant_unified_descriptor = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_MAPPING(_desc->variant_unified_descriptor,
TSUITE_EVENT_MOUSE_IN_STR, _desc->mouse_in_mouse_out);
EET_DATA_DESCRIPTOR_ADD_MAPPING(_desc->variant_unified_descriptor,
TSUITE_EVENT_MOUSE_OUT_STR, _desc->mouse_in_mouse_out);
EET_DATA_DESCRIPTOR_ADD_MAPPING(_desc->variant_unified_descriptor,
TSUITE_EVENT_MOUSE_DOWN_STR, _desc->mouse_down_mouse_up);
EET_DATA_DESCRIPTOR_ADD_MAPPING(_desc->variant_unified_descriptor,
TSUITE_EVENT_MOUSE_UP_STR, _desc->mouse_down_mouse_up);
EET_DATA_DESCRIPTOR_ADD_MAPPING(_desc->variant_unified_descriptor,
TSUITE_EVENT_MOUSE_MOVE_STR, _desc->mouse_move);
EET_DATA_DESCRIPTOR_ADD_MAPPING(_desc->variant_unified_descriptor,
TSUITE_EVENT_MOUSE_WHEEL_STR, _desc->mouse_wheel);
EET_DATA_DESCRIPTOR_ADD_MAPPING(_desc->variant_unified_descriptor,
TSUITE_EVENT_MULTI_DOWN_STR, _desc->multi_event);
EET_DATA_DESCRIPTOR_ADD_MAPPING(_desc->variant_unified_descriptor,
TSUITE_EVENT_MULTI_UP_STR, _desc->multi_event);
EET_DATA_DESCRIPTOR_ADD_MAPPING(_desc->variant_unified_descriptor,
TSUITE_EVENT_MULTI_MOVE_STR, _desc->multi_move);
EET_DATA_DESCRIPTOR_ADD_MAPPING(_desc->variant_unified_descriptor,
TSUITE_EVENT_KEY_DOWN_STR, _desc->key_down_key_up);
EET_DATA_DESCRIPTOR_ADD_MAPPING(_desc->variant_unified_descriptor,
TSUITE_EVENT_KEY_UP_STR, _desc->key_down_key_up);
EET_DATA_DESCRIPTOR_ADD_MAPPING(_desc->variant_unified_descriptor,
TSUITE_EVENT_KEY_DOWN_WITH_KEYCODE_STR, _desc->key_down_key_up_with_keycode);
EET_DATA_DESCRIPTOR_ADD_MAPPING(_desc->variant_unified_descriptor,
TSUITE_EVENT_KEY_UP_WITH_KEYCODE_STR, _desc->key_down_key_up_with_keycode);
EET_DATA_DESCRIPTOR_ADD_MAPPING(_desc->variant_unified_descriptor,
TSUITE_EVENT_TAKE_SHOT_STR, _desc->take_screenshot);
EET_DATA_DESCRIPTOR_ADD_VARIANT(_desc->variant_descriptor,
Variant_st, "data", data, t, _desc->variant_unified_descriptor);
EET_DATA_DESCRIPTOR_ADD_BASIC(_desc->lists_descriptor,
Lists_st, "first_timestamp", first_timestamp, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_LIST(_desc->lists_descriptor,
Lists_st, "variant_list", variant_list, _desc->variant_descriptor);
return _desc;
}
static void
_data_descriptors_shutdown(void)
{
if (_desc)
{
eet_data_descriptor_free(_desc->mouse_in_mouse_out);
eet_data_descriptor_free(_desc->mouse_down_mouse_up);
eet_data_descriptor_free(_desc->mouse_move);
eet_data_descriptor_free(_desc->mouse_wheel);
eet_data_descriptor_free(_desc->multi_event);
eet_data_descriptor_free(_desc->multi_move);
eet_data_descriptor_free(_desc->key_down_key_up);
eet_data_descriptor_free(_desc->key_down_key_up_with_keycode);
eet_data_descriptor_free(_desc->take_screenshot);
eet_data_descriptor_free(_desc->lists_descriptor);
eet_data_descriptor_free(_desc->variant_descriptor);
eet_data_descriptor_free(_desc->variant_unified_descriptor);
free(_desc);
_desc = NULL;
/* FIXME: Should probably only init and shutdown once */
}
}
EAPI Exactness_Unit *
legacy_rec_file_read(const char *filename)
{
Lists_st *vr_list;
Eina_List *itr;
Variant_st *v, *prev_v = NULL;
Exactness_Unit *unit = NULL;
Eet_File *fp = eet_open(filename, EET_FILE_MODE_READ);
if (!fp)
{
printf("Failed to open input file <%s>.\n", filename);
return NULL;
}
/* Read events list */
_data_descriptors_init();
vr_list = eet_data_read(fp, _desc->lists_descriptor, CACHE_FILE_ENTRY);
eet_close(fp);
_data_descriptors_shutdown();
unit = calloc(1, sizeof(*unit));
EINA_LIST_FOREACH(vr_list->variant_list, itr, v)
{
Exactness_Action *act = calloc(1, sizeof(*act));
Tsuite_Event_Type old_type = _event_mapping_type_get(v->t.type);
unsigned int vtm = _evt_time_get(0, v);
if (!vtm) continue;
switch (old_type)
{
case TSUITE_EVENT_MOUSE_IN:
{
mouse_in_mouse_out *d_i = v->data;
act->type = EXACTNESS_ACTION_MOUSE_IN;
act->n_evas = d_i->n_evas;
break;
}
case TSUITE_EVENT_MOUSE_OUT:
{
mouse_in_mouse_out *d_i = v->data;
act->type = EXACTNESS_ACTION_MOUSE_OUT;
act->n_evas = d_i->n_evas;
break;
}
case TSUITE_EVENT_MOUSE_DOWN:
case TSUITE_EVENT_MOUSE_UP:
{
mouse_down_mouse_up *d_i = v->data;
Exactness_Action_Multi_Event *d_o = calloc(1, sizeof(*d_o));
d_o->b = d_i->b;
d_o->flags = d_i->flags;
if (old_type == TSUITE_EVENT_MOUSE_DOWN)
act->type = EXACTNESS_ACTION_MULTI_DOWN;
else
act->type = EXACTNESS_ACTION_MULTI_UP;
act->n_evas = d_i->n_evas;
act->data = d_o;
break;
}
case TSUITE_EVENT_MOUSE_MOVE:
{
mouse_move *d_i = v->data;
Exactness_Action_Multi_Move *d_o = calloc(1, sizeof(*d_o));
d_o->x = d_i->x;
d_o->y = d_i->y;
act->type = EXACTNESS_ACTION_MULTI_MOVE;
act->n_evas = d_i->n_evas;
act->data = d_o;
break;
}
case TSUITE_EVENT_MOUSE_WHEEL:
{
mouse_wheel *d_i = v->data;
Exactness_Action_Mouse_Wheel *d_o = calloc(1, sizeof(*d_o));
d_o->direction = d_i->direction;
d_o->z = d_i->z;
act->type = EXACTNESS_ACTION_MOUSE_WHEEL;
act->n_evas = d_i->n_evas;
act->data = d_o;
break;
}
case TSUITE_EVENT_MULTI_DOWN:
case TSUITE_EVENT_MULTI_UP:
{
multi_event *d_i = v->data;
Exactness_Action_Multi_Event *d_o = calloc(1, sizeof(*d_o));
d_o->d = d_i->d;
d_o->b = d_i->b;
d_o->x = d_i->x;
d_o->y = d_i->y;
d_o->rad = d_i->rad;
d_o->radx = d_i->radx;
d_o->rady = d_i->rady;
d_o->pres = d_i->pres;
d_o->ang = d_i->ang;
d_o->fx = d_i->fx;
d_o->fy = d_i->fy;
d_o->flags = d_i->flags;
if (old_type == TSUITE_EVENT_MULTI_DOWN)
act->type = EXACTNESS_ACTION_MULTI_DOWN;
else
act->type = EXACTNESS_ACTION_MULTI_UP;
act->n_evas = d_i->n_evas;
act->data = d_o;
break;
}
case TSUITE_EVENT_MULTI_MOVE:
{
multi_move *d_i = v->data;
Exactness_Action_Multi_Move *d_o = calloc(1, sizeof(*d_o));
d_o->d = d_i->d;
d_o->x = d_i->x;
d_o->y = d_i->y;
d_o->rad = d_i->rad;
d_o->radx = d_i->radx;
d_o->rady = d_i->rady;
d_o->pres = d_i->pres;
d_o->ang = d_i->ang;
d_o->fx = d_i->fx;
d_o->fy = d_i->fy;
act->type = EXACTNESS_ACTION_MULTI_MOVE;
act->n_evas = d_i->n_evas;
act->data = d_o;
break;
}
case TSUITE_EVENT_KEY_DOWN:
case TSUITE_EVENT_KEY_UP:
{
key_down_key_up *d_i = v->data;
Exactness_Action_Key_Down_Up *d_o = calloc(1, sizeof(*d_o));
d_o->keyname = d_i->keyname;
d_o->key = d_i->key;
d_o->string = d_i->string;
d_o->compose = d_i->compose;
if (old_type == TSUITE_EVENT_KEY_DOWN)
act->type = EXACTNESS_ACTION_KEY_DOWN;
else
act->type = EXACTNESS_ACTION_KEY_UP;
act->n_evas = d_i->n_evas;
act->data = d_o;
break;
}
case TSUITE_EVENT_KEY_DOWN_WITH_KEYCODE:
case TSUITE_EVENT_KEY_UP_WITH_KEYCODE:
{
key_down_key_up_with_keycode *d_i = v->data;
Exactness_Action_Key_Down_Up *d_o = calloc(1, sizeof(*d_o));
d_o->keyname = d_i->keyname;
d_o->key = d_i->key;
d_o->string = d_i->string;
d_o->compose = d_i->compose;
d_o->keycode = d_i->keycode;
if (old_type == TSUITE_EVENT_KEY_DOWN_WITH_KEYCODE)
act->type = EXACTNESS_ACTION_KEY_DOWN;
else
act->type = EXACTNESS_ACTION_KEY_UP;
act->n_evas = d_i->n_evas;
act->data = d_o;
break;
}
case TSUITE_EVENT_TAKE_SHOT:
{
take_screenshot *d_i = v->data;
act->type = EXACTNESS_ACTION_TAKE_SHOT;
act->n_evas = d_i->n_evas;
break;
}
default: break;
}
if (!prev_v)
{
if (vr_list->first_timestamp)
act->delay_ms = _evt_time_get(0, v) - vr_list->first_timestamp;
else
act->delay_ms = 0;
}
else
{
if (vtm > _evt_time_get(0, prev_v))
act->delay_ms = vtm - _evt_time_get(0, prev_v);
else act->delay_ms = 0;
}
unit->actions = eina_list_append(unit->actions, act);
prev_v = v;
}
#ifdef DEBUG_TSUITE
printf("%s number of actions in the scenario <%d>\n", __func__, eina_list_count(unit->actions));
#endif
_free_events(vr_list);
return unit;
}

View File

@ -0,0 +1,31 @@
exactness_pub_deps = [eina, evas]
exactness_deps = []
exactness_src = [
'Exactness.h',
'exactness_private.h',
'legacy_file.c',
'unit.c'
]
exactness_lib = library('exactness', exactness_src,
dependencies: [ eina, eet, evas ],
install: true,
version : meson.project_version()
)
exactness = declare_dependency(
include_directories: include_directories('.'),
link_with : exactness_lib,
dependencies: [ eina, evas, eet ],
)
exactness_include_dir = join_paths(dir_data, 'exactness', 'include')
exactness_header_src = [
'Exactness.h',
]
install_headers(exactness_header_src,
install_dir : dir_package_include
)

409
src/lib/exactness/unit.c Normal file
View File

@ -0,0 +1,409 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Eet.h>
#include "Exactness.h"
#include "exactness_private.h"
typedef struct _Dummy
{
} _Dummy;
static Eet_Data_Descriptor *
_mouse_wheel_desc_make(void)
{
Eet_Data_Descriptor_Class eddc;
Eet_Data_Descriptor *_d;
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Exactness_Action_Mouse_Wheel);
_d = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Mouse_Wheel, "direction", direction, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Mouse_Wheel, "z", z, EET_T_INT);
return _d;
}
static Eet_Data_Descriptor *
_key_down_up_desc_make(void)
{
Eet_Data_Descriptor_Class eddc;
Eet_Data_Descriptor *_d;
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Exactness_Action_Key_Down_Up);
_d = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Key_Down_Up, "keyname", keyname, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Key_Down_Up, "key", key, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Key_Down_Up, "string", string, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Key_Down_Up, "compose", compose, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Key_Down_Up, "keycode", keycode, EET_T_INT);
return _d;
}
static Eet_Data_Descriptor *
_multi_event_desc_make(void)
{
Eet_Data_Descriptor_Class eddc;
Eet_Data_Descriptor *_d;
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Exactness_Action_Multi_Event);
_d = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Event, "d", d, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Event, "b", b, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Event, "x", x, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Event, "y", y, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Event, "rad", rad, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Event, "radx", radx, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Event, "rady", rady, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Event, "pres", pres, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Event, "ang", ang, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Event, "fx", fx, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Event, "fy", fy, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Event, "flags", flags, EET_T_INT);
return _d;
}
static Eet_Data_Descriptor *
_multi_move_desc_make(void)
{
Eet_Data_Descriptor_Class eddc;
Eet_Data_Descriptor *_d;
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Exactness_Action_Multi_Move);
_d = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Move, "d", d, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Move, "x", x, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Move, "y", y, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Move, "rad", rad, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Move, "radx", radx, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Move, "rady", rady, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Move, "pres", pres, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Move, "ang", ang, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Move, "fx", fx, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Move, "fy", fy, EET_T_DOUBLE);
return _d;
}
static Eet_Data_Descriptor *
_efl_event_desc_make(void)
{
Eet_Data_Descriptor_Class eddc;
Eet_Data_Descriptor *_d;
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Exactness_Action_Efl_Event);
_d = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Efl_Event, "wdg_name", wdg_name, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Efl_Event, "event_name", event_name, EET_T_STRING);
return _d;
}
static Eet_Data_Descriptor *
_click_on_desc_make(void)
{
Eet_Data_Descriptor_Class eddc;
Eet_Data_Descriptor *_d;
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Exactness_Action_Click_On);
_d = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Click_On, "wdg_name", wdg_name, EET_T_STRING);
return _d;
}
static Eet_Data_Descriptor *
_dummy_desc_make(void)
{
Eet_Data_Descriptor_Class eddc;
Eet_Data_Descriptor *_d;
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, _Dummy);
_d = eet_data_descriptor_stream_new(&eddc);
return _d;
}
/* !!! SAME ORDER AS Exactness_Action_Type */
static const char *_mapping[] =
{
"",
"exactness_action_mouse_in",
"exactness_action_mouse_out",
"exactness_action_mouse_wheel",
"exactness_action_multi_down",
"exactness_action_multi_up",
"exactness_action_multi_move",
"exactness_action_key_down",
"exactness_action_key_up",
"exactness_action_take_shot",
"exactness_action_efl_event",
"exactness_action_click_on",
"exactness_action_stabilize"
};
const char *
_exactness_action_type_to_string_get(Exactness_Action_Type type)
{
if (type <= EXACTNESS_ACTION_LAST) return _mapping[type];
return NULL;
}
static const char *
_variant_type_get(const void *data, Eina_Bool *unknow)
{
const Exactness_Action *act = data;
if (unknow) *unknow = EINA_FALSE;
if (act->type <= EXACTNESS_ACTION_LAST) return _mapping[act->type];
return NULL;
}
static Eina_Bool
_variant_type_set(const char *type,
void *data,
Eina_Bool unknow EINA_UNUSED)
{
int i;
Exactness_Action *act = data;
for (i = 0; i <= EXACTNESS_ACTION_LAST; i++)
{
if (!strcmp(_mapping[i], type)) act->type = i;
}
return EINA_TRUE;
}
static Eet_Data_Descriptor *
_unit_desc_make(void)
{
Eet_Data_Descriptor_Class eddc;
static Eet_Data_Descriptor *unit_d = NULL;
static Eet_Data_Descriptor *action_d = NULL, *action_variant_d = NULL;
static Eet_Data_Descriptor *objs_d = NULL;
static Eet_Data_Descriptor *obj_d = NULL;
if (!obj_d)
{
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Exactness_Object);
obj_d = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(obj_d, Exactness_Object, "kl_name", kl_name, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(obj_d, Exactness_Object, "id", id, EET_T_ULONG_LONG);
EET_DATA_DESCRIPTOR_ADD_BASIC(obj_d, Exactness_Object, "parent_id", parent_id, EET_T_ULONG_LONG);
/* Evas stuff */
EET_DATA_DESCRIPTOR_ADD_BASIC(obj_d, Exactness_Object, "x", x, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC(obj_d, Exactness_Object, "y", y, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC(obj_d, Exactness_Object, "w", w, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC(obj_d, Exactness_Object, "h", h, EET_T_INT);
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Exactness_Objects);
objs_d = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_LIST(objs_d, Exactness_Objects, "objs", objs, obj_d);
}
if (!unit_d)
{
Eet_Data_Descriptor *code_d = NULL;
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Exactness_Source_Code);
code_d = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(code_d, Exactness_Source_Code, "language", language, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(code_d, Exactness_Source_Code, "content", content, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(code_d, Exactness_Source_Code, "command", command, EET_T_STRING);
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Exactness_Action);
action_d = eet_data_descriptor_stream_new(&eddc);
eddc.version = EET_DATA_DESCRIPTOR_CLASS_VERSION;
eddc.func.type_get = _variant_type_get;
eddc.func.type_set = _variant_type_set;
action_variant_d = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_MAPPING(action_variant_d,
_mapping[EXACTNESS_ACTION_MOUSE_IN], _dummy_desc_make());
EET_DATA_DESCRIPTOR_ADD_MAPPING(action_variant_d,
_mapping[EXACTNESS_ACTION_MOUSE_OUT], _dummy_desc_make());
EET_DATA_DESCRIPTOR_ADD_MAPPING(action_variant_d,
_mapping[EXACTNESS_ACTION_MOUSE_WHEEL], _mouse_wheel_desc_make());
EET_DATA_DESCRIPTOR_ADD_MAPPING(action_variant_d,
_mapping[EXACTNESS_ACTION_MULTI_DOWN], _multi_event_desc_make());
EET_DATA_DESCRIPTOR_ADD_MAPPING(action_variant_d,
_mapping[EXACTNESS_ACTION_MULTI_UP], _multi_event_desc_make());
EET_DATA_DESCRIPTOR_ADD_MAPPING(action_variant_d,
_mapping[EXACTNESS_ACTION_MULTI_MOVE], _multi_move_desc_make());
EET_DATA_DESCRIPTOR_ADD_MAPPING(action_variant_d,
_mapping[EXACTNESS_ACTION_KEY_DOWN], _key_down_up_desc_make());
EET_DATA_DESCRIPTOR_ADD_MAPPING(action_variant_d,
_mapping[EXACTNESS_ACTION_KEY_UP], _key_down_up_desc_make());
EET_DATA_DESCRIPTOR_ADD_MAPPING(action_variant_d,
_mapping[EXACTNESS_ACTION_TAKE_SHOT], _dummy_desc_make());
EET_DATA_DESCRIPTOR_ADD_MAPPING(action_variant_d,
_mapping[EXACTNESS_ACTION_EFL_EVENT], _efl_event_desc_make());
EET_DATA_DESCRIPTOR_ADD_MAPPING(action_variant_d,
_mapping[EXACTNESS_ACTION_CLICK_ON], _click_on_desc_make());
EET_DATA_DESCRIPTOR_ADD_MAPPING(action_variant_d,
_mapping[EXACTNESS_ACTION_STABILIZE], _dummy_desc_make());
EET_DATA_DESCRIPTOR_ADD_BASIC(action_d, Exactness_Action, "n_evas", n_evas, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_BASIC(action_d, Exactness_Action, "delay_ms", delay_ms, EET_T_UINT);
EET_DATA_DESCRIPTOR_ADD_VARIANT(action_d, Exactness_Action, "data", data, type, action_variant_d);
/* Exactness_Unit */
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Exactness_Unit);
unit_d = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_LIST(unit_d, Exactness_Unit, "actions", actions, action_d);
EET_DATA_DESCRIPTOR_ADD_LIST(unit_d, Exactness_Unit, "objs", objs, objs_d);
EET_DATA_DESCRIPTOR_ADD_LIST(unit_d, Exactness_Unit, "codes", codes, code_d);
EET_DATA_DESCRIPTOR_ADD_BASIC(unit_d, Exactness_Unit, "fonts_path", fonts_path, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(unit_d, Exactness_Unit, "nb_shots", nb_shots, EET_T_UINT);
}
return unit_d;
}
/* END Event struct descriptors */
EAPI Exactness_Unit *
exactness_unit_file_read(const char *filename)
{
int i;
Eina_List *itr, *itr2;
Exactness_Objects *e_objs;
Exactness_Object *e_obj, *e_parent;
Exactness_Unit *unit = NULL;
Eet_File *file;
eet_init();
file = eet_open(filename, EET_FILE_MODE_READ);
if (!file)
{
fprintf(stderr, "Impossible to extract EET from %s\n", filename);
return NULL;
}
unit = eet_data_read(file, _unit_desc_make(), "cache");
for (i = 0; i < unit->nb_shots; i++)
{
char entry[32];
Exactness_Image *ex_img = malloc(sizeof(*ex_img));
sprintf(entry, "images/%d", i + 1);
ex_img->pixels = eet_data_image_read(file, entry,
&ex_img->w, &ex_img->h, NULL,
NULL, NULL, NULL);
unit->imgs = eina_list_append(unit->imgs, ex_img);
}
EINA_LIST_FOREACH(unit->objs, itr, e_objs)
{
Eina_Hash *hash = eina_hash_pointer_new(NULL);
EINA_LIST_FOREACH(e_objs->objs, itr2, e_obj)
{
eina_hash_set(hash, &(e_obj->id), e_obj);
}
EINA_LIST_FOREACH(e_objs->objs, itr2, e_obj)
{
if (!e_obj->parent_id)
e_objs->main_objs = eina_list_append(e_objs->main_objs, e_obj);
else
{
e_parent = eina_hash_find(hash, &(e_obj->parent_id));
if (e_parent) e_parent->children = eina_list_append(e_parent->children, e_obj);
}
}
eina_hash_free(hash);
}
eet_close(file);
eet_shutdown();
return unit;
}
EAPI Eina_Bool
exactness_unit_file_write(Exactness_Unit *unit, const char *filename)
{
Eina_List *itr;
Exactness_Image *ex_img;
Eet_File *file;
int i = 1;
eet_init();
file = eet_open(filename, EET_FILE_MODE_WRITE);
eet_data_write(file, _unit_desc_make(), "cache", unit, EINA_TRUE);
EINA_LIST_FOREACH(unit->imgs, itr, ex_img)
{
char entry[32];
sprintf(entry, "images/%d", i++);
eet_data_image_write(file, entry,
ex_img->pixels, ex_img->w, ex_img->h, 0xFF,
0, 100, EET_IMAGE_LOSSLESS);
}
eet_close(file);
eet_shutdown();
return EINA_TRUE;
}
EAPI Eina_Bool
exactness_image_compare(Exactness_Image *img1, Exactness_Image *img2, Exactness_Image **imgO)
{
unsigned int w, h;
int *pxs1, *pxs2, *pxsO = NULL;
unsigned int w1 = img1 ? img1->w : 0, h1 = img1 ? img1->h : 0;
unsigned int w2 = img2 ? img2->w : 0, h2 = img2 ? img2->h : 0;
unsigned int wO = MAX(w1, w2);
unsigned int hO = MAX(h1, h2);
Eina_Bool ret = EINA_FALSE;
if (imgO) *imgO = NULL;
if (!wO || !hO) return EINA_FALSE;
pxs1 = img1 ? img1->pixels : NULL;
pxs2 = img2 ? img2->pixels : NULL;
if (imgO) pxsO = malloc(wO * hO * 4);
for (w = 0; w < wO; w++)
{
for (h = 0; h < hO; h++)
{
Eina_Bool valid1 = img1 ? w < w1 && h < h1 : EINA_FALSE;
Eina_Bool valid2 = img2 ? w < w2 && h < h2 : EINA_FALSE;
int px1 = valid1 ? pxs1[h * w1 + w] : 0;
int px2 = valid2 ? pxs2[h * w2 + w] : 0;
int r1 = (px1 & 0x00FF0000) >> 16;
int r2 = (px2 & 0x00FF0000) >> 16;
int g1 = (px1 & 0x0000FF00) >> 8;
int g2 = (px2 & 0x0000FF00) >> 8;
int b1 = (px1 & 0x000000FF);
int b2 = (px2 & 0x000000FF);
int new_r, new_g, new_b;
if (valid1 || valid2)
{
if (px1 != px2)
{
new_r = 0xFF;
new_g = ((g1 + g2) >> 1) >> 2;
new_b = ((b1 + b2) >> 1) >> 2;
ret = EINA_TRUE;
}
else
{
new_r = (((r1 + r2) >> 1) >> 2) + 0xC0;
new_g = (((g1 + g2) >> 1) >> 2) + 0xC0;
new_b = (((b1 + b2) >> 1) >> 2) + 0xC0;
}
}
else
{
new_r = new_g = new_b = 0x0;
}
if (pxsO) pxsO[h * wO + w] = 0xFF000000 | new_r << 16 | new_g << 8 | new_b;
}
}
if (imgO)
{
Exactness_Image *imgR = calloc(1, sizeof(Exactness_Image));
*imgO = imgR;
imgR->w = wO;
imgR->h = hO;
imgR->pixels = pxsO;
}
return ret;
}
EAPI void exactness_image_free(Exactness_Image *img)
{
if (!img) return;
free(img->pixels);
free(img);
}