diff --git a/configure.bat b/configure.bat index 57eef43029..4207191f6a 100644 --- a/configure.bat +++ b/configure.bat @@ -139,6 +139,7 @@ exit /B 0 -Dlibmount=false^ "-Devas-loaders-disabler=gst,pdf,ps,raw,svg,rsvg,xcf,bmp,dds,generic,gif,ico,jp2k,pmaps,psd,tga,tgv,tiff,wbmp,webp,xpm,json"^ -Dopengl=none^ + -Dexactness-win32=true^ "-Demotion-loaders-disabler=gstreamer1,libvlc,xine"^ -Dbindings=^ --buildtype=debug^ diff --git a/meson.build b/meson.build index d4162af987..969324f500 100644 --- a/meson.build +++ b/meson.build @@ -225,6 +225,9 @@ foreach lang : ['c', 'objc', 'cpp'] error('Version of targetted Windows incorrect') endif add_global_arguments('-D__USE_MINGW_ANSI_STDIO', language: lang) + if get_option('exactness-win32') + add_global_arguments('-DEFL_EXACTNESS_WIN32', language: lang) + endif endif endforeach @@ -495,13 +498,14 @@ subprojects = [ if sys_windows ignored_subprojects = [ # temporarily ignored - 'exactness', ] + if get_option('exactness-win32') == false + ignored_subprojects += ['exactness'] + endif else ignored_subprojects = [] endif - _subprojects = [] foreach package : subprojects package_name = package[0] diff --git a/meson_options.txt b/meson_options.txt index d63e7084d1..c79ee8341b 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -344,6 +344,12 @@ option('dotnet', description: 'Enable building C# bindings with dotnet instead of mono' ) +option('exactness-win32', + type: 'boolean', + value: false, + description: 'Enable building Exactness on Windows' +) + option('lua-interpreter', type: 'combo', choices: ['luajit', 'lua'], diff --git a/src/bin/exactness/exactness.c b/src/bin/exactness/exactness.c index 715ad275be..035a30bc87 100644 --- a/src/bin/exactness/exactness.c +++ b/src/bin/exactness/exactness.c @@ -10,7 +10,9 @@ #include "common.h" #ifdef _WIN32 -# include /* mkdir */ +# include /* mkdir, dirname */ +#else +# include #endif #define SCHEDULER_CMD_SIZE 1024 @@ -44,6 +46,7 @@ typedef enum static unsigned short _running_jobs = 0, _max_jobs = 1; static Eina_List *_base_dirs = NULL; static char *_dest_dir; +static char dest_dir[PATH_MAX]; 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; @@ -110,17 +113,17 @@ _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); + 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); + 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); + char *buf = alloca(strlen(dest_dir) + strlen(ent_name)); + sprintf(buf, "%s/%s/comp_%s", dest_dir, CURRENT_SUBDIR, ent_name); if (!_image_save(imgO, buf)) goto cleanup; _compare_errors = eina_list_append(_compare_errors, strdup(ent_name)); @@ -164,7 +167,7 @@ static void _run_test_compare(const List_Entry *ent) { char *path = alloca(PATH_MAX); - char *origdir = alloca(strlen(_dest_dir) + 20); + char *origdir = alloca(strlen(dest_dir) + 20); const char *base_dir; Eina_List *itr; int n = 1, nb_fails = 0; @@ -175,7 +178,7 @@ _run_test_compare(const List_Entry *ent) if (ecore_file_exists(path)) { char *currentdir; - sprintf(origdir, "%s/%s/%s", _dest_dir, CURRENT_SUBDIR, ORIG_SUBDIR); + sprintf(origdir, "%s/%s/%s", dest_dir, CURRENT_SUBDIR, ORIG_SUBDIR); if (!ecore_file_exists(origdir)) { if (mkdir(origdir, 0744) < 0) @@ -185,9 +188,10 @@ _run_test_compare(const List_Entry *ent) } } _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); + 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; } @@ -228,9 +232,13 @@ _run_command_prepare(const List_Entry *ent, char *buf) ok: sbuf = eina_strbuf_new(); printf("STATUS %s: START\n", ent->name); + + if (_wrap_command) + eina_strbuf_append_printf(sbuf, "%s", _wrap_command); + eina_strbuf_append_printf(sbuf, - "%s exactness_play %s %s%s %s%.*s %s%s%s-t '%s' ", - _wrap_command ? _wrap_command : "", + "python %s/exactness_play.py %s %s%s %s%.*s %s%s%s-t \"%s\" ", + PACKAGE_BIN_DIR, _mode == RUN_SIMULATION ? "-s" : "", _fonts_dir ? "-f " : "", _fonts_dir ? _fonts_dir : "", _verbose ? "-" : "", _verbose, "vvvvvvvvvv", @@ -241,12 +249,13 @@ _run_command_prepare(const List_Entry *ent, char *buf) ); if (_mode == RUN_PLAY) - eina_strbuf_append_printf(sbuf, "-o '%s/%s/%s.exu' ", _dest_dir, CURRENT_SUBDIR, ent->name); + 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); + eina_strbuf_append_printf(sbuf, "-o \"%s\" ", scn_path); if (ent->command) { + eina_strbuf_append(sbuf, "-- "); eina_strbuf_append(sbuf, CONFIG); eina_strbuf_append(sbuf, ent->command); @@ -345,6 +354,9 @@ _list_file_load(const char *filename) return NULL; } + char *_test_file_dir = realpath(filename, NULL); + _test_file_dir = dirname(_test_file_dir); + while (fgets(buf, BUF_SIZE, file)) { /* Skip comment/empty lines. */ @@ -360,7 +372,9 @@ _list_file_load(const char *filename) if (tmp) { *tmp = '\0'; - cur->command = tmp + 1; + char *command; + asprintf(&command, "%s/%s", _test_file_dir, tmp + 1); + cur->command = command; } else { @@ -380,6 +394,8 @@ _list_file_load(const char *filename) List_Entry); } + free(_test_file_dir); + fclose(file); return ret; } @@ -497,11 +513,15 @@ main(int argc, char *argv[]) ECORE_GETOPT_VALUE_NONE }; + // Force to use the buffer engine + setenv("ELM_DISPLAY", "buffer", 1); + setenv("ECORE_EVAS_ENGINE", "buffer", 1); + if (!ecore_evas_init()) return EXIT_FAILURE; _log_domain = eina_log_domain_register("exactness", "red"); - _dest_dir = "./"; + _dest_dir = "."; _scan_objs = scan_objs; eina_log_abort_on_critical_set(EINA_TRUE); @@ -549,6 +569,15 @@ main(int argc, char *argv[]) goto end; } + /* Get absolute path for all parameters */ + EINA_LIST_FOREACH(_base_dirs, itr, base_dir) + { + char _resolved_base_dir[PATH_MAX]; + realpath(base_dir, _resolved_base_dir); + eina_list_data_set(itr, _resolved_base_dir); + } + realpath(_dest_dir, dest_dir); + /* Pre-run summary */ fprintf(stderr, "Running with settings:\n"); fprintf(stderr, "\tConcurrent jobs: %d\n", _max_jobs); @@ -556,12 +585,12 @@ main(int argc, char *argv[]) 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); + fprintf(stderr, "\tDest dir: %s\n", dest_dir); if (mode_play) { _mode = RUN_PLAY; - if (snprintf(tmp, PATH_MAX, "%s/%s", _dest_dir, CURRENT_SUBDIR) + if (snprintf(tmp, PATH_MAX, "%s/%s", dest_dir, CURRENT_SUBDIR) >= PATH_MAX) { fprintf(stderr, "Path too long: %s", tmp); @@ -581,7 +610,7 @@ main(int argc, char *argv[]) else if (mode_init) { _mode = RUN_INIT; - if (snprintf(tmp, PATH_MAX, "%s/%s", _dest_dir, ORIG_SUBDIR) + if (snprintf(tmp, PATH_MAX, "%s/%s", dest_dir, ORIG_SUBDIR) >= PATH_MAX) { fprintf(stderr, "Path too long: %s", tmp); @@ -637,7 +666,7 @@ main(int argc, char *argv[]) /* Generate the filename. */ snprintf(report_filename, PATH_MAX, "%s/%s/errors.html", - _dest_dir, mode_init ? ORIG_SUBDIR : CURRENT_SUBDIR); + dest_dir, mode_init ? ORIG_SUBDIR : CURRENT_SUBDIR); report_file = fopen(report_filename, "w+"); if (report_file) { @@ -671,7 +700,7 @@ main(int argc, char *argv[]) Eina_Bool is_from_exu; char origpath[PATH_MAX]; snprintf(origpath, PATH_MAX, "%s/%s/orig/%s", - _dest_dir, CURRENT_SUBDIR, test_name); + dest_dir, CURRENT_SUBDIR, test_name); is_from_exu = ecore_file_exists(origpath); printf("\t* %s\n", test_name); diff --git a/src/bin/exactness/exactness_play.in b/src/bin/exactness/exactness_play.in index 38200d9ba1..a9fb0fbd2a 100644 --- a/src/bin/exactness/exactness_play.in +++ b/src/bin/exactness/exactness_play.in @@ -48,7 +48,11 @@ if G.version: exit(0) spawn_env = os.environ.copy() -spawn_env["LD_PRELOAD"] = @EXACTNESS_PLAY_PRELOAD_PATH@ +if os.name == 'nt': + # Windows + spawn_env["EXACTNESS_PRELOAD_WIN32"] = "PLAY" +else: + spawn_env["LD_PRELOAD"] = @EXACTNESS_PLAY_PRELOAD_PATH@ if G.tests == None and G.external_injection == True: print("no test file specified") @@ -69,7 +73,7 @@ if G.tests != None: if G.fontsdir != None: spawn_env["EXACTNESS_FONTS_DIR"] = G.fontsdir if G.speed != 1.0: - spawn_env["EXACTNESS_SPEED"] = G.speed + spawn_env["EXACTNESS_SPEED"] = str(G.speed) if G.scan_objects: spawn_env["EXACTNESS_SCAN_OBJECTS"] = "Yes" if G.disable_screenshots: @@ -80,6 +84,7 @@ if G.verbose: spawn_env["EXACTNESS_VERBOSE"] = "Yes" if G.show_on_screen == False: spawn_env["ELM_DISPLAY"] = "buffer" + spawn_env["ECORE_EVAS_ENGINE"] = "buffer" passed_all_the_env_vars = False app = [] @@ -97,5 +102,6 @@ for argument in G.app: if passed_all_the_env_vars: app.append(argument) -recorder = subprocess.Popen(app, env=spawn_env) -recorder.wait() +with subprocess.Popen(app, env=spawn_env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True) as p: + for line in p.stdout: + print(line, end='') diff --git a/src/bin/exactness/exactness_record.in b/src/bin/exactness/exactness_record.in index 377d465199..84f359d12e 100644 --- a/src/bin/exactness/exactness_record.in +++ b/src/bin/exactness/exactness_record.in @@ -45,7 +45,11 @@ if G.version: exit(0) spawn_env = os.environ.copy() -spawn_env["LD_PRELOAD"] = @EXACTNESS_RECORD_PRELOAD_PATH@ +if os.name == 'nt': + # Windows + spawn_env["EXACTNESS_PRELOAD_WIN32"] = "RECORD" +else: + spawn_env["LD_PRELOAD"] = @EXACTNESS_PLAY_PRELOAD_PATH@ if G.tests != None: spawn_env["EXACTNESS_DEST"] = G.tests @@ -72,5 +76,6 @@ for argument in G.app: if passed_all_the_env_vars: app.append(argument) -recorder = subprocess.Popen(app, env=spawn_env) -recorder.wait() +with subprocess.Popen(app, env=spawn_env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True) as p: + for line in p.stdout: + print(line, end='') diff --git a/src/bin/exactness/meson.build b/src/bin/exactness/meson.build index 4d048f18c9..fb93924b27 100644 --- a/src/bin/exactness/meson.build +++ b/src/bin/exactness/meson.build @@ -23,14 +23,15 @@ edjs = custom_target('player_entry', input : 'player_entry.edc', output : 'player_entry.edj', install : true, - install_dir : 'share/exactness', + install_dir : join_paths('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'), + '-in-tree', '@INPUT@', '@OUTPUT@'], depends : edje_depends) -exactness_play_bin = library('exactness_play', +exactness_play_lib = library('exactness_play', [ 'player.c', 'common.c', 'common.h', edjs ], dependencies: [ elementary, dl], c_args: '-DDATA_DIR="'+join_paths(dir_data, 'exactness')+'"', @@ -38,29 +39,42 @@ exactness_play_bin = library('exactness_play', version : meson.project_version() ) -exactness_record_bin = library('exactness_record', +exactness_record_deps = [ elementary, dl] +if sys_windows + winmm = cc.find_library('winmm') + exactness_record_deps += winmm +endif + +exactness_record_lib = library('exactness_record', [ 'recorder.c', 'common.c', 'common.h' ], - dependencies: [ elementary, dl], + dependencies: exactness_record_deps, c_args: '-DDATA_DIR="'+join_paths(dir_data, 'exactness')+'"', install: true, version : meson.project_version() ) +exactness_play_lib_path = join_paths( + get_option('prefix'), get_option('libdir'), + 'lib' + exactness_play_lib.name() + '.so.' + meson.project_version() ) +exactness_record_lib_path = join_paths( + get_option('prefix'), get_option('libdir'), + 'lib' + exactness_record_lib.name() + '.so.' + meson.project_version() ) + exactness_env = configuration_data() -exactness_env.set_quoted('EXACTNESS_PLAY_PRELOAD_PATH', exactness_play_bin.full_path()) -exactness_env.set_quoted('EXACTNESS_RECORD_PRELOAD_PATH', exactness_record_bin.full_path()) +exactness_env.set_quoted('EXACTNESS_PLAY_PRELOAD_PATH', exactness_play_lib_path) +exactness_env.set_quoted('EXACTNESS_RECORD_PRELOAD_PATH', exactness_record_lib_path) exactness_env.set_quoted('VERSION', meson.project_version()) configure_file( input: 'exactness_record.in', - output: 'exactness_record', + output: 'exactness_record.py', configuration: exactness_env, install_dir: get_option('bindir'), install_mode: 'rwxr-xr-x') configure_file( input: 'exactness_play.in', - output: 'exactness_play', + output: 'exactness_play.py', configuration: exactness_env, install_dir: get_option('bindir'), install_mode: 'rwxr-xr-x') diff --git a/src/bin/exactness/player.c b/src/bin/exactness/player.c index 278c72422f..427052e1bf 100644 --- a/src/bin/exactness/player.c +++ b/src/bin/exactness/player.c @@ -7,10 +7,11 @@ #include #ifndef _MSC_VER # include -#endif - -#ifdef HAVE_DLSYM -# include +# ifdef HAVE_DLSYM +# include +# endif +#else +# include #endif #ifdef HAVE_FORK @@ -84,6 +85,7 @@ static Eina_Bool _exit_required = EINA_FALSE; static Eina_Bool _pause_request = EINA_FALSE; static Eina_Bool _playing_status = EINA_FALSE; static Eina_Bool _ready_to_write = EINA_FALSE; +static Eina_Bool _output_written = EINA_FALSE; static Exactness_Image * _snapshot_shot_get(Evas *e) @@ -1014,45 +1016,52 @@ _setup_ee_creation(void) ecore_idler_add(_src_feed, NULL); } -static void +static Eina_Bool _write_unit_file(void) { if (_dest && _dest_unit && _ready_to_write) { Exactness_Unit *tmp = NULL; - EINA_SAFETY_ON_NULL_RETURN(_src_unit); + if (!_src_unit) return EINA_FALSE; if (_src_type == FTYPE_EXU) { tmp = exactness_unit_file_read(_src_filename); _dest_unit->actions = tmp->actions; } - exactness_unit_file_write(_dest_unit, _dest); + return exactness_unit_file_write(_dest_unit, _dest); } + return EINA_FALSE; } -#ifdef HAVE_DLSYM + +#ifndef _WIN32 +# ifdef HAVE_DLSYM +# define ORIGINAL_CALL_T(t, name, ...) \ + t (*_original_init_cb)(); \ + _original_init_cb = dlsym(RTLD_NEXT, #name); \ + original_return = _original_init_cb(__VA_ARGS__); +# else +# define ORIGINAL_CALL_T(t, name, ...) \ + printf("THIS IS NOT SUPPORTED WITHOUT DLSYM\n"); \ + abort(); +# endif +#else # define ORIGINAL_CALL_T(t, name, ...) \ t (*_original_init_cb)(); \ - _original_init_cb = dlsym(RTLD_NEXT, name); \ + _original_init_cb = & name ## _original; \ original_return = _original_init_cb(__VA_ARGS__); -#else -# define ORIGINAL_CALL_T(t, name, ...) \ - printf("THIS IS NOT SUPPORTED ON WINDOWS\n"); \ - abort(); #endif #define ORIGINAL_CALL(name, ...) \ - ORIGINAL_CALL_T(int, name, __VA_ARGS__) + ORIGINAL_CALL_T(int , name, __VA_ARGS__) int eina_init(void) { int original_return; - ORIGINAL_CALL("eina_init"); - + ORIGINAL_CALL(eina_init); ex_set_original_envvar(); - if (original_return == 1) { const char *dest = getenv("EXACTNESS_DEST"); @@ -1092,8 +1101,7 @@ ecore_evas_init(void) { int original_return; - ORIGINAL_CALL("ecore_evas_init") - + ORIGINAL_CALL(ecore_evas_init); if (ex_is_original_app() && original_return == 1) { _setup_ee_creation(); @@ -1107,8 +1115,8 @@ int elm_init(int argc, char **argv) { int original_return; - ORIGINAL_CALL("elm_init", argc, argv) + ORIGINAL_CALL(elm_init, argc, argv); if (ex_is_original_app() && original_return == 1) ex_prepare_elm_overlay(); @@ -1119,17 +1127,19 @@ void ecore_main_loop_begin(void) { int original_return; - ORIGINAL_CALL("ecore_main_loop_begin") + + ORIGINAL_CALL(ecore_main_loop_begin); if (ex_is_original_app()) _write_unit_file(); (void)original_return; } -Eina_Value* +Eina_Value * efl_loop_begin(Eo *obj) { Eina_Value *original_return; - ORIGINAL_CALL_T(Eina_Value*, "efl_loop_begin", obj); + + ORIGINAL_CALL_T(Eina_Value*, efl_loop_begin, obj); if (ex_is_original_app()) _write_unit_file(); return original_return; @@ -1139,13 +1149,65 @@ int eina_shutdown(void) { int original_return; - static Eina_Bool output_written = EINA_FALSE; - ORIGINAL_CALL("eina_shutdown") - if (ex_is_original_app() &&original_return == 1 && !output_written) + + ORIGINAL_CALL(eina_shutdown); + if (ex_is_original_app() &&original_return == 1 && !_output_written) { - output_written = EINA_TRUE; - _write_unit_file(); + _output_written = _write_unit_file(); } return original_return; } + +#ifdef _WIN32 + +void exactness_init(void) +{ + eina_init_redirect = eina_init; + eina_shutdown_redirect = eina_shutdown; + efl_loop_begin_redirect = efl_loop_begin; + elm_init_redirect = elm_init; + ecore_evas_init_redirect = ecore_evas_init; + ecore_main_loop_begin_redirect = ecore_main_loop_begin; +} + +void exactness_shutdown(void) +{ + eina_init_redirect = NULL; + eina_shutdown_redirect = NULL; + efl_loop_begin_redirect = NULL; + elm_init_redirect = NULL; + ecore_evas_init_redirect = NULL; + ecore_main_loop_begin_redirect = NULL; + + if (!_output_written) + { + _output_written = _write_unit_file(); + } +} + +BOOL WINAPI +DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) +{ + switch (reason) + { + case DLL_PROCESS_ATTACH: + exactness_init(); + break; + case DLL_PROCESS_DETACH: + exactness_shutdown(); + break; + case DLL_THREAD_ATTACH: + exactness_init(); + break; + case DLL_THREAD_DETACH: + exactness_shutdown(); + break; + default: + break; + } + + return TRUE; +} + +#endif /* _WIN32 */ diff --git a/src/bin/exactness/recorder.c b/src/bin/exactness/recorder.c index 4e703c49b9..2162c202ee 100644 --- a/src/bin/exactness/recorder.c +++ b/src/bin/exactness/recorder.c @@ -7,10 +7,14 @@ #include #ifndef _MSC_VER # include +# ifdef HAVE_DLSYM +# include +# endif +#else +# include #endif - -#ifdef HAVE_DLSYM -# include +#ifdef _WIN32 +# include // timeGetTime() #endif #include @@ -139,7 +143,7 @@ _event_pointer_cb(void *data, const Efl_Event *event) 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 }; + fx, fy, (Evas_Button_Flags)flags }; if (n_evas >= 0) _add_to_list(evt, n_evas, timestamp, &t, sizeof(t)); break; } @@ -293,18 +297,29 @@ static void _setup_ee_creation(void) { ecore_evas_callback_new_set(_my_evas_new); +#ifdef _WIN32 + _last_timestamp = timeGetTime(); +#else _last_timestamp = ecore_time_get() * 1000; +#endif } -#ifdef HAVE_DLSYM +#ifndef _WIN32 +# ifdef HAVE_DLSYM +# define ORIGINAL_CALL_T(t, name, ...) \ + t (*_original_init_cb)(); \ + _original_init_cb = dlsym(RTLD_NEXT, #name); \ + original_return = _original_init_cb(__VA_ARGS__); +# else +# define ORIGINAL_CALL_T(t, name, ...) \ + printf("THIS IS NOT SUPPORTED WITHOUT DLSYM\n"); \ + abort(); +# endif +#else # define ORIGINAL_CALL_T(t, name, ...) \ t (*_original_init_cb)(); \ - _original_init_cb = dlsym(RTLD_NEXT, name); \ + _original_init_cb = & name ## _original; \ original_return = _original_init_cb(__VA_ARGS__); -#else -# define ORIGINAL_CALL_T(t, name, ...) \ - printf("THIS IS NOT SUPPORTED ON WINDOWS\n"); \ - abort(); #endif #define ORIGINAL_CALL(name, ...) \ @@ -315,7 +330,7 @@ eina_init(void) { int original_return; - ORIGINAL_CALL("eina_init"); + ORIGINAL_CALL(eina_init); ex_set_original_envvar(); @@ -339,7 +354,7 @@ ecore_evas_init(void) { int original_return; - ORIGINAL_CALL("ecore_evas_init") + ORIGINAL_CALL(ecore_evas_init); if (ex_is_original_app() && original_return == 1) { @@ -355,7 +370,7 @@ int elm_init(int argc, char **argv) { int original_return; - ORIGINAL_CALL("elm_init", argc, argv) + ORIGINAL_CALL(elm_init, argc, argv); if (ex_is_original_app() && original_return == 1) ex_prepare_elm_overlay(); @@ -367,7 +382,7 @@ void ecore_main_loop_begin(void) { int original_return; - ORIGINAL_CALL("ecore_main_loop_begin") + ORIGINAL_CALL(ecore_main_loop_begin); if (ex_is_original_app()) _output_write(); (void)original_return; @@ -377,7 +392,7 @@ Eina_Value* efl_loop_begin(Eo *obj) { Eina_Value *original_return; - ORIGINAL_CALL_T(Eina_Value*, "efl_loop_begin", obj); + ORIGINAL_CALL_T(Eina_Value *, efl_loop_begin, obj); if (ex_is_original_app()) _output_write(); return original_return; @@ -388,7 +403,7 @@ eina_shutdown(void) { int original_return; static Eina_Bool output_written = EINA_FALSE; - ORIGINAL_CALL("eina_shutdown") + ORIGINAL_CALL(eina_shutdown); if (ex_is_original_app() && original_return == 1 && !output_written) { output_written = EINA_TRUE; @@ -397,3 +412,51 @@ eina_shutdown(void) return original_return; } + +#ifdef _WIN32 + +void exactness_init(void) +{ + eina_init_redirect = eina_init; + eina_shutdown_redirect = eina_shutdown; + efl_loop_begin_redirect = efl_loop_begin; + elm_init_redirect = elm_init; + ecore_evas_init_redirect = ecore_evas_init; + ecore_main_loop_begin_redirect = ecore_main_loop_begin; +} + +void exactness_shutdown(void) +{ + eina_init_redirect = NULL; + eina_shutdown_redirect = NULL; + efl_loop_begin_redirect = NULL; + elm_init_redirect = NULL; + ecore_evas_init_redirect = NULL; + ecore_main_loop_begin_redirect = NULL; +} + +BOOL WINAPI +DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) +{ + switch (reason) + { + case DLL_PROCESS_ATTACH: + exactness_init(); + break; + case DLL_PROCESS_DETACH: + exactness_shutdown(); + break; + case DLL_THREAD_ATTACH: + exactness_init(); + break; + case DLL_THREAD_DETACH: + exactness_shutdown(); + break; + default: + break; + } + + return TRUE; +} + +#endif /* _WIN32 */ diff --git a/src/lib/ecore/Ecore.h b/src/lib/ecore/Ecore.h index 623f296cef..eb7a638bef 100644 --- a/src/lib/ecore/Ecore.h +++ b/src/lib/ecore/Ecore.h @@ -306,6 +306,14 @@ extern "C" { ECORE_API double _ecore_main_loop_wakeup_time_get(void); +#ifdef EFL_EXACTNESS_WIN32 +# include "efl_loop_data.h" +typedef Eina_Value *(*efl_loop_begin_t)(Eo *obj); +extern ECORE_API efl_loop_begin_t efl_loop_begin_redirect; +ECORE_API ECORE_API_WEAK Eina_Value *efl_loop_begin_original(Eo *obj); + +#endif + #ifdef __cplusplus } #endif diff --git a/src/lib/ecore/Ecore_Common.h b/src/lib/ecore/Ecore_Common.h index aa2e8423db..d6841f3440 100644 --- a/src/lib/ecore/Ecore_Common.h +++ b/src/lib/ecore/Ecore_Common.h @@ -311,6 +311,11 @@ ECORE_API void ecore_main_loop_glib_always_integrate_disable(void); * timeout for the timers can be changed using * ecore_main_loop_select_func_set(). */ +#ifdef EFL_EXACTNESS_WIN32 +typedef void(*ecore_main_loop_begin_t)(void); +extern ECORE_API ecore_main_loop_begin_t ecore_main_loop_begin_redirect; +ECORE_API void ecore_main_loop_begin_original(void); +#endif ECORE_API void ecore_main_loop_begin(void); /** diff --git a/src/lib/ecore/ecore_main.c b/src/lib/ecore/ecore_main.c index 4bca7759f1..c56d06528c 100644 --- a/src/lib/ecore/ecore_main.c +++ b/src/lib/ecore/ecore_main.c @@ -1299,8 +1299,25 @@ ecore_main_loop_iterate_may_block(int may_block) return efl_loop_iterate_may_block(ML_OBJ, may_block); } +#ifdef EFL_EXACTNESS_WIN32 +ECORE_API ecore_main_loop_begin_t ecore_main_loop_begin_redirect = NULL; + +ECORE_API void +ecore_main_loop_begin(void) +{ + exactness_preload(); + if (ecore_main_loop_begin_redirect) + ecore_main_loop_begin_redirect(); + else + ecore_main_loop_begin_original(); +} + +ECORE_API void +ecore_main_loop_begin_original(void) +#else ECORE_API void ecore_main_loop_begin(void) +#endif { DBG("ecore_main_loop_begin"); EINA_MAIN_LOOP_CHECK_RETURN; diff --git a/src/lib/ecore/ecore_private.h b/src/lib/ecore/ecore_private.h index 5576bb99e7..5cfa65b61c 100644 --- a/src/lib/ecore/ecore_private.h +++ b/src/lib/ecore/ecore_private.h @@ -10,6 +10,8 @@ #include "ecore_event_message.eo.h" #include "ecore_event_message_handler.eo.h" +#include "efl_loop_data.h" + extern int _ecore_log_dom; #ifdef _ECORE_DEFAULT_LOG_DOM # undef _ECORE_DEFAULT_LOG_DOM @@ -62,9 +64,6 @@ typedef struct _Ecore_Factorized_Idle Ecore_Factorized_Idle; typedef struct _Efl_Loop_Promise_Simple_Data Efl_Loop_Promise_Simple_Data; -typedef struct _Efl_Loop_Timer_Data Efl_Loop_Timer_Data; -typedef struct _Efl_Loop_Data Efl_Loop_Data; - typedef struct _Efl_Task_Data Efl_Task_Data; typedef struct _Efl_Appthread_Data Efl_Appthread_Data; @@ -78,74 +77,6 @@ struct _Message Eina_Bool delete_me; }; -struct _Efl_Loop_Data -{ - double loop_time; - - Efl_Loop_Message_Handler *future_message_handler; - - Efl_Loop_Timer *poll_high; - Efl_Loop_Timer *poll_medium; - Efl_Loop_Timer *poll_low; - - Eina_List *exes; // only used in main loop (for now?) - - Eina_List *fd_handlers_obj; - - Ecore_Fd_Handler *fd_handlers; - Eina_List *fd_handlers_with_prep; - Eina_List *file_fd_handlers; - Eina_List *always_fd_handlers; - Eina_List *fd_handlers_with_buffer; - Eina_List *fd_handlers_to_delete; - Ecore_Fd_Handler *fd_handlers_to_call; - Ecore_Fd_Handler *fd_handlers_to_call_current; - -# ifdef _WIN32 - Ecore_Win32_Handler *win32_handlers; - Ecore_Win32_Handler *win32_handler_current; - Eina_List *win32_handlers_to_delete; -# endif - - Eina_List *thread_children; - - Eina_Inlist *message_queue; - Eina_Inlist *message_pending_queue; - unsigned int message_walking; - - unsigned int throttle; - - int epoll_fd; - pid_t epoll_pid; - int timer_fd; - - double last_check; - Eina_Inlist *timers; - Eina_Inlist *suspended; - Efl_Loop_Timer_Data *timer_current; - int timers_added; - - Eina_Value exit_code; - - int idlers; - int in_loop; - unsigned int loop_active; - - struct { - int high; - int medium; - int low; - } pollers; - - struct { - char **environ_ptr; - char **environ_copy; - } env; - - Eina_Bool do_quit : 1; - Eina_Bool quit_on_last_thread_child_del : 1; -}; - struct _Efl_Task_Data { Eina_Stringshare *command; diff --git a/src/lib/ecore/efl_loop.c b/src/lib/ecore/efl_loop.c index 84aa3f2c47..b688f948a2 100644 --- a/src/lib/ecore/efl_loop.c +++ b/src/lib/ecore/efl_loop.c @@ -19,6 +19,7 @@ #include "Ecore.h" #include "ecore_private.h" +#include "efl_loop_data.h" #include "ecore_main_common.h" @@ -56,8 +57,30 @@ _efl_loop_iterate_may_block(Eo *obj, Efl_Loop_Data *pd, int may_block) return _ecore_main_loop_iterate_may_block(obj, pd, may_block); } +#ifdef EFL_EXACTNESS_WIN32 +ECORE_API efl_loop_begin_t efl_loop_begin_redirect = NULL; + +EOLIAN static Eina_Value * +_efl_loop_begin_original(Eo *obj, Efl_Loop_Data *pd); + +ECORE_API ECORE_API_WEAK EFL_FUNC_BODY(efl_loop_begin_original, Eina_Value *, NULL); + EOLIAN static Eina_Value * _efl_loop_begin(Eo *obj, Efl_Loop_Data *pd) +{ + exactness_preload(); + if (efl_loop_begin_redirect) + return efl_loop_begin_redirect(obj); + else + return efl_loop_begin_original(obj); +} + +EOLIAN static Eina_Value * +_efl_loop_begin_original(Eo *obj, Efl_Loop_Data *pd) +#else +EOLIAN static Eina_Value * +_efl_loop_begin(Eo *obj, Efl_Loop_Data *pd) +#endif { _ecore_main_loop_begin(obj, pd); if (pd->thread_children) @@ -696,9 +719,18 @@ efl_loop_future_scheduler_get(const Eo *obj) return NULL; } -#define EFL_LOOP_EXTRA_OPS \ + +#ifdef EFL_EXACTNESS_WIN32 +# define EFL_LOOP_EXTRA_OPS \ + EFL_OBJECT_OP_FUNC(efl_loop_begin_original, _efl_loop_begin_original), \ EFL_OBJECT_OP_FUNC(efl_loop_message_process, _efl_loop_message_process), \ EFL_OBJECT_OP_FUNC(efl_loop_register, _efl_loop_register), \ EFL_OBJECT_OP_FUNC(efl_loop_unregister, _efl_loop_unregister) +#else +# define EFL_LOOP_EXTRA_OPS \ + EFL_OBJECT_OP_FUNC(efl_loop_message_process, _efl_loop_message_process), \ + EFL_OBJECT_OP_FUNC(efl_loop_register, _efl_loop_register), \ + EFL_OBJECT_OP_FUNC(efl_loop_unregister, _efl_loop_unregister) +#endif #include "efl_loop.eo.c" diff --git a/src/lib/ecore/efl_loop_data.h b/src/lib/ecore/efl_loop_data.h new file mode 100644 index 0000000000..15b6aa02f9 --- /dev/null +++ b/src/lib/ecore/efl_loop_data.h @@ -0,0 +1,76 @@ +#ifndef _EFL_LOOP_DATA_H +#define _EFL_LOOP_DATA_H + +typedef struct _Efl_Loop_Data Efl_Loop_Data; +typedef struct _Efl_Loop_Timer_Data Efl_Loop_Timer_Data; + +struct _Efl_Loop_Data +{ + double loop_time; + + Efl_Loop_Message_Handler *future_message_handler; + + Efl_Loop_Timer *poll_high; + Efl_Loop_Timer *poll_medium; + Efl_Loop_Timer *poll_low; + + Eina_List *exes; // only used in main loop (for now?) + + Eina_List *fd_handlers_obj; + + Ecore_Fd_Handler *fd_handlers; + Eina_List *fd_handlers_with_prep; + Eina_List *file_fd_handlers; + Eina_List *always_fd_handlers; + Eina_List *fd_handlers_with_buffer; + Eina_List *fd_handlers_to_delete; + Ecore_Fd_Handler *fd_handlers_to_call; + Ecore_Fd_Handler *fd_handlers_to_call_current; + +# ifdef _WIN32 + Ecore_Win32_Handler *win32_handlers; + Ecore_Win32_Handler *win32_handler_current; + Eina_List *win32_handlers_to_delete; +# endif + + Eina_List *thread_children; + + Eina_Inlist *message_queue; + Eina_Inlist *message_pending_queue; + unsigned int message_walking; + + unsigned int throttle; + + int epoll_fd; + pid_t epoll_pid; + int timer_fd; + + double last_check; + Eina_Inlist *timers; + Eina_Inlist *suspended; + Efl_Loop_Timer_Data *timer_current; + int timers_added; + + Eina_Value exit_code; + + int idlers; + int in_loop; + unsigned int loop_active; + + struct { + int high; + int medium; + int low; + } pollers; + + struct { + char **environ_ptr; + char **environ_copy; + } env; + + Eina_Bool do_quit : 1; + Eina_Bool quit_on_last_thread_child_del : 1; +}; + + +#endif diff --git a/src/lib/ecore/meson.build b/src/lib/ecore/meson.build index 14376c32e5..58d88ea41f 100644 --- a/src/lib/ecore/meson.build +++ b/src/lib/ecore/meson.build @@ -101,6 +101,7 @@ ecore_header_src = [ 'ecore_api.h', 'ecore_exe_eo.legacy.h', 'efl_loop_timer_eo.legacy.h', + 'efl_loop_data.h', ] ecore_src = files([ @@ -197,6 +198,10 @@ if get_option('g-mainloop') == true endif endif +if sys_windows and get_option('exactness-win32') + config_h.set('EFL_EXACTNESS_WIN32', '1') +endif + ecore_lib = library('ecore', ecore_src, pub_eo_file_target, dependencies: ecore_pub_deps + [ecore_deps, ecore_ext_deps], diff --git a/src/lib/ecore_evas/Ecore_Evas.h b/src/lib/ecore_evas/Ecore_Evas.h index 29e235941a..61aa8b66aa 100644 --- a/src/lib/ecore_evas/Ecore_Evas.h +++ b/src/lib/ecore_evas/Ecore_Evas.h @@ -159,6 +159,11 @@ ECORE_EVAS_API int ecore_evas_engine_type_supported_get(Ecore_Evas_Engin * * @see ecore_evas_shutdown() */ +#ifdef EFL_EXACTNESS_WIN32 +typedef int(*ecore_evas_init_t)(void); +extern ECORE_EVAS_API ecore_evas_init_t ecore_evas_init_redirect; +ECORE_EVAS_API int ecore_evas_init_original(void); +#endif ECORE_EVAS_API int ecore_evas_init(void); /** diff --git a/src/lib/ecore_evas/ecore_evas.c b/src/lib/ecore_evas/ecore_evas.c index 1767de4a1a..1d924f0af3 100644 --- a/src/lib/ecore_evas/ecore_evas.c +++ b/src/lib/ecore_evas/ecore_evas.c @@ -605,8 +605,26 @@ ecore_evas_engine_type_supported_get(Ecore_Evas_Engine_Type engine) }; } + +#ifdef EFL_EXACTNESS_WIN32 +ECORE_EVAS_API ecore_evas_init_t ecore_evas_init_redirect = NULL; + ECORE_EVAS_API int ecore_evas_init(void) +{ + exactness_preload(); + if (ecore_evas_init_redirect) + return ecore_evas_init_redirect(); + else + return ecore_evas_init_original(); +} + +ECORE_EVAS_API int +ecore_evas_init_original(void) +#else +ECORE_EVAS_API int +ecore_evas_init(void) +#endif { Ecore_Evas_Object_Animator_Interface iface; @@ -1008,7 +1026,7 @@ _ecore_evas_constructor_ews(int x, int y, int w, int h, const char *extra_option /* note: keep sorted by priority, highest first */ static const struct ecore_evas_engine _engines[] = { - /* unix */ +#ifndef _WIN32 {"software_x11", _ecore_evas_constructor_software_x11}, {"opengl_x11", _ecore_evas_constructor_opengl_x11}, {"fb", _ecore_evas_constructor_fb}, @@ -1028,6 +1046,10 @@ static const struct ecore_evas_engine _engines[] = { #ifdef BUILD_ECORE_EVAS_EWS {"ews", _ecore_evas_constructor_ews}, #endif +#endif + {"software_gdi", _ecore_evas_constructor_software_gdi}, + {"software_ddraw", _ecore_evas_constructor_software_ddraw}, + {"buffer", _ecore_evas_constructor_buffer}, {NULL, NULL} }; diff --git a/src/lib/eina/eina_main.c b/src/lib/eina/eina_main.c index 3d3bdb6458..9d3d523d84 100644 --- a/src/lib/eina/eina_main.c +++ b/src/lib/eina/eina_main.c @@ -280,8 +280,62 @@ _eina_threads_do_shutdown(void) */ EINA_API Eina_Version *eina_version = &_version; +#ifdef EFL_EXACTNESS_WIN32 +EINA_API eina_init_t eina_init_redirect = NULL; + +EINA_API Eina_Bool +exactness_preload(void) +{ + char *env = getenv("EXACTNESS_PRELOAD_WIN32"); + if (env) + { + if (!eina_init_redirect) + { + static HINSTANCE dll = NULL; + if (!dll) + { + if (!strcmp(env, "PLAY")) + { + dll = LoadLibraryA("C:/Users/joaoantoniocardoso/efl/build/src/bin/exactness/exactness_play-1.dll"); + if (!dll) + { + fprintf(stderr, "Failed loading exactness_play-1.dll\n"); + return EINA_FALSE; + } + return EINA_TRUE; + } + else if (!strcmp(env, "RECORD")) + { + dll = LoadLibraryA("C:/Users/joaoantoniocardoso/efl/build/src/bin/exactness/exactness_record-1.dll"); + if (!dll) + { + fprintf(stderr, "Failed loading exactness_record-1.dll\n"); + return EINA_FALSE; + } + return EINA_TRUE; + } + } + } + } + return EINA_FALSE; +} + +EINA_API int +eina_init(void) +{ + exactness_preload(); + if (eina_init_redirect) + return eina_init_redirect(); + else + return eina_init_original(); +} + +EINA_API int +eina_init_original(void) +#else EINA_API int eina_init(void) +#endif { const struct eina_desc_setup *itr, *itr_end; @@ -351,8 +405,25 @@ eina_init(void) return 1; } +#ifdef EFL_EXACTNESS_WIN32 +EINA_API eina_shutdown_t eina_shutdown_redirect = NULL; + +EINA_API int +eina_shutdown(void) +{ + exactness_preload(); + if (eina_shutdown_redirect) + return eina_shutdown_redirect(); + else + return eina_shutdown_original(); +} + +EINA_API int +eina_shutdown_original(void) +#else EINA_API int eina_shutdown(void) +#endif { if (_eina_main_count <= 0) { diff --git a/src/lib/eina/eina_main.h b/src/lib/eina/eina_main.h index 7b38917de4..5636fa4be1 100644 --- a/src/lib/eina/eina_main.h +++ b/src/lib/eina/eina_main.h @@ -175,6 +175,11 @@ EINA_API extern Eina_Error EINA_ERROR_NOT_IMPLEMENTED; * threads, but requires Eina to be compiled with such feature. * */ +#ifdef EFL_EXACTNESS_WIN32 +typedef int(*eina_init_t)(void); +extern EINA_API eina_init_t eina_init_redirect; +EINA_API int eina_init_original(void); +#endif EINA_API int eina_init(void); /** @@ -191,6 +196,11 @@ EINA_API int eina_init(void); * not call any of the Eina functions anymore. You must call * eina_init() again to use the Eina functions again. */ +#ifdef EFL_EXACTNESS_WIN32 +typedef int(*eina_shutdown_t)(void); +extern EINA_API eina_shutdown_t eina_shutdown_redirect; +EINA_API int eina_shutdown_original(void); +#endif EINA_API int eina_shutdown(void); /** @@ -250,6 +260,10 @@ EINA_API Eina_Bool eina_main_loop_is(void); */ EINA_API void eina_main_loop_define(void); +#ifdef EFL_EXACTNESS_WIN32 +EINA_API Eina_Bool exactness_preload(void); +#endif + /** * @} */ diff --git a/src/lib/elementary/elm_general.h b/src/lib/elementary/elm_general.h index 5c278f90e0..121c6200c5 100644 --- a/src/lib/elementary/elm_general.h +++ b/src/lib/elementary/elm_general.h @@ -573,6 +573,12 @@ ELM_API extern double _elm_startup_time; * @see elm_shutdown(). * @ingroup Elm_General */ +#ifdef EFL_EXACTNESS_WIN32 +typedef int(*elm_init_t)(int argc, char **argv); +extern ELM_API elm_init_t elm_init_redirect; + +ELM_API int elm_init_original(int argc, char **argv); +#endif ELM_API int elm_init(int argc, char **argv); /** diff --git a/src/lib/elementary/elm_main.c b/src/lib/elementary/elm_main.c index d39dd3ec01..75b1afc87d 100644 --- a/src/lib/elementary/elm_main.c +++ b/src/lib/elementary/elm_main.c @@ -419,8 +419,25 @@ _efl_ui_theme_apply_error_init(void) // This is necessary to keep backward compatibility static const char *bcargv[] = { "exe" }; +#ifdef EFL_EXACTNESS_WIN32 +ELM_API elm_init_t elm_init_redirect = NULL; + +ELM_API int +elm_init(int argc, char **argv) +{ + exactness_preload(); + if (elm_init_redirect) + return elm_init_redirect(argc, argv); + else + return elm_init_original(argc, argv); +} + +ELM_API int +elm_init_original(int argc, char **argv) +#else ELM_API int elm_init(int argc, char **argv) +#endif { _elm_init_count++; if (_elm_init_count > 1) return _elm_init_count;