From: duna.oh Date: Thu, 28 Jul 2022 05:54:09 +0000 (+0900) Subject: launch: implement tizen_launch_effect, tizen_launch_splash X-Git-Tag: accepted/tizen/unified/20220808.135412^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F98%2F279198%2F1;p=platform%2Fcore%2Fuifw%2Flibds-tizen.git launch: implement tizen_launch_effect, tizen_launch_splash Change-Id: I58c4c5e3b56237d370f56d0b7b96a5e8b058bfcc --- diff --git a/examples/meson.build b/examples/meson.build index d9fca10..4d90eb7 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -48,6 +48,7 @@ executable('tinyds-tdm-libinput', common_deps, deps_libds_tizen_backend_tdm, deps_libds_tizen_input_devicemgr, + deps_libds_tizen_launch, dependency('pixman-1', required: true), dependency('threads', required: true), ], diff --git a/examples/tinyds-tdm-libinput.c b/examples/tinyds-tdm-libinput.c index 10c02bb..faf666b 100644 --- a/examples/tinyds-tdm-libinput.c +++ b/examples/tinyds-tdm-libinput.c @@ -26,6 +26,7 @@ #include #include #include +#include #define USE_TDM_BUFFER_QUEUE @@ -79,6 +80,8 @@ struct tinyds_server uint32_t seat_caps; double output_x, output_y; struct ds_tizen_input_devicemgr *devicemgr; + struct ds_tizen_effect *effect; + struct ds_tizen_splash *splash; struct tinyds_output *output; struct wl_event_source *stdin_source; @@ -90,6 +93,11 @@ struct tinyds_server struct wl_listener new_xdg_surface; struct wl_listener devicemgr_destroy; struct wl_listener pointer_warp; + struct wl_listener effect_destroy; + struct wl_listener effect_type_set; + struct wl_listener effect_type_unset; + struct wl_listener new_splash; + struct wl_listener splash_owner; struct wl_list keyboards; struct wl_list pointers; @@ -110,6 +118,9 @@ struct tinyds_view int x, y; bool mapped; + + pid_t pid; + int effect_type; }; struct tinyds_pointer @@ -219,6 +230,25 @@ main(void) } static void +view_populate_pid(struct tinyds_view *view) +{ + pid_t pid; + struct wl_client *client = NULL; + struct ds_surface *surface = ds_xdg_surface_get_surface(view->xdg_surface); + + if (surface) + client = wl_resource_get_client(ds_surface_get_wl_resource(surface)); + wl_client_get_credentials(client, &pid, NULL, NULL); + + ds_inf("view pid(%u)", pid); + view->pid = pid; + + view->effect_type = ds_tizen_effect_get_effect_type(view->server->effect, pid); + ds_tizen_effect_unset_effect_type(view->server->effect, pid); + ds_inf("view effect_type(%d)", view->effect_type); +} + +static void view_handle_xdg_surface_map(struct wl_listener *listener, void *data TINYDS_UNUSED) { @@ -228,6 +258,8 @@ view_handle_xdg_surface_map(struct wl_listener *listener, view = wl_container_of(listener, view, xdg_surface_map); view->mapped = true; + view_populate_pid(view); + wl_list_for_each(kbd, &view->server->keyboards, link) { keyboard = ds_input_device_get_keyboard(kbd->dev); if (keyboard != NULL) { @@ -320,6 +352,9 @@ server_new_xdg_surface(struct wl_listener *listener, void *data) view->x = rand() % 1000; view->y = rand() % 500; + view->pid = 0; + view->effect_type = -1; + ds_inf("view at (%d, %d)", view->x, view->y); } @@ -508,6 +543,113 @@ devicemgr_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED) server->devicemgr = NULL; } +static void +launch_effect_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED) +{ + struct tinyds_server *server = + wl_container_of(listener, server, effect_destroy); + + wl_list_remove(&server->effect_destroy.link); + wl_list_remove(&server->effect_type_set.link); + wl_list_remove(&server->effect_type_unset.link); + wl_list_remove(&server->new_splash.link); + + server->effect = NULL; +} + +static void +launch_effect_handle_type_set(struct wl_listener *listener, void *data) +{ + struct tinyds_server *server; + struct ds_tizen_effect_event_type_set *event = data; + struct tinyds_view *view = NULL; + bool existing = false; + + server = wl_container_of(listener, server, effect_type_set); + + ds_inf("Launch effect. type_set: pid(%u) type:%s", event->pid, (event->effect_type == 1) ? "depth-in" : "launch"); + + wl_list_for_each(view, &server->views, link) { + if (view->pid == event->pid) { + view->effect_type = event->effect_type; + ds_inf("Launch effect. existing pid"); + existing = true; + } + } + if (existing) { + ds_tizen_effect_unset_effect_type(server->effect, event->pid); + } else { + ds_tizen_effect_set_effect_type(server->effect, event->pid, event->effect_type); + } +} + +static void +launch_effect_handle_type_unset(struct wl_listener *listener, void *data) +{ + struct tinyds_server *server; + struct ds_tizen_effect_event_type_unset *event = data; + struct tinyds_view *view = NULL; + + server = wl_container_of(listener, server, effect_type_unset); + + ds_inf("Launch effect. type_unset: pid(%u)", event->pid); + + wl_list_for_each(view, &server->views, link) { + if (view->pid == event->pid) { + view->effect_type = -1; + ds_inf("Launch effect. pid found"); + } + } + ds_tizen_effect_unset_effect_type(server->effect, event->pid); +} + +static void +launch_splash_handle_owner(struct wl_listener *listener, void *data) +{ + struct tinyds_server *server; + struct ds_tizen_splash_event_owner *event = data; + struct tinyds_view *view = NULL; + + server = wl_container_of(listener, server, splash_owner); + + ds_inf("Splash owner. pid(%u)", event->pid); + + wl_list_for_each(view, &server->views, link) { + if (view->pid == event->pid) { + if (event->pid == ds_tizen_splash_get_pid(server->splash)) + ;// + else { + ds_tizen_splash_set_pid(server->splash, event->pid); + } + } + } +} + +static void +launch_effect_handle_new_splash(struct wl_listener *listener, void *data) +{ + struct tinyds_server *server; + struct ds_tizen_effect_event_new_splash *event = data; + struct tinyds_view *view = NULL; + + server = wl_container_of(listener, server, new_splash); + + ds_inf("Launch new splash. splash(%p)", event->splash); + if (!event->splash) return; + + server->splash = event->splash; + + // new view for "Launchscreen" + view = calloc(1, sizeof *view); + assert(view); + wl_list_insert(server->views.prev, &view->link); + view->pid = ds_tizen_splash_get_pid(event->splash); + + server->splash_owner.notify = launch_splash_handle_owner; + ds_tizen_splash_add_owner_listener(server->splash, + &server->splash_owner); +} + static bool init_server(struct tinyds_server *server, struct wl_display *display) { @@ -574,6 +716,27 @@ init_server(struct tinyds_server *server, struct wl_display *display) ds_tizen_input_devicemgr_add_pointer_warp_listener(server->devicemgr, &server->pointer_warp); + server->effect = ds_tizen_effect_create(display); + if (!server->effect) { + goto err; + } + + server->effect_destroy.notify = launch_effect_handle_destroy; + ds_tizen_effect_add_destroy_listener(server->effect, + &server->effect_destroy); + + server->effect_type_set.notify = launch_effect_handle_type_set; + ds_tizen_effect_add_type_set_listener(server->effect, + &server->effect_type_set); + + server->effect_type_unset.notify = launch_effect_handle_type_unset; + ds_tizen_effect_add_type_unset_listener(server->effect, + &server->effect_type_unset); + + server->new_splash.notify = launch_effect_handle_new_splash; + ds_tizen_effect_add_new_splash_listener(server->effect, + &server->new_splash); + return true; err: diff --git a/include/libds-tizen/launch/effect.h b/include/libds-tizen/launch/effect.h new file mode 100644 index 0000000..d49fa33 --- /dev/null +++ b/include/libds-tizen/launch/effect.h @@ -0,0 +1,92 @@ +#ifndef LIBDS_TIZEN_EFFECT_H +#define LIBDS_TIZEN_EFFECT_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct ds_tizen_effect; +struct ds_tizen_splash; + +enum ds_tizen_effect_type +{ + DS_TIZEN_EFFECT_TYPE_LAUNCH = 0, + DS_TIZEN_EFFECT_TYPE_DEPTH_IN, +}; + +struct ds_tizen_effect_event_type_set +{ + uint32_t pid; + enum ds_tizen_effect_type effect_type; +}; + +struct ds_tizen_effect_event_type_unset +{ + uint32_t pid; +}; + +struct ds_tizen_effect_event_new_splash +{ + struct ds_tizen_splash *splash; +}; + +enum ds_tizen_splash_file_type +{ + DS_TIZEN_SPLASH_FILE_TYPE_ERR = -1, + DS_TIZEN_SPLASH_FILE_TYPE_IMG, + DS_TIZEN_SPLASH_FILE_TYPE_EDJ, +}; + +struct ds_tizen_splash_event_owner +{ + uint32_t pid; +}; + +// launch_effect +struct ds_tizen_effect * +ds_tizen_effect_create(struct wl_display *display); + +void +ds_tizen_effect_add_destroy_listener( + struct ds_tizen_effect *effect, struct wl_listener *listener); +void +ds_tizen_effect_add_type_set_listener( + struct ds_tizen_effect *effect, struct wl_listener *listener); +void +ds_tizen_effect_add_type_unset_listener(struct ds_tizen_effect *effect, + struct wl_listener *listener); +void +ds_tizen_effect_add_new_splash_listener(struct ds_tizen_effect *effect, + struct wl_listener *listener); + +void +ds_tizen_effect_set_effect_type(struct ds_tizen_effect *effect, + uint32_t pid, int effect_type); +void +ds_tizen_effect_unset_effect_type(struct ds_tizen_effect *effect, + uint32_t pid); +int +ds_tizen_effect_get_effect_type(struct ds_tizen_effect *effect, + uint32_t pid); + +// launch_splash +void +ds_tizen_splash_add_destroy_listener( + struct ds_tizen_splash *splash, struct wl_listener *listener); +void +ds_tizen_splash_add_owner_listener( + struct ds_tizen_splash *splash, struct wl_listener *listener); + +uint32_t +ds_tizen_splash_get_pid(struct ds_tizen_splash *splash); +void +ds_tizen_splash_set_pid(struct ds_tizen_splash *splash, uint32_t pid); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/packaging/libds-tizen.spec b/packaging/libds-tizen.spec index 546a832..b76d434 100644 --- a/packaging/libds-tizen.spec +++ b/packaging/libds-tizen.spec @@ -398,9 +398,11 @@ ninja -C builddir install %defattr(-,root,root,-) %license LICENSE %{_includedir}/libds-tizen/launch/appinfo.h +%{_includedir}/libds-tizen/launch/effect.h %{_libdir}/pkgconfig/libds-tizen-launch.pc %{_libdir}/libds-tizen-launch.so %{_bindir}/libds-tizen-launch-appinfo-tests +%{_bindir}/libds-tizen-launch-effect-tests %files display-policy %manifest %{name}.manifest diff --git a/src/launch/effect.c b/src/launch/effect.c new file mode 100644 index 0000000..fc38c77 --- /dev/null +++ b/src/launch/effect.c @@ -0,0 +1,557 @@ +#include +#include +#include +#include + +#include "util.h" +#include + +#define TIZEN_EFFECT_VERSION 1 +#define SPLASH_CLIENT_PID 321 // no meaning +#define CUSTOM_EFFECT_CALLEE "_CUSTOM_EFFECT_CALLEE_" + +struct ds_tizen_effect +{ + struct wl_global *global; + + struct wl_list clients; + struct wl_list infos; + + struct wl_listener destroy; + + struct { + struct wl_signal destroy; + struct wl_signal type_set; + struct wl_signal type_unset; + struct wl_signal new_splash; + } events; +}; + +struct ds_tizen_effect_client +{ + struct ds_tizen_effect *effect; + + struct wl_resource *resource; + struct wl_client *wl_client; + + struct wl_list splashs; + + struct wl_list link; // ds_tizen_effect::clients +}; + +struct ds_tizen_effect_info +{ + uint32_t pid; + int effect_type; + + struct wl_list link; // ds_tizen_effect::infos +}; + +struct ds_tizen_splash +{ + struct ds_tizen_effect *effect; + + struct ds_tizen_effect_client *client; + struct wl_resource *resource; + + uint32_t pid; + char *appid; + bool custom_effect_callee; + + struct { + struct wl_signal destroy; + struct wl_signal owner; + } events; + + struct wl_list link; // ds_tizen_effect_client::splashs +}; + +static void effect_handle_display_destroy(struct wl_listener *listener, + void *data); + +static void effect_bind(struct wl_client *wl_client, void *data, + uint32_t version, uint32_t id); + +WL_EXPORT struct ds_tizen_effect * +ds_tizen_effect_create(struct wl_display *display) +{ + struct ds_tizen_effect *effect; + + effect = calloc(1, sizeof *effect); + if (!effect) { + ds_err("calloc() failed."); + return NULL; + } + + effect->global = wl_global_create(display, &tizen_launch_effect_interface, + TIZEN_EFFECT_VERSION, effect, effect_bind); + if (!effect->global) { + ds_err("wl_global_create() failed. tizen_launch_effect_interface"); + free(effect); + return NULL; + } + + wl_list_init(&effect->clients); + wl_list_init(&effect->infos); + + effect->destroy.notify = effect_handle_display_destroy; + wl_display_add_destroy_listener(display, &effect->destroy); + + wl_signal_init(&effect->events.destroy); + wl_signal_init(&effect->events.type_set); + wl_signal_init(&effect->events.type_unset); + wl_signal_init(&effect->events.new_splash); + + ds_inf("Global create: tizen_launch_effect. effect(%p)", effect); + + return effect; +} + +//launch_effect +WL_EXPORT void +ds_tizen_effect_add_destroy_listener( + struct ds_tizen_effect *effect, struct wl_listener *listener) +{ + wl_signal_add(&effect->events.destroy, listener); +} + +WL_EXPORT void +ds_tizen_effect_add_type_set_listener( + struct ds_tizen_effect *effect, struct wl_listener *listener) +{ + wl_signal_add(&effect->events.type_set, listener); +} + +WL_EXPORT void +ds_tizen_effect_add_type_unset_listener( + struct ds_tizen_effect *effect, struct wl_listener *listener) +{ + wl_signal_add(&effect->events.type_unset, listener); +} + +WL_EXPORT void +ds_tizen_effect_add_new_splash_listener( + struct ds_tizen_effect *effect, struct wl_listener *listener) +{ + wl_signal_add(&effect->events.new_splash, listener); +} + +WL_EXPORT void +ds_tizen_effect_set_effect_type(struct ds_tizen_effect *effect, + uint32_t pid, int effect_type) +{ + struct ds_tizen_effect_info *info; + + ds_inf("ds_tizen_effect_set_effect_type() pid(%u), effect_type(%d)", pid, effect_type); + + info = calloc(1, sizeof *info); + if (info == NULL) { + ds_err("calloc() failed. tizen_effect_info"); + return; + } + info->pid = pid; + info->effect_type = effect_type; + + wl_list_insert(&effect->infos, &info->link); +} + +WL_EXPORT void +ds_tizen_effect_unset_effect_type(struct ds_tizen_effect *effect, + uint32_t pid) +{ + struct ds_tizen_effect_info *info, *tmp; + + ds_inf("ds_tizen_effect_unset_effect_type() pid(%u)", pid); + + wl_list_for_each_safe(info, tmp, &effect->infos, link) { + if (info->pid == pid) { + ds_inf("ds_tizen_effect_unset_effect_type() pid found.", pid); + wl_list_remove(&info->link); + free(info); + } + } +} + +WL_EXPORT int +ds_tizen_effect_get_effect_type(struct ds_tizen_effect *effect, + uint32_t pid) +{ + struct ds_tizen_effect_info *info; + + ds_inf("ds_tizen_effect_get_effect_type() pid(%u)", pid); + + wl_list_for_each(info, &effect->infos, link) { + if (info->pid == pid) { + return info->effect_type; + } + } + return -1; +} + +//launch_splash +WL_EXPORT void +ds_tizen_splash_add_destroy_listener( + struct ds_tizen_splash *splash, struct wl_listener *listener) +{ + wl_signal_add(&splash->events.destroy, listener); +} + +WL_EXPORT void +ds_tizen_splash_add_owner_listener( + struct ds_tizen_splash *splash, struct wl_listener *listener) +{ + wl_signal_add(&splash->events.owner, listener); +} + +WL_EXPORT uint32_t +ds_tizen_splash_get_pid(struct ds_tizen_splash *splash) +{ + return splash->pid; +} + +WL_EXPORT void +ds_tizen_splash_set_pid(struct ds_tizen_splash *splash, uint32_t pid) +{ + splash->pid = pid; +} + +static void +effect_client_destroy(struct ds_tizen_effect_client *client) +{ + struct ds_tizen_splash *splash, *tmp; + + wl_list_for_each_safe(splash, tmp, &client->splashs, link) { + wl_signal_emit(&splash->events.destroy, splash); + wl_list_remove(&splash->link); + free(splash); + } + + wl_list_remove(&client->link); + free(client); +} + +static void effect_handle_display_destroy(struct wl_listener *listener, + void *data) +{ + struct ds_tizen_effect *effect; + struct ds_tizen_effect_client *client, *tmp_client; + struct ds_tizen_effect_info *info, *tmp_info; + + effect = wl_container_of(listener, effect, destroy); + + ds_inf("Global destroy: effect(%p)", effect); + + wl_signal_emit(&effect->events.destroy, effect); + wl_list_remove(&effect->destroy.link); + + wl_list_for_each_safe(client, tmp_client, &effect->clients, link) { + effect_client_destroy(client); + } + + wl_list_for_each_safe(info, tmp_info, &effect->infos, link) { + wl_list_remove(&info->link); + free(info); + } + + wl_global_destroy(effect->global); + free(effect); +} + +static int +effect_get_effect_type(const char *effect_type) +{ + enum ds_tizen_effect_type type = 0; + + if (!effect_type) return 0; + + if (!strncmp(effect_type, "launch", sizeof("launch"))) type = DS_TIZEN_EFFECT_TYPE_LAUNCH; + else if (!strncmp(effect_type, "depth-in", sizeof("depth-in"))) type = DS_TIZEN_EFFECT_TYPE_DEPTH_IN; + + return type; +} + +static void +splash_handle_destroy(struct wl_client *wl_client, struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static void +splash_handle_launch(struct wl_client *wl_client, + struct wl_resource *resource, const char *pfname, uint32_t ftype, + uint32_t depth, uint32_t angle, uint32_t indicator, + const char *effect_type, const char *theme_type, + struct wl_array *options) +{ + struct ds_tizen_effect_event_type_set ds_event; + struct ds_tizen_splash *splash; + struct ds_tizen_effect *effect; + + ds_inf("splash launch"); + ds_inf("path %s(%s), indicator(%d), angle(%d), effect_type(%s)", + pfname, (ftype == DS_TIZEN_SPLASH_FILE_TYPE_IMG) ? "IMG" : "EDC", indicator, angle, effect_type); + ds_inf("theme_type(%s), options(%p)",theme_type, options); + + splash = wl_resource_get_user_data(resource); + splash->pid = SPLASH_CLIENT_PID; + effect = splash->effect; + if (effect) { + ds_event.pid = SPLASH_CLIENT_PID; + ds_event.effect_type = effect_get_effect_type(effect_type); + + ds_inf("Effect type_set. pid:%u type:%s", ds_event.pid, effect_type); + + wl_signal_emit(&effect->events.type_set, &ds_event); + } +} + +static void +splash_handle_owner(struct wl_client *wl_client, + struct wl_resource *resource, uint32_t pid) +{ + struct ds_tizen_splash *splash; + struct ds_tizen_splash_event_owner ds_event; + + ds_inf("splash set owner. pid:%u", pid); + + splash = wl_resource_get_user_data(resource); + + ds_event.pid = pid; + wl_signal_emit(&splash->events.owner, &ds_event); +} + +static void +splash_handle_launch_v2(struct wl_client *wl_client, + struct wl_resource *resource, const char *pfname, uint32_t ftype, + uint32_t depth, uint32_t angle, uint32_t indicator, + const char *effect_type, const char *theme_type, + struct wl_array *options, struct wl_array *extra_config) +{ + struct ds_tizen_effect_event_type_set ds_event; + struct ds_tizen_splash *splash; + struct ds_tizen_effect *effect; + + ds_inf("splash launch_v2"); + ds_inf("path %s(%s), indicator(%d), angle(%d), effect_type(%s)", + pfname, (ftype == DS_TIZEN_SPLASH_FILE_TYPE_IMG) ? "IMG" : "EDC", indicator, angle, effect_type); + ds_inf("theme_type(%s) options(%p) extra_config(%p)", theme_type, options, extra_config); + + splash = wl_resource_get_user_data(resource); + splash->pid = SPLASH_CLIENT_PID; + effect = splash->effect; + if (effect) { + ds_event.pid = SPLASH_CLIENT_PID; + ds_event.effect_type = effect_get_effect_type(effect_type); + + ds_inf("Effect type_set. pid:%u type:%s", ds_event.pid, effect_type); + + wl_signal_emit(&effect->events.type_set, &ds_event); + } + + //Parse extra config + if ((extra_config) && (extra_config->size)) { + char *p_char; + int len = 0; + int size = extra_config->size; + + while (size > 0) { + p_char = extra_config->data + len; + len = strlen(p_char) + 1; + size -= len; + + if (!strcmp(p_char, CUSTOM_EFFECT_CALLEE)) { + //parse next data(appid) from array + if (size > 0) { + p_char = p_char + len; + len = strlen(p_char) + 1; + size -= len; + + splash->appid = strdup(p_char); + splash->custom_effect_callee = true; + + ds_inf("custom effect callee set appid(%s)", + splash->appid); + } + else break; + } + } + } +} + +static const struct tizen_launch_splash_interface splash_impl = +{ + splash_handle_destroy, + splash_handle_launch, + splash_handle_owner, + splash_handle_launch_v2, +}; + +static void +splash_client_handle_destroy(struct wl_resource *resource) +{ + struct ds_tizen_splash *splash; + + splash = wl_resource_get_user_data(resource); + + ds_inf("splash_client_handle_destroy (client:%p)", splash->client); + + wl_signal_emit(&splash->events.destroy, splash); + wl_list_remove(&splash->link); + free(splash); +} + +struct ds_tizen_splash* +splash_create_splash_img(struct ds_tizen_effect_client *client, uint32_t id) +{ + struct ds_tizen_splash *splash; + + splash = calloc(1, sizeof *splash); + if (!splash) { + wl_client_post_no_memory(client->wl_client); + return NULL; + } + + splash->resource = wl_resource_create(client->wl_client, + &tizen_launch_splash_interface, wl_resource_get_version(client->resource), + id); + if (!splash->resource) { + free(splash); + wl_client_post_no_memory(client->wl_client); + return NULL; + } + splash->client = client; + splash->effect = client->effect; + splash->pid = SPLASH_CLIENT_PID; + + wl_signal_init(&splash->events.destroy); + wl_signal_init(&splash->events.owner); + + wl_resource_set_implementation(splash->resource, &splash_impl, + splash, splash_client_handle_destroy); + + wl_list_insert(&client->splashs, &splash->link); + + ds_inf("New Splash img %p (res %p)", splash, splash->resource); + + return splash; +} + +static void +effect_handle_create_splash_img(struct wl_client *wl_client, + struct wl_resource *resource, uint32_t id) +{ + struct ds_tizen_effect *effect; + struct ds_tizen_effect_client *client; + struct ds_tizen_effect_event_new_splash ds_event; + struct ds_tizen_splash *splash; + + client = wl_resource_get_user_data(resource); + splash = splash_create_splash_img(client, id); + if (!splash) return; + + effect = client->effect; + ds_event.splash = splash; + wl_signal_emit(&effect->events.new_splash, &ds_event); +} + +static void +effect_handle_type_set(struct wl_client *wl_client, + struct wl_resource *resource, const char *effect_type, uint32_t pid, + struct wl_array *options) +{ + struct ds_tizen_effect *effect; + struct ds_tizen_effect_client *client; + struct ds_tizen_effect_event_type_set ds_event; + + client = wl_resource_get_user_data(resource); + effect = client->effect; + + ds_event.pid = pid; + ds_event.effect_type = effect_get_effect_type(effect_type); + + ds_inf("Effect type_set. pid:%u type:%s", pid, effect_type); + + wl_signal_emit(&effect->events.type_set, &ds_event); +} + +static void +effect_handle_type_unset(struct wl_client *wl_client, + struct wl_resource *resource, uint32_t pid) +{ + struct ds_tizen_effect *effect; + struct ds_tizen_effect_client *client; + struct ds_tizen_effect_event_type_unset ds_event; + + client = wl_resource_get_user_data(resource); + effect = client->effect; + + ds_event.pid = pid; + + ds_inf("Effect type_unset. pid:%u", pid); + + wl_signal_emit(&effect->events.type_unset, &ds_event); +} + +static void +effect_handle_destroy(struct wl_client *wl_client, + struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static const struct tizen_launch_effect_interface effect_impl = +{ + effect_handle_create_splash_img, + effect_handle_type_set, + effect_handle_type_unset, + effect_handle_destroy, +}; + +static void +effect_client_handle_destroy(struct wl_resource *resource) +{ + struct ds_tizen_effect_client *client; + + client = wl_resource_get_user_data(resource); + + ds_inf("effect_client_handle_destroy (client:%p)", client); + + effect_client_destroy(client); +} + +static void effect_bind(struct wl_client *wl_client, void *data, + uint32_t version, uint32_t id) +{ + struct ds_tizen_effect *effect = data; + struct ds_tizen_effect_client *client; + + client = calloc(1, sizeof *client); + if (client == NULL) { + ds_err("calloc() failed. tizen_,launch_effect"); + wl_client_post_no_memory(wl_client); + return; + } + + ds_inf("tizen_effect. client binds. (client:%p)", client); + + client->effect = effect; + client->wl_client = wl_client; + + client->resource = wl_resource_create(wl_client, + &tizen_launch_effect_interface, + MIN(version, TIZEN_EFFECT_VERSION), id); + + if (client->resource == NULL) { + ds_err("tizen_effect : wl_resource_create() failed."); + free(client); + wl_client_post_no_memory(wl_client); + return; + } + + wl_list_init(&client->splashs); + + wl_resource_set_implementation(client->resource, &effect_impl, client, + effect_client_handle_destroy); + + wl_list_insert(&effect->clients, &client->link); +} diff --git a/src/launch/meson.build b/src/launch/meson.build index b3e2efd..494a933 100644 --- a/src/launch/meson.build +++ b/src/launch/meson.build @@ -1,5 +1,6 @@ libds_tizen_launch_files = [ 'appinfo.c', + 'effect.c', ] libds_tizen_launch_deps = [ diff --git a/tests/meson.build b/tests/meson.build index 40e737e..58051f6 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -85,6 +85,25 @@ executable('libds-tizen-launch-appinfo-tests', install : true ) +## launch effect tests +tc_launch_effect_files = [ + 'tc_main.cpp', + 'tc_launch_effect.cpp', +] + +executable('libds-tizen-launch-effect-tests', + [ + tc_mock_files, + tc_launch_effect_files + ], + dependencies: [ + deps_test_common, + deps_libds_tizen_launch, + ], + install_dir: libds_tizen_bindir, + install : true +) + ## display-policy tests tc_display_policy_files = [ 'tc_main.cpp', diff --git a/tests/tc_launch_effect.cpp b/tests/tc_launch_effect.cpp new file mode 100644 index 0000000..ebfd8ca --- /dev/null +++ b/tests/tc_launch_effect.cpp @@ -0,0 +1,476 @@ +#include "tc_main.h" +#include "mockclient.h" +#include "mockcompositor.h" +#include +#include +#include + +#define TIZEN_EFFECT_VERSION 1 +#define SPLASH_CLIENT_PID 321 // no meaning +#define CUSTOM_EFFECT_CALLEE "_CUSTOM_EFFECT_CALLEE_" +#define SPLASH_TYPE_IMG 0 +#define SPLASH_TYPE_EDC 1 + +//code from e-tizen-testcase +char const *path_edc = "/usr/share/e_tizen_unittests/data/launch_splash.edj"; +char const *path_img = "/usr/share/e_tizen_unittests/data/launchimg_splash.png"; + +class MockEffectCompositor : public MockCompositor +{ +public: + MockEffectCompositor() + : MockCompositor(&MockEffectCompositor::TestSetup, this) + { + ds_inf("%s : this(%p)", __func__, this); + + // initialize the flags to check + bDestroyed = false; + bTypeSet = false; + bNewSplash = false; + bOwner = false; + + mPid = 0; + mEffectType = -1; + } + + ~MockEffectCompositor() + { + ds_inf("%s : this(%p)", __func__, this); + } + + static void TestSetup(void *data) + { + MockEffectCompositor *mockComp = + static_cast(data); + Compositor *comp = mockComp->compositor; + + ds_inf("%s: mockComp(%p)", __func__, mockComp); + + mockComp->mEffect = ds_tizen_effect_create(comp->display); + + // destroy listener + mockComp->mDestroyListener.notify = + MockEffectCompositor::DestroyCallback; + mockComp->mDestroyListener.parent = mockComp; + ds_tizen_effect_add_destroy_listener(mockComp->mEffect, + &mockComp->mDestroyListener); + + // type_set listener + mockComp->mTypeSetListener.notify = + MockEffectCompositor::TypeSetCallback; + mockComp->mTypeSetListener.parent = mockComp; + ds_tizen_effect_add_type_set_listener(mockComp->mEffect, + &mockComp->mTypeSetListener); + + // type_unset listener + mockComp->mTypeUnsetListener.notify = + MockEffectCompositor::TypeUnsetCallback; + mockComp->mTypeUnsetListener.parent = mockComp; + ds_tizen_effect_add_type_unset_listener(mockComp->mEffect, + &mockComp->mTypeUnsetListener); + + // new_splash listener + mockComp->mNewSplashListener.notify = + MockEffectCompositor::NewSplashCallback; + mockComp->mNewSplashListener.parent = mockComp; + ds_tizen_effect_add_new_splash_listener(mockComp->mEffect, + &mockComp->mNewSplashListener); + } + + static void DestroyCallback(struct wl_listener *listener, void *data) + { + ds_inf("%s", __func__); + + MockEffectCompositor *mockComp = + reinterpret_cast(listener)->parent; + + mockComp->bDestroyed = true; + } + + static void TypeSetCallback(struct wl_listener *listener, void *data) + { + struct ds_tizen_effect_event_type_set *event = (ds_tizen_effect_event_type_set *)data; + ds_inf("%s", __func__); + + MockEffectCompositor *mockComp = + reinterpret_cast(listener)->parent; + + mockComp->bTypeSet = true; + mockComp->mPid = event->pid; + mockComp->mEffectType = event->effect_type; + } + + static void TypeUnsetCallback(struct wl_listener *listener, void *data) + { + struct ds_tizen_effect_event_type_unset *event = (ds_tizen_effect_event_type_unset *)data; + ds_inf("%s", __func__); + + MockEffectCompositor *mockComp = + reinterpret_cast(listener)->parent; + + mockComp->bTypeSet = false; + mockComp->mPid = event->pid; + mockComp->mEffectType = -1; + } + + + static void NewSplashCallback(struct wl_listener *listener, void *data) + { + struct ds_tizen_effect_event_new_splash *event = (ds_tizen_effect_event_new_splash *)data; + ds_inf("%s", __func__); + + MockEffectCompositor *mockComp = + reinterpret_cast(listener)->parent; + + mockComp->bNewSplash = true; + mockComp->mSplash = event->splash; + + // owner listener + mockComp->mOwnerListener.notify = + MockEffectCompositor::OwnerCallback; + mockComp->mOwnerListener.parent = mockComp; + ds_tizen_splash_add_owner_listener(mockComp->mSplash, + &mockComp->mOwnerListener); + } + + static void OwnerCallback(struct wl_listener *listener, void *data) + { + struct ds_tizen_splash_event_owner *event = (ds_tizen_splash_event_owner *)data; + ds_inf("%s", __func__); + + MockEffectCompositor *mockComp = + reinterpret_cast(listener)->parent; + + mockComp->mPid = event->pid; + } + +public: + bool bDestroyed; + bool bTypeSet; + bool bNewSplash; + bool bOwner; + + uint32_t mPid; + int mEffectType; + +private: + struct ds_tizen_effect *mEffect; + struct ds_tizen_splash *mSplash; + struct DestroyListener: ::wl_listener { + MockEffectCompositor *parent; + }; + DestroyListener mDestroyListener; + + struct TypeSetListener: ::wl_listener { + MockEffectCompositor *parent; + }; + TypeSetListener mTypeSetListener; + + struct TypeUnsetListener: ::wl_listener { + MockEffectCompositor *parent; + }; + TypeUnsetListener mTypeUnsetListener; + + struct NewSplashListener: ::wl_listener { + MockEffectCompositor *parent; + }; + NewSplashListener mNewSplashListener; + + struct OwnerListener: ::wl_listener { + MockEffectCompositor *parent; + }; + OwnerListener mOwnerListener; +}; + +class MockEffectClient : public MockClient +{ +public: + MockEffectClient() + : compositor_res(nullptr), + tizen_launch_effect(nullptr) + {} + + MockEffectClient(const struct wl_registry_listener *listener) + : MockClient(listener, this) + { + ds_inf("%s", __func__); + } + + ~MockEffectClient() + { + ds_inf("%s", __func__); + } + + void SetWlCompositor(struct wl_compositor *global_res) + { + ds_inf("%s", __func__); + + compositor_res = global_res; + } + + struct wl_compositor *GetWlCompositor() + { + ds_inf("%s", __func__); + + return compositor_res; + } + + void SetTizenEffect(struct tizen_launch_effect *global_res) + { + ds_inf("%s", __func__); + tizen_launch_effect = global_res; + } + + struct tizen_launch_effect *GetTizenEffect() + { + ds_inf("%s", __func__); + + return tizen_launch_effect; + } + +public: + +private: + struct wl_compositor *compositor_res; + struct tizen_launch_effect *tizen_launch_effect; +}; + +static void +client_registry_cb_global(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) +{ + ds_inf("%s", __func__); + + MockEffectClient *client = static_cast(data); + struct wl_compositor *compositor_res; + struct tizen_launch_effect *tizen_launch_effect; + + if (!strcmp(interface, "wl_compositor")) { + compositor_res = (struct wl_compositor *)wl_registry_bind(registry, + name, &wl_compositor_interface, 1); + if (compositor_res == nullptr) { + ds_err("wl_registry_bind() failed. wl_compositor resource."); + return; + } + client->SetWlCompositor(compositor_res); + } else if (!strcmp(interface, "tizen_launch_effect")) { + tizen_launch_effect = (struct tizen_launch_effect *)wl_registry_bind(registry, + name, &tizen_launch_effect_interface, TIZEN_EFFECT_VERSION); + if (tizen_launch_effect == nullptr) { + ds_err("wl_registry_bind() failed. tizen_launch_effect resource."); + return; + } + client->SetTizenEffect(tizen_launch_effect); + } +} + +static void +client_registry_cb_global_remove(void *data, struct wl_registry *registry, + uint32_t name) +{ + ds_inf("%s", __func__); + + MockEffectClient *client = static_cast(data); + struct wl_compositor *compositor_res = client->GetWlCompositor(); + struct tizen_launch_effect *effect_res = client->GetTizenEffect(); + + tizen_launch_effect_destroy(effect_res); + wl_compositor_destroy(compositor_res); +} + +static const struct wl_registry_listener registry_listener = { + .global = client_registry_cb_global, + .global_remove = client_registry_cb_global_remove +}; + +class EffectTest : public ::testing::Test +{ +public: + void SetUp(void) override; + void TearDown(void) override; + + MockEffectCompositor *comp; + MockEffectClient *client; + struct wl_compositor *compositor_res; + struct tizen_launch_effect *effect_res; +}; + +void +EffectTest::SetUp(void) +{ + ds_inf("%s", __func__); + + comp = new MockEffectCompositor(); + client = new MockEffectClient(®istry_listener); + compositor_res = client->GetWlCompositor(); + effect_res = client->GetTizenEffect(); + + client->RoundTrip(); +} + +void +EffectTest::TearDown(void) +{ + ds_inf("%s", __func__); + + client->RoundTrip(); + + delete client; + delete comp; +} + +TEST_F(EffectTest, Create_P) +{ + EXPECT_TRUE(true); +} + +TEST_F(EffectTest, Req_TizenEffectTypeSet) +{ + uint pid = 12345; + const char *effect_type; + + effect_type = "launch"; + tizen_launch_effect_type_set(effect_res, effect_type, pid, NULL); + client->RoundTrip(); + EXPECT_TRUE(comp->bTypeSet); + EXPECT_TRUE(comp->mPid == pid); + EXPECT_TRUE(comp->mEffectType == DS_TIZEN_EFFECT_TYPE_LAUNCH); +} + +TEST_F(EffectTest, Req_TizenEffectTypeUnSet) +{ + uint pid = 12345; + const char *effect_type; + + effect_type = "depth-in"; + tizen_launch_effect_type_set(effect_res, effect_type, pid, NULL); + client->RoundTrip(); + EXPECT_TRUE(comp->bTypeSet); + EXPECT_TRUE(comp->mPid == pid); + EXPECT_TRUE(comp->mEffectType == DS_TIZEN_EFFECT_TYPE_DEPTH_IN); + + tizen_launch_effect_type_unset(effect_res, pid); + client->RoundTrip(); + EXPECT_FALSE(comp->bTypeSet); + EXPECT_TRUE(comp->mPid == pid); + EXPECT_TRUE(comp->mEffectType == -1); +} + +TEST_F(EffectTest, Req_TizenEffectCreateSplashImg) +{ + struct tizen_launch_splash *splash = NULL; + + splash = tizen_launch_effect_create_splash_img(effect_res); + client->RoundTrip(); + EXPECT_TRUE(splash != NULL); + EXPECT_TRUE(comp->bNewSplash); +} + +TEST_F(EffectTest, Req_TizenSplashLaunch_EDC) +{ + struct tizen_launch_splash *splash = NULL; + struct wl_array options; + + splash = tizen_launch_effect_create_splash_img(effect_res); + client->RoundTrip(); + EXPECT_TRUE(splash != NULL); + EXPECT_TRUE(comp->bNewSplash); + + wl_array_init(&options); + + tizen_launch_splash_launch(splash, path_edc,\ + SPLASH_TYPE_EDC, 24, 0, 0, "launch", "default", &options); + client->RoundTrip(); + wl_array_release(&options); + EXPECT_TRUE(comp->mPid == SPLASH_CLIENT_PID); + EXPECT_TRUE(comp->mEffectType == DS_TIZEN_EFFECT_TYPE_LAUNCH); +} + +TEST_F(EffectTest, Req_TizenSplashLaunch_IMG) +{ + struct tizen_launch_splash *splash = NULL; + struct wl_array options; + + splash = tizen_launch_effect_create_splash_img(effect_res); + client->RoundTrip(); + EXPECT_TRUE(splash != NULL); + EXPECT_TRUE(comp->bNewSplash); + + wl_array_init(&options); + + tizen_launch_splash_launch(splash, path_img,\ + SPLASH_TYPE_IMG, 24, 0, 0, "launch", "default", &options); + client->RoundTrip(); + wl_array_release(&options); + EXPECT_TRUE(comp->mPid == SPLASH_CLIENT_PID); + EXPECT_TRUE(comp->mEffectType == DS_TIZEN_EFFECT_TYPE_LAUNCH); +} + +TEST_F(EffectTest, Req_TizenSplashSetOwner) +{ + struct tizen_launch_splash *splash = NULL; + struct wl_array options; + uint32_t pid = 12345; + + splash = tizen_launch_effect_create_splash_img(effect_res); + client->RoundTrip(); + EXPECT_TRUE(splash != NULL); + EXPECT_TRUE(comp->bNewSplash); + + wl_array_init(&options); + + tizen_launch_splash_launch(splash, path_img,\ + SPLASH_TYPE_IMG, 24, 0, 0, "depth-in", "default", &options); + client->RoundTrip(); + wl_array_release(&options); + EXPECT_TRUE(comp->mPid == SPLASH_CLIENT_PID); + EXPECT_TRUE(comp->mEffectType == DS_TIZEN_EFFECT_TYPE_DEPTH_IN); + + tizen_launch_splash_owner(splash, pid); + client->RoundTrip(); + EXPECT_TRUE(comp->mPid == pid); + EXPECT_TRUE(comp->mEffectType == DS_TIZEN_EFFECT_TYPE_DEPTH_IN); +} + +TEST_F(EffectTest, Req_TizenSplashLaunch_v2) + +{ + struct tizen_launch_splash *splash = NULL; + struct wl_array options; + struct wl_array extra_config; + int custom_effect = 0; + void *data; + int size; + const char *appid = "org.tizen.libds-tizen-launch-effect-test"; + + splash = tizen_launch_effect_create_splash_img(effect_res); + client->RoundTrip(); + EXPECT_TRUE(splash != NULL); + EXPECT_TRUE(comp->bNewSplash); + + // set + wl_array_init(&options); + size = strlen(appid) + 1; + data = wl_array_add(&options, size); + memcpy(data, appid, size); + + wl_array_init(&extra_config); + size = strlen(CUSTOM_EFFECT_CALLEE) + 1; + data = wl_array_add(&extra_config, size); + memcpy(data, CUSTOM_EFFECT_CALLEE, size); + + size = strlen(appid) + 1; + data = wl_array_add(&extra_config, size); + memcpy(data, appid, size); + + if (extra_config.size > 0) + custom_effect = 1; + + tizen_launch_splash_launch_v2(splash, path_edc,\ + SPLASH_TYPE_EDC, 24, 0, 0, "depth-in", "default", &options, custom_effect ? &extra_config : NULL); + client->RoundTrip(); + wl_array_release(&options); + wl_array_release(&extra_config); + EXPECT_TRUE(comp->mPid == SPLASH_CLIENT_PID); + EXPECT_TRUE(comp->mEffectType == DS_TIZEN_EFFECT_TYPE_DEPTH_IN); +}