screen: add ds_tizen_screen 65/301265/1 accepted/tizen_8.0_unified tizen_7.0_mc tizen_8.0 accepted/tizen/8.0/unified/20231229.032728 accepted/tizen/unified/20231114.041330
authorSooChan Lim <sc1.lim@samsung.com>
Thu, 9 Nov 2023 10:03:11 +0000 (19:03 +0900)
committerTizen Window System <tizen.windowsystem@gmail.com>
Mon, 13 Nov 2023 06:55:49 +0000 (15:55 +0900)
This is the implementation for wtz-screen server.

Change-Id: I645d1b3db5941c839a0d94417b3588ff4ccf3216

include/libds-tizen/screen.h [new file with mode: 0644]
src/meson.build
src/screen/screen.c [new file with mode: 0644]

diff --git a/include/libds-tizen/screen.h b/include/libds-tizen/screen.h
new file mode 100644 (file)
index 0000000..11a39ab
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef LIBDS_TIZEN_SCREEN_H
+#define LIBDS_TIZEN_SCREEN_H
+
+#include <stdint.h>
+#include <wayland-server.h>
+
+#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
index f0163b4..4bb67a0 100644 (file)
@@ -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 (file)
index 0000000..c5c9916
--- /dev/null
@@ -0,0 +1,473 @@
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <wayland-server.h>
+#include <wtz-screen-server-protocol.h>
+#include <libds/log.h>
+
+#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