From 9bc1ad102ab661d68eb1a5eebdc507cc7f0aac17 Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Fri, 24 Jun 2016 15:32:21 -0700 Subject: [PATCH] elementary: introduce EFL_MAIN and rely on Eo_Event to call the initialisation function. FIXME: Find a way to return an exit value. Maybe on efl_loop_quit ? --- src/bin/elementary/quicklaunch.c | 5 +- src/bin/elementary/test.c | 56 ++++++++------ src/lib/elementary/elm_general.h | 13 ++++ src/lib/elementary/elm_main.c | 127 ++++++++++++++++++++++++++++++- 4 files changed, 172 insertions(+), 29 deletions(-) diff --git a/src/bin/elementary/quicklaunch.c b/src/bin/elementary/quicklaunch.c index 6ca0a3c973..0318d96090 100644 --- a/src/bin/elementary/quicklaunch.c +++ b/src/bin/elementary/quicklaunch.c @@ -151,7 +151,10 @@ handle_run(int fd, unsigned long bytes) } } #endif - elm_quicklaunch_prepare(argc, argv, cwd); + // Try new form before trying old form + if (!efl_quicklaunch_prepare(argc, argv, cwd)) + elm_quicklaunch_prepare(argc, argv, cwd); + elm_quicklaunch_fork(argc, argv, cwd, post_fork, NULL); elm_quicklaunch_cleanup(); } diff --git a/src/bin/elementary/test.c b/src/bin/elementary/test.c index c9c259661b..d6da4baa69 100644 --- a/src/bin/elementary/test.c +++ b/src/bin/elementary/test.c @@ -998,32 +998,47 @@ colorclass_list_cb(void) return ret; } +static void +_main_loop_death(void *data EINA_UNUSED, + const Eo_Event *ev EINA_UNUSED) +{ + struct elm_test *t; + + EINA_LIST_FREE(tests, t) + free(t); + + eina_log_domain_unregister(_log_domain); +} + /* this is your elementary main function - it MUST be called IMMEDIATELY * after elm_init() and MUST be passed argc and argv, and MUST be called - * elm_main and not be static - must be a visible symbol with EAPI_MAIN infront */ -EAPI_MAIN int -elm_main(int argc, char **argv) + * efl_main and not be static - must be a visible symbol with EAPI_MAIN infront */ +EAPI_MAIN void +efl_main(void *data EINA_UNUSED, + const Eo_Event *ev) { + Efl_Loop_Arguments *arge = ev->info; Eina_Bool test_win_only = EINA_FALSE; char *autorun = NULL; - struct elm_test *t = NULL; _log_domain = eina_log_domain_register("elementary_test", NULL); + eo_event_callback_add(ev->object, EO_EVENT_DEL, _main_loop_death, NULL); + elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED); /* tell elm about our app so it can figure out where to get files */ elm_app_compile_bin_dir_set(PACKAGE_BIN_DIR); elm_app_compile_lib_dir_set(PACKAGE_LIB_DIR); elm_app_compile_data_dir_set(PACKAGE_DATA_DIR); - elm_app_info_set(elm_main, "elementary", "images/logo.png"); + elm_app_info_set(efl_main, "elementary", "images/logo.png"); /* if called with a single argument try to autorun a test with * the same name as the given param * ex: elementary_test "Box Vert 2" */ - if (argc == 2) + if (eina_array_count(arge->argv) == 2) { - if (!strcmp(argv[1], "--help")) + if (!strcmp(eina_array_data_get(arge->argv, 1), "--help")) { printf("Usages:\n" "$ elementary_test\n" @@ -1031,19 +1046,19 @@ elm_main(int argc, char **argv) "$ elementary_test -to [TEST_NAME]\n\n" "Examples:\n" "$ elementary_test -to Button\n\n"); - goto end; + return; } - autorun = argv[1]; + autorun = eina_array_data_get(arge->argv, 1); } - else if (argc == 3) + else if (eina_array_count(arge->argv) == 3) { /* Just a workaround to make the shot module more * useful with elementary test. */ - if ((!strcmp(argv[1], "--test-win-only")) || - (!strcmp(argv[1], "-to"))) + if ((!strcmp(eina_array_data_get(arge->argv, 1), "--test-win-only")) || + (!strcmp(eina_array_data_get(arge->argv, 1), "-to"))) { test_win_only = EINA_TRUE; - autorun = argv[2]; + autorun = eina_array_data_get(arge->argv, 2); } } @@ -1051,18 +1066,9 @@ elm_main(int argc, char **argv) elm_color_class_list_cb_set(colorclass_list_cb); /* put here any init specific to this app like parsing args etc. */ my_win_main(autorun, test_win_only); /* create main window */ - elm_run(); /* and run the program now and handle all events etc. */ - /* if the mainloop that elm_run() runs exist - we exit the app */ - EINA_LIST_FREE(tests, t) - free(t); - -end: - eina_log_domain_unregister(_log_domain); - - /* exit code */ - return 0; + /* FIXME: Hum, no exit code anywhere anymore ? */ } /* all elementary apps should use this. but it should be placed right after - * elm_main() */ -ELM_MAIN() + * efl_main() */ +EFL_MAIN() diff --git a/src/lib/elementary/elm_general.h b/src/lib/elementary/elm_general.h index b2d72b7ae9..fb2eb6a008 100644 --- a/src/lib/elementary/elm_general.h +++ b/src/lib/elementary/elm_general.h @@ -71,12 +71,14 @@ extern EAPI double _elm_startup_time; #ifndef ELM_LIB_QUICKLAUNCH #define ELM_MAIN() int main(int argc, char **argv) { int ret; _elm_startup_time = ecore_time_unix_get(); elm_init(argc, argv); ret = elm_main(argc, argv); elm_shutdown(); return ret; } /**< macro to be used after the elm_main() function */ +#define EFL_MAIN() int main(int argc, char **argv) { int ret = 0; _elm_startup_time = ecore_time_unix_get(); elm_init(argc, argv); eo_event_callback_add(ecore_main_loop_get(), EFL_LOOP_EVENT_ARGUMENTS, efl_main, NULL); elm_run(); elm_shutdown(); return ret; } #else /** @deprecated macro to be used after the elm_main() function. * Do not define ELM_LIB_QUICKLAUNCH * Compile your programs with -fpie and -pie -rdynamic instead, to generate a single binary (linkable executable). */ #define ELM_MAIN() int main(int argc, char **argv) { int ret; _elm_startup_time = ecore_time_unix_get(); ret = elm_quicklaunch_fallback(argc, argv); elm_shutdown(); return ret; } +#define EFL_MAIN() int main(int argc, char **argv) { int ret = 0; _elm_startup_time = ecore_time_unix_get(); efl_quicklaunch_fallback(argc, argv); elm_shutdown(); return ret; } #endif /**************************************************************************/ @@ -209,6 +211,11 @@ EAPI void elm_quicklaunch_seed(void); */ EAPI Eina_Bool elm_quicklaunch_prepare(int argc, char **argv, const char *cwd); +/** + * Exposed symbol used only by macros and should not be used by apps + */ +EAPI Eina_Bool efl_quicklaunch_prepare(int argc, char **argv, const char *cwd); + /** * Exposed symbol used only by macros and should not be used by apps */ @@ -224,6 +231,12 @@ EAPI void elm_quicklaunch_cleanup(void); */ EAPI int elm_quicklaunch_fallback(int argc, char **argv); +/** + * Exposed symbol used only by macros and should not be used by apps + */ +EAPI Eina_Bool efl_quicklaunch_fallback(int argc, char **argv); + + /** * Exposed symbol used only by macros and should not be used by apps */ diff --git a/src/lib/elementary/elm_main.c b/src/lib/elementary/elm_main.c index 9c9454121e..d8bf9d5d6b 100644 --- a/src/lib/elementary/elm_main.c +++ b/src/lib/elementary/elm_main.c @@ -842,6 +842,8 @@ static void *qr_handle = NULL; #endif static int (*qr_main)(int argc, char **argv) = NULL; +static void (*qre_main)(void *data, + const Eo_Event *ev) = NULL; EAPI Eina_Bool elm_quicklaunch_prepare(int argc, @@ -932,6 +934,94 @@ elm_quicklaunch_prepare(int argc, #endif } +EAPI Eina_Bool +efl_quicklaunch_prepare(int argc, + char **argv, + const char *cwd) +{ +#ifdef HAVE_FORK + char *exe, *exe2, *p; + char *exename; + + if (argc <= 0 || argv == NULL) return EINA_FALSE; + + exe = elm_quicklaunch_exe_path_get(argv[0], cwd); + if (!exe) + { + ERR("requested quicklaunch binary '%s' does not exist\n", argv[0]); + return EINA_FALSE; + } + + exe2 = malloc(strlen(exe) + 1 + 7 + strlen(LIBEXT)); + strcpy(exe2, exe); + p = strrchr(exe2, '/'); + if (p) p++; + else p = exe2; + exename = alloca(strlen(p) + 1); + strcpy(exename, p); + *p = 0; + strcat(p, "../lib/"); + strcat(p, exename); + strcat(p, LIBEXT); + if (access(exe2, R_OK | X_OK) != 0) + ELM_SAFE_FREE(exe2, free); + /* Try linking to executable first. Works with PIE files. */ + qr_handle = dlopen(exe, RTLD_NOW | RTLD_GLOBAL); + if (qr_handle) + { + INF("dlopen('%s') = %p", exe, qr_handle); + qre_main = dlsym(qr_handle, "efl_main"); + if (qre_main) + { + INF("dlsym(%p, 'elm_main') = %p", qr_handle, qre_main); + free(exe2); + free(exe); + return EINA_TRUE; + } + dlclose(qr_handle); + qr_handle = NULL; + } + + if (!exe2) + { + WRN("not quicklauncher capable: '%s'", exe); + free(exe); + return EINA_FALSE; + } + free(exe); + + /* Open companion .so file. + * Support for legacy quicklaunch apps with separate library. + */ + qr_handle = dlopen(exe2, RTLD_NOW | RTLD_GLOBAL); + if (!qr_handle) + { + fprintf(stderr, "dlerr: %s\n", dlerror()); + WRN("dlopen('%s') failed: %s", exe2, dlerror()); + free(exe2); + return EINA_FALSE; + } + INF("dlopen('%s') = %p", exe2, qr_handle); + qre_main = dlsym(qr_handle, "efl_main"); + INF("dlsym(%p, 'elm_main') = %p", qr_handle, qre_main); + if (!qre_main) + { + WRN("not quicklauncher capable: no efl_main in '%s'", exe2); + dlclose(qr_handle); + qr_handle = NULL; + free(exe2); + return EINA_FALSE; + } + free(exe2); + return EINA_TRUE; +#else + (void)argc; + (void)argv; + (void)cwd; + return EINA_FALSE; +#endif +} + EAPI Eina_Bool elm_quicklaunch_fork(int argc, char **argv, @@ -943,7 +1033,7 @@ elm_quicklaunch_fork(int argc, pid_t child; int ret; - if (!qr_main) + if (!qr_main && !qre_main) { int i; char **args; @@ -1031,8 +1121,20 @@ elm_quicklaunch_fork(int argc, ecore_app_args_set(argc, (const char **)argv); if (_elm_config->atspi_mode != ELM_ATSPI_MODE_OFF) _elm_atspi_bridge_init(); - ret = qr_main(argc, argv); - exit(ret); + + if (qre_main) + { + eo_event_callback_add(ecore_main_loop_get(), EFL_LOOP_EVENT_ARGUMENTS, qre_main, NULL); + elm_run(); + elm_shutdown(); + // FIXME: get value back from the main loop quit ? + exit(0); + } + else + { + ret = qr_main(argc, argv); + exit(ret); + } return EINA_TRUE; #else return EINA_FALSE; @@ -1071,6 +1173,25 @@ elm_quicklaunch_fallback(int argc, return ret; } +EAPI Eina_Bool +efl_quicklaunch_fallback(int argc, + char **argv) +{ + /* int ret; */ + char cwd[PATH_MAX]; + elm_quicklaunch_init(argc, argv); + elm_quicklaunch_sub_init(argc, argv); + if (efl_quicklaunch_prepare(argc, argv, getcwd(cwd, sizeof(cwd)))) + { + eo_event_callback_add(ecore_main_loop_get(), EFL_LOOP_EVENT_ARGUMENTS, qre_main, NULL); + elm_run(); + // FIXME: get value back from the main loop quit ? + return EINA_TRUE; + } + + return EINA_FALSE; +} + EAPI char * elm_quicklaunch_exe_path_get(const char *exe, const char *cwd) {