From: SooChan Lim Date: Thu, 9 Nov 2023 10:03:11 +0000 (+0900) Subject: screen: add ds_tizen_screen X-Git-Tag: accepted/tizen/8.0/unified/20231229.032728 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Ftags%2Faccepted%2Ftizen%2F8.0%2Funified%2F20231229.032728;p=platform%2Fcore%2Fuifw%2Flibds-tizen.git screen: add ds_tizen_screen This is the implementation for wtz-screen server. Change-Id: I645d1b3db5941c839a0d94417b3588ff4ccf3216 --- diff --git a/include/libds-tizen/screen.h b/include/libds-tizen/screen.h new file mode 100644 index 0000000..11a39ab --- /dev/null +++ b/include/libds-tizen/screen.h @@ -0,0 +1,72 @@ +#ifndef LIBDS_TIZEN_SCREEN_H +#define LIBDS_TIZEN_SCREEN_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct ds_tizen_screen; +struct ds_tizen_splitscreen; +struct ds_tizen_splitscreen_region; + +enum ds_tizen_screen_capability +{ + DS_TIZEN_SCREEN_CAPABILITY_NONE, + DS_TIZEN_SCREEN_CAPABILITY_SPLITSCREEN, +}; + +WL_EXPORT struct ds_tizen_screen * +ds_tizen_screen_create(struct wl_display *display); + +WL_EXPORT void +ds_tizen_screen_add_capability(struct ds_tizen_screen *screen, + enum ds_tizen_screen_capability cap); + +WL_EXPORT void +ds_tizen_screen_add_destroy_listener(struct ds_tizen_screen *screen, + struct wl_listener *listener); + +WL_EXPORT void +ds_tizen_screen_add_get_splitscreen_listener( + struct ds_tizen_screen *screen, + struct wl_listener *listener); + + +WL_EXPORT void +ds_tizen_splitscreen_add_destroy_listener( + struct ds_tizen_splitscreen *splitscreen, + struct wl_listener *listener); + +WL_EXPORT void +ds_tizen_splitscreen_add_activate_listener( + struct ds_tizen_splitscreen *splitscreen, + struct wl_listener *listener); + +WL_EXPORT void +ds_tizen_splitscreen_add_deactivate_listener( + struct ds_tizen_splitscreen *splitscreen, + struct wl_listener *listener); + +WL_EXPORT struct ds_tizen_splitscreen_region * +ds_tizen_splitscreen_region_create( + struct ds_tizen_splitscreen *splitscreen, + const char *name, int32_t x, int32_t y, uint32_t w, uint32_t h); + +WL_EXPORT void +ds_tizen_splitscreen_region_add_destroy_listener( + struct ds_tizen_splitscreen_region *splitscreen_region, + struct wl_listener *listener); + +WL_EXPORT void +ds_tizen_splitscreen_region_add_assign_appid_listener( + struct ds_tizen_splitscreen_region *splitscreen_region, + struct wl_listener *listener); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/meson.build b/src/meson.build index f0163b4..4bb67a0 100644 --- a/src/meson.build +++ b/src/meson.build @@ -88,6 +88,7 @@ libds_tizen_files = [ 'keyrouter/keyrouter.c', 'security.c', 'display_policy/display_policy.c', + 'screen/screen.c', ] libds_tizen_deps = [ @@ -111,6 +112,7 @@ libds_tizen_deps = [ dependency('scaler-server', required: true), dependency('tizen-extension-server', required: true), dependency('xkbcommon', required: true), + dependency('wtz-screen-server', required: true), ] keylayout_dir = get_option('keylayout_dir') diff --git a/src/screen/screen.c b/src/screen/screen.c new file mode 100644 index 0000000..c5c9916 --- /dev/null +++ b/src/screen/screen.c @@ -0,0 +1,473 @@ +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "libds-tizen/screen.h" + +#define TIZEN_SCREEN_VERSION 1 + +struct ds_tizen_screen +{ + struct wl_global *global; + + struct wl_list clients; + + struct wl_listener destroy; + + struct wl_array capabilities; + + uint32_t splitscreen_capability; + + bool splitscreen_enabled; + + struct { + struct wl_signal destroy; + struct wl_signal get_splitscreen; + } events; +}; + +struct ds_tizen_screen_client +{ + struct ds_tizen_screen *screen; + + struct wl_resource *resource; + struct wl_client *client; + + struct { + struct wl_signal destroy; + } events; + + struct wl_list link; // ds_tizen_screen::clients +}; + +struct ds_tizen_splitscreen +{ + struct wl_resource *resource; + + struct ds_tizen_screen_client *screen_client; + struct ds_tizen_screen *screen; + + struct { + struct wl_signal destroy; + struct wl_signal activate; + struct wl_signal deactivate; + } events; +}; + +struct ds_tizen_splitscreen_region +{ + struct wl_resource *resource; + + const char *appid; + + struct { + struct wl_signal destroy; + struct wl_signal assign_appid; + } events; +}; + +static void +splitscreen_handle_destroy(struct wl_client *client, + struct wl_resource *splitscreen_resource) +{ + wl_resource_destroy(splitscreen_resource); +} + +static void +splitscreen_handle_activate(struct wl_client *client, + struct wl_resource *splitscreen_resource) +{ + struct ds_tizen_splitscreen *splitscreen; + + splitscreen = wl_resource_get_user_data(splitscreen_resource); + + ds_inf("screen_splitscreen:%p activate", splitscreen); + + wl_signal_emit_mutable(&splitscreen->events.activate, splitscreen); +} + +static void +splitscreen_handle_deactivate(struct wl_client *client, + struct wl_resource *splitscreen_resource) +{ + struct ds_tizen_splitscreen *splitscreen; + + splitscreen = wl_resource_get_user_data(splitscreen_resource); + + ds_inf("screen_splitscreen:%p deactivate", splitscreen); + + wl_signal_emit_mutable(&splitscreen->events.deactivate, splitscreen); +} + +static const struct wtz_splitscreen_interface splitscreen_impl = +{ + .destroy = splitscreen_handle_destroy, + .activate = splitscreen_handle_activate, + .deactivate = splitscreen_handle_deactivate, +}; + +static void +_tizen_screen_splitscreen_handle_resource_destroy(struct wl_resource *splitscreen_resource) +{ + struct ds_tizen_splitscreen *splitscreen; + struct ds_tizen_screen *screen; + + splitscreen = wl_resource_get_user_data(splitscreen_resource); + + ds_inf("screen_splitscreen:%p destroy", splitscreen); + + wl_signal_emit_mutable(&splitscreen->events.destroy, splitscreen); + + screen = splitscreen->screen; + screen->splitscreen_enabled = false; // unset splitscreen resource on a screen + + free(splitscreen); +} + +static void +screen_handle_get_splitscreen(struct wl_client *client, + struct wl_resource *screen_client_resource, + uint32_t id) +{ + struct ds_tizen_screen_client *screen_client; + struct ds_tizen_splitscreen *splitscreen; + struct ds_tizen_screen *screen; + + screen_client = wl_resource_get_user_data(screen_client_resource); + + screen = screen_client->screen; + + if (!screen->splitscreen_capability) { + wl_resource_post_error(screen_client_resource, WTZ_SCREEN_ERROR_NOT_SUPPORTED, + "Not Supported"); + return; + } + + // check splitscreen resource on a screen + // splitscreen resource is only one per a screen. + if (screen->splitscreen_enabled) { + wl_resource_post_error(screen_client_resource, WTZ_SCREEN_ERROR_INVALID_PARAMETER, + "Already Occupied"); + return; + } + + splitscreen = calloc(1, sizeof *splitscreen); + if (!splitscreen) { + wl_client_post_no_memory(client); + return; + } + + splitscreen->resource = wl_resource_create(client, &wtz_splitscreen_interface, + wl_resource_get_version(screen_client_resource), id); + if (!splitscreen->resource) { + wl_client_post_no_memory(client); + free(splitscreen); + return; + } + + splitscreen->screen_client = screen_client; + splitscreen->screen = screen; + + wl_resource_set_implementation(splitscreen->resource, &splitscreen_impl, + splitscreen, _tizen_screen_splitscreen_handle_resource_destroy); + + ds_inf("screen_splitscreen:%p create", splitscreen); + + wl_signal_init(&splitscreen->events.destroy); + wl_signal_init(&splitscreen->events.activate); + wl_signal_init(&splitscreen->events.deactivate); + + screen->splitscreen_enabled = true; // set splitscreen resource on a screen + + wl_signal_emit_mutable(&screen_client->screen->events.get_splitscreen, splitscreen); +} + +static void +screen_handle_destroy(struct wl_client *wl_client, + struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static const struct wtz_screen_interface screen_impl = +{ + .destroy = screen_handle_destroy, + .get_splitscreen = screen_handle_get_splitscreen, +}; + +static void +_tizen_screen_client_handle_resource_destroy(struct wl_resource *resource) +{ + struct ds_tizen_screen_client *client; + + client = wl_resource_get_user_data(resource); + + ds_inf("_tizen_screen_client_handle_destroy (client:%p)", client); + + wl_list_remove(&client->link); + free(client); +} + +static void +screen_bind(struct wl_client *wl_client, void *data, uint32_t version, + uint32_t id) +{ + struct ds_tizen_screen *screen = data; + struct ds_tizen_screen_client *screen_client; + + screen_client = calloc(1, sizeof *screen_client); + if (screen_client == NULL) { + ds_err("calloc() failed. tizen_screen"); + wl_client_post_no_memory(wl_client); + return; + } + + ds_inf("tizen_screen_client binds. (screen_client:%p)", screen_client); + + screen_client->screen = screen; + screen_client->client = wl_client; + + screen_client->resource = wl_resource_create(wl_client, &wtz_screen_interface, + MIN(version, TIZEN_SCREEN_VERSION), id); + if (screen_client->resource == NULL) { + ds_err("tizen_screen : wl_resource_create() failed."); + free(screen_client); + wl_client_post_no_memory(wl_client); + return; + } + + wl_resource_set_implementation(screen_client->resource, &screen_impl, screen_client, + _tizen_screen_client_handle_resource_destroy); + + // send the capabilities of the screen + wtz_screen_send_capabilities(screen_client->resource, &screen->capabilities); + + wl_signal_init(&screen_client->events.destroy); + + wl_list_insert(&screen->clients, &screen_client->link); +} + +static void +screen_handle_display_destroy(struct wl_listener *listener, void *data) +{ + struct ds_tizen_screen *screen; + + screen = wl_container_of(listener, screen, destroy); + + ds_inf("Global destroy: screen(%p)", screen); + + wl_signal_emit_mutable(&screen->events.destroy, screen); + wl_list_remove(&screen->destroy.link); + wl_global_destroy(screen->global); + free(screen); +} + +WL_EXPORT struct ds_tizen_screen * +ds_tizen_screen_create(struct wl_display *display) +{ + struct ds_tizen_screen *screen; + + screen = calloc(1, sizeof *screen); + if (!screen) { + ds_err("calloc() failed."); + return NULL; + } + + screen->global = wl_global_create(display, &wtz_screen_interface, + TIZEN_SCREEN_VERSION, screen, screen_bind); + if (!screen->global) { + ds_err("wl_global_create() failed. wtz_screen_interface"); + free(screen); + return NULL; + } + + wl_list_init(&screen->clients); + + screen->destroy.notify = screen_handle_display_destroy; + wl_display_add_destroy_listener(display, &screen->destroy); + + wl_array_init(&screen->capabilities); + + wl_signal_init(&screen->events.destroy); + wl_signal_init(&screen->events.get_splitscreen); + + ds_inf("Global created: tizen_screen(%p)", screen); + + return screen; +} + +static void +_screen_capability_add(struct wl_array *capabilities, uint32_t cap) +{ + uint32_t *c; + + c = wl_array_add(capabilities, sizeof(*c)); + if (c) + *c = cap; + else + ds_err("wl_array_add() failed"); +} + +WL_EXPORT void +ds_tizen_screen_add_capability( + struct ds_tizen_screen *screen, + enum ds_tizen_screen_capability cap) +{ + uint32_t capability; + + ds_inf("screen:%p add capability(%d)", screen, cap); + + if (cap == DS_TIZEN_SCREEN_CAPABILITY_SPLITSCREEN) { + capability = WTZ_SCREEN_CAPABILITY_SPLITSCREEN; + screen->splitscreen_capability = 1; + } else + capability = WTZ_SCREEN_CAPABILITY_NONE; + + _screen_capability_add(&screen->capabilities, capability); +} + +WL_EXPORT void +ds_tizen_screen_add_destroy_listener( + struct ds_tizen_screen *screen, + struct wl_listener *listener) +{ + wl_signal_add(&screen->events.destroy, listener); +} + +WL_EXPORT void +ds_tizen_screen_add_get_splitscreen_listener( + struct ds_tizen_screen *screen, + struct wl_listener *listener) +{ + wl_signal_add(&screen->events.get_splitscreen, listener); +} + +WL_EXPORT void +ds_tizen_splitscreen_add_destroy_listener( + struct ds_tizen_splitscreen *splitscreen, + struct wl_listener *listener) +{ + wl_signal_add(&splitscreen->events.destroy, listener); +} + +WL_EXPORT void +ds_tizen_splitscreen_add_activate_listener( + struct ds_tizen_splitscreen *splitscreen, + struct wl_listener *listener) +{ + wl_signal_add(&splitscreen->events.activate, listener); +} + +WL_EXPORT void +ds_tizen_splitscreen_add_deactivate_listener( + struct ds_tizen_splitscreen *splitscreen, + struct wl_listener *listener) +{ + wl_signal_add(&splitscreen->events.deactivate, listener); +} + +static void +splitscreen_region_handle_destroy(struct wl_client *client, + struct wl_resource *splitscreen_region_resource) +{ + wl_resource_destroy(splitscreen_region_resource); +} + +static void +splitscreen_region_handle_assign_appid(struct wl_client *client, + struct wl_resource *splitscreen_region_resource, const char *appid) +{ + struct ds_tizen_splitscreen_region *splitscreen_region; + + splitscreen_region = wl_resource_get_user_data(splitscreen_region_resource); + + ds_inf("screen_splitscreen_region:%p assign_appid", splitscreen_region); + + splitscreen_region->appid = appid; + + wl_signal_emit_mutable(&splitscreen_region->events.assign_appid, (void *)appid); +} + +static const struct wtz_splitscreen_region_interface splitscreen_region_impl = +{ + .destroy = splitscreen_region_handle_destroy, + .assign_appid = splitscreen_region_handle_assign_appid, +}; + +static void +_tizen_screen_splitscreen_region_handle_resource_destroy( + struct wl_resource *splitscreen_region_resource) +{ + struct ds_tizen_splitscreen_region *splitscreen_region; + + splitscreen_region = wl_resource_get_user_data(splitscreen_region_resource); + + ds_inf("screen_splitscreen_region:%p destroy", splitscreen_region); + + wl_signal_emit_mutable(&splitscreen_region->events.destroy, + splitscreen_region); + + free(splitscreen_region); +} + +WL_EXPORT struct ds_tizen_splitscreen_region * +ds_tizen_splitscreen_region_create( + struct ds_tizen_splitscreen *splitscreen, + const char *name, int32_t x, int32_t y, uint32_t w, uint32_t h) +{ + struct ds_tizen_splitscreen_region *splitscreen_region; + struct ds_tizen_screen_client *screen_client; + + splitscreen_region = calloc(1, sizeof *splitscreen_region); + if (!splitscreen_region) { + ds_err("calloc() failed."); + return NULL; + } + + screen_client = splitscreen->screen_client; + + splitscreen_region->resource = wl_resource_create(screen_client->client, + &wtz_splitscreen_region_interface, + TIZEN_SCREEN_VERSION, 0); + if (!splitscreen_region->resource) { + ds_err("wl_resource_create() failed. wtz_splitscreen_region_interface"); + free(splitscreen_region); + return NULL; + } + + wl_resource_set_implementation(splitscreen_region->resource, + &splitscreen_region_impl, splitscreen_region, + _tizen_screen_splitscreen_region_handle_resource_destroy); + + // send the splitscreen_region resources + wtz_splitscreen_send_region(splitscreen->resource, splitscreen_region->resource); + + // send the name of the split_screen_region + wtz_splitscreen_region_send_name(splitscreen_region->resource, name); + + // send the geometry of the split_screen_region + wtz_splitscreen_region_send_geometry( + splitscreen_region->resource, x, y, w, h); + + return splitscreen_region; +} + +WL_EXPORT void +ds_tizen_splitscreen_region_add_destroy_listener( + struct ds_tizen_splitscreen_region *splitscreen_region, + struct wl_listener *listener) +{ + wl_signal_add(&splitscreen_region->events.destroy, listener); +} + +WL_EXPORT void +ds_tizen_splitscreen_region_add_assign_appid_listener( + struct ds_tizen_splitscreen_region *splitscreen_region, + struct wl_listener *listener) +{ + wl_signal_add(&splitscreen_region->events.assign_appid, listener); +} \ No newline at end of file