exactness: import code from external repo into efl.git

Exactness has been developed in a separate git repo for many years. This
finally moves it over into efl. Having it in tree allows us for easier
testing with our current main target elementary_test and integration
into our CI system (patches for this are work in progress already).

We are only importing the lib and binary for test execution, not the
full set of test data. This is would be over 500MB and thus it will stay
in a different repo and only made available during the actual testing.

[The original patch was made by Daniel Zaoui. Over the course of review
and testing it got extended with build fixes for API changes and mingw
compilation support from Stefan Schmidt and Michael Blumenkrantz]

Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Differential Revision: https://phab.enlightenment.org/D11285
This commit is contained in:
Daniel Zaoui 2018-12-24 22:51:52 +02:00 committed by Stefan Schmidt
parent 78ad088dd7
commit 50dbfcf31d
14 changed files with 7324 additions and 0 deletions

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();
mode_play = mode_init = mode_simulation = EINA_FALSE;
want_quit = EINA_FALSE;
_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)));
/* 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)
{
printf("%s %p\n", report_filename, 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,483 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <unistd.h>
#ifndef EFL_EO_API_SUPPORT
#define EFL_EO_API_SUPPORT
#endif
#include <Eina.h>
#include <Eet.h>
#include <Ecore.h>
#include <Ecore_Getopt.h>
#include <Elementary.h>
#include <Exactness.h>
#include "exactness_private.h"
typedef struct
{
Eina_Debug_Session *session;
int srcid;
void *buffer;
unsigned int size;
} _Main_Loop_Info;
#define WRAPPER_TO_XFER_MAIN_LOOP(foo) \
static void \
_intern_main_loop ## foo(void *data) \
{ \
_Main_Loop_Info *info = data; \
_main_loop ## foo(info->session, info->srcid, info->buffer, info->size); \
free(info->buffer); \
free(info); \
} \
static Eina_Bool \
foo(Eina_Debug_Session *session, int srcid, void *buffer, int size) \
{ \
_Main_Loop_Info *info = calloc(1, sizeof(*info)); \
info->session = session; \
info->srcid = srcid; \
info->size = size; \
if (info->size) \
{ \
info->buffer = malloc(info->size); \
memcpy(info->buffer, buffer, info->size); \
} \
ecore_main_loop_thread_safe_call_async(_intern_main_loop ## foo, info); \
return EINA_TRUE; \
}
#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)
{
static Eina_Bool on = EINA_FALSE;
if (status)
{
if (!on)
{
eina_debug_session_send(_session, 0, _all_apps_get_op, NULL, 0);
}
on = EINA_TRUE;
}
}
static const Ecore_Getopt optdesc = {
"exactness_inject",
"%prog [options] <-v|-p|-t|-h> command",
PACKAGE_VERSION,
"(C) 2018 Enlightenment",
"BSD",
"A scenario events injector for EFL based applications.",
1,
{
ECORE_GETOPT_STORE_STR('t', "test", "Test to run on the given application"),
ECORE_GETOPT_STORE_INT('p', "pid", "PID of the application to connect to"),
ECORE_GETOPT_STORE_INT('r', "remote-port", "Port to connect remotely to the daemon. Local connection if not specified"),
ECORE_GETOPT_COUNT('v', "verbose", "Turn verbose messages on."),
ECORE_GETOPT_LICENSE('L', "license"),
ECORE_GETOPT_COPYRIGHT('C', "copyright"),
ECORE_GETOPT_VERSION('V', "version"),
ECORE_GETOPT_HELP('h', "help"),
ECORE_GETOPT_SENTINEL
}
};
int main(int argc, char **argv)
{
int opt_args = 0, real__ = 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:
eet_shutdown();
eina_shutdown();
return real__;
}

1653
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,
)

1393
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,531 @@
#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
#ifndef EFL_EO_API_SUPPORT
#define EFL_EO_API_SUPPORT
#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 (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 end;
}
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;
end:
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,876 @@
#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
)

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

@ -0,0 +1,424 @@
#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_in_out_desc_make(void)
{
Eet_Data_Descriptor_Class eddc;
Eet_Data_Descriptor *_d;
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Exactness_Action_Mouse_In_Out);
_d = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Mouse_In_Out, "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, 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);
}