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),
],
#include <libds-tizen/input_devicemgr.h>
#include <xkbcommon/xkbcommon.h>
#include <libds/interfaces/keyboard.h>
+#include <libds-tizen/launch/effect.h>
#define USE_TDM_BUFFER_QUEUE
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;
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;
int x, y;
bool mapped;
+
+ pid_t pid;
+ int effect_type;
};
struct tinyds_pointer
}
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)
{
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) {
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);
}
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)
{
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:
--- /dev/null
+#ifndef LIBDS_TIZEN_EFFECT_H
+#define LIBDS_TIZEN_EFFECT_H
+
+#include <stdint.h>
+#include <wayland-server.h>
+
+#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
%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
--- /dev/null
+#include <stdlib.h>
+#include <wayland-server.h>
+#include <tizen-launch-server-protocol.h>
+#include <libds/log.h>
+
+#include "util.h"
+#include <libds-tizen/launch/effect.h>
+
+#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);
+}
libds_tizen_launch_files = [
'appinfo.c',
+ 'effect.c',
]
libds_tizen_launch_deps = [
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',
--- /dev/null
+#include "tc_main.h"
+#include "mockclient.h"
+#include "mockcompositor.h"
+#include <libds-tizen/launch/effect.h>
+#include <tizen-launch-server-protocol.h>
+#include <tizen-launch-client-protocol.h>
+
+#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<MockEffectCompositor *>(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<DestroyListener *>(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<TypeSetListener *>(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<TypeUnsetListener *>(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<NewSplashListener *>(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<OwnerListener *>(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<MockEffectClient *>(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<MockEffectClient *>(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);
+}