impelement libds-tizen-indicator 89/278389/1
authorSooChan Lim <sc1.lim@samsung.com>
Thu, 7 Jul 2022 10:28:26 +0000 (19:28 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Wed, 20 Jul 2022 05:05:14 +0000 (14:05 +0900)
This is the server implementation for tizen_indicator protocol.

Change-Id: I97efef30d5f9e5c540d51b92bcac43808b53951a

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

diff --git a/include/libds-tizen/indicator.h b/include/libds-tizen/indicator.h
new file mode 100644 (file)
index 0000000..69fc82e
--- /dev/null
@@ -0,0 +1,75 @@
+#ifndef LIBDS_TIZEN_INDICATOR_H
+#define LIBDS_TIZEN_INDICATOR_H
+
+#include <stdint.h>
+#include <wayland-server.h>
+#include <libds/surface.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ds_tizen_indicator;
+
+enum ds_tizen_indicator_state
+{
+    DS_TIZEN_INDICATOR_STATE_UNKNOWN,
+    DS_TIZEN_INDICATOR_STATE_OFF,
+    DS_TIZEN_INDICATOR_STATE_ON,
+};
+
+enum ds_tizen_indicator_opacity_mode
+{
+    DS_TIZEN_INDICATOR_OPACITY_MODE_UNKNOWN,
+    DS_TIZEN_INDICATOR_OPACITY_MODE_OPAQUE,
+    DS_TIZEN_INDICATOR_OPACITY_MODE_TRANSLUCENT,
+    DS_TIZEN_INDICATOR_OPACITY_MODE_TRANSPARENT,
+    DS_TIZEN_INDICATOR_OPACITY_MODE_BG_TRANSPARENT,
+};
+
+enum ds_tizen_indicator_visible_type
+{
+    DS_TIZEN_INDICATOR_VISIBLE_TYPE_HIDDEN,
+    DS_TIZEN_INDICATOR_VISIBLE_TYPE_SHOWN,
+};
+
+struct ds_tizen_indicator *
+ds_tizen_indicator_create(struct wl_display *display);
+
+void
+ds_tizen_indicator_add_destroy_listener(struct ds_tizen_indicator *indicator,
+        struct wl_listener *listener);
+
+void
+ds_tizen_indicator_add_change_state_listener(
+        struct ds_tizen_indicator *indicator, struct wl_listener *listener);
+
+void
+ds_tizen_indicator_add_change_opacity_mode_listener(
+        struct ds_tizen_indicator *indicator, struct wl_listener *listener);
+
+void
+ds_tizen_indicator_add_change_visible_type_listener(
+        struct ds_tizen_indicator *indicator, struct wl_listener *listener);
+
+enum ds_tizen_indicator_state
+ds_tizen_indicator_get_state(struct ds_tizen_indicator *indicator,
+        struct ds_surface *surface);
+
+enum ds_tizen_indicator_opacity_mode
+ds_tizen_indicator_get_opacity_mode(struct ds_tizen_indicator *indicator,
+        struct ds_surface *surface);
+
+enum ds_tizen_indicator_visible_type
+ds_tizen_indicator_get_visible_type(struct ds_tizen_indicator *indicator,
+        struct ds_surface *surface);
+
+void
+ds_tizen_indicator_send_flick(struct ds_tizen_indicator *indicator,
+        struct ds_surface *surface);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
index c5e0623..34b918c 100644 (file)
@@ -122,6 +122,21 @@ Group:   Development/Libraries
 %description dpms-devel
 Development package for tizen dpms
 
+## libds-tizen-indicator
+%package indicator
+Summary: Library for tizen indicator
+Group:   Development/Libraries
+
+%description indicator
+Library for tizen indicator
+
+%package indicator-devel
+Summary: Development package for tizen indicator
+Group:   Development/Libraries
+
+%description indicator-devel
+Development package for tizen indicator
+
 %prep
 %setup -q
 cp %{SOURCE1001} .
@@ -232,3 +247,17 @@ ninja -C builddir install
 %{_libdir}/libds-tizen-dpms.so
 %{_bindir}/tinyds-tdm-dpms
 %{_bindir}/ds-simple-dpms
+
+%files indicator
+%manifest %{name}.manifest
+%defattr(-,root,root,-)
+%license LICENSE
+%{_libdir}/libds-tizen-indicator.so.*
+
+%files indicator-devel
+%manifest %{name}.manifest
+%defattr(-,root,root,-)
+%license LICENSE
+%{_includedir}/libds-tizen/indicator.h
+%{_libdir}/pkgconfig/libds-tizen-indicator.pc
+%{_libdir}/libds-tizen-indicator.so
diff --git a/src/indicator/indicator.c b/src/indicator/indicator.c
new file mode 100644 (file)
index 0000000..23f0e9f
--- /dev/null
@@ -0,0 +1,499 @@
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <wayland-server.h>
+#include <tizen-extension-server-protocol.h>
+#include <libds/log.h>
+
+#include "util.h"
+#include "libds-tizen/indicator.h"
+
+#define TIZEN_INDICATOR_VERSION 1
+
+struct ds_tizen_indicator
+{
+    struct wl_global *global;
+
+    struct wl_list clients;
+
+    struct wl_listener destroy;
+
+    struct {
+        struct wl_signal destroy;
+        struct wl_signal change_state;
+        struct wl_signal change_opacity_mode;
+        struct wl_signal change_visible_type;
+    } events;
+};
+
+struct ds_tizen_indicator_client
+{
+    struct ds_tizen_indicator *indicator;
+
+    struct wl_resource *resource;
+    struct wl_client *wl_client;
+
+    struct wl_list infos;
+
+    struct wl_list link; // ds_tizen_indicator::clients
+};
+
+struct ds_tizen_indicator_info
+{
+    struct ds_surface *surface;
+
+    int32_t state;
+    int32_t opacity_mode;
+    int32_t visible_type;
+
+    struct wl_list link; // ds_tizen_indicator_client::infos
+};
+
+static void indicator_handle_display_destroy(struct wl_listener *listener,
+        void *data);
+
+static void indicator_bind(struct wl_client *wl_client, void *data,
+        uint32_t version, uint32_t id);
+
+static struct ds_tizen_indicator_client *tizen_indicator_find_client(
+    struct ds_tizen_indicator *indicator,
+    struct ds_surface *surface);
+
+static struct ds_tizen_indicator_info *tizen_indicator_find_info(
+        struct ds_tizen_indicator *indicator,
+        struct ds_surface *surface);
+
+static struct ds_tizen_indicator_info *tizen_indicator_client_find_info(
+    struct ds_tizen_indicator_client *client,
+    struct ds_surface *surface);
+
+static struct ds_tizen_indicator_info *tizen_indicator_client_get_info(
+        struct ds_tizen_indicator_client *client,
+        struct ds_surface *surface);
+
+WL_EXPORT struct ds_tizen_indicator *
+ds_tizen_indicator_create(struct wl_display *display)
+{
+    struct ds_tizen_indicator *indicator;
+
+    indicator = calloc(1, sizeof *indicator);
+    if (!indicator) {
+        ds_err("calloc() failed.");
+        return NULL;
+    }
+
+    indicator->global = wl_global_create(display, &tizen_indicator_interface,
+            1, indicator, indicator_bind);
+    if (!indicator->global) {
+        ds_err("wl_global_create() failed. tizen_indicator_interface");
+        free(indicator);
+        return NULL;
+    }
+
+    wl_list_init(&indicator->clients);
+
+    indicator->destroy.notify = indicator_handle_display_destroy;
+    wl_display_add_destroy_listener(display, &indicator->destroy);
+
+    wl_signal_init(&indicator->events.destroy);
+    wl_signal_init(&indicator->events.change_state);
+    wl_signal_init(&indicator->events.change_opacity_mode);
+    wl_signal_init(&indicator->events.change_visible_type);
+
+       ds_inf("Global created: tizen_indicator(%p)", indicator);
+
+    return indicator;
+}
+
+WL_EXPORT void
+ds_tizen_indicator_add_destroy_listener(struct ds_tizen_indicator *indicator,
+        struct wl_listener *listener)
+{
+    wl_signal_add(&indicator->events.destroy, listener);
+}
+
+WL_EXPORT void
+ds_tizen_indicator_add_change_state_listener(
+    struct ds_tizen_indicator *indicator, struct wl_listener *listener)
+{
+    wl_signal_add(&indicator->events.change_state, listener);
+}
+
+WL_EXPORT void
+ds_tizen_indicator_add_change_opacity_mode_listener(
+    struct ds_tizen_indicator *indicator, struct wl_listener *listener)
+{
+    wl_signal_add(&indicator->events.change_opacity_mode, listener);
+}
+
+WL_EXPORT void
+ds_tizen_indicator_add_change_visible_type_listener(
+    struct ds_tizen_indicator *indicator, struct wl_listener *listener)
+{
+    wl_signal_add(&indicator->events.change_visible_type, listener);
+}
+
+WL_EXPORT enum ds_tizen_indicator_state
+ds_tizen_indicator_get_state(struct ds_tizen_indicator *indicator,
+        struct ds_surface *surface)
+{
+    struct ds_tizen_indicator_info *info;
+
+    info = tizen_indicator_find_info(indicator, surface);
+    if (info == NULL) {
+        ds_err("tizen_indicator: tizen_indicator_find_info() failed.");
+        return DS_TIZEN_INDICATOR_STATE_UNKNOWN;
+    }
+
+    return info->state;
+}
+
+WL_EXPORT enum ds_tizen_indicator_opacity_mode
+ds_tizen_indicator_get_opacity_mode(struct ds_tizen_indicator *indicator,
+        struct ds_surface *surface)
+{
+    struct ds_tizen_indicator_info *info;
+
+    info = tizen_indicator_find_info(indicator, surface);
+    if (info == NULL) {
+        ds_err("tizen_indicator: tizen_indicator_find_info() failed.");
+        return DS_TIZEN_INDICATOR_OPACITY_MODE_UNKNOWN;
+    }
+
+    return info->opacity_mode;
+}
+
+WL_EXPORT enum ds_tizen_indicator_visible_type
+ds_tizen_indicator_get_visible_type(struct ds_tizen_indicator *indicator,
+        struct ds_surface *surface)
+{
+    struct ds_tizen_indicator_info *info;
+
+    info = tizen_indicator_find_info(indicator, surface);
+    if (info == NULL) {
+        ds_err("tizen_indicator: tizen_indicator_find_info() failed.");
+        return DS_TIZEN_INDICATOR_VISIBLE_TYPE_HIDDEN;
+    }
+
+    return info->visible_type;
+}
+
+WL_EXPORT void
+ds_tizen_indicator_send_flick(struct ds_tizen_indicator *indicator,
+        struct ds_surface *surface)
+{
+    struct ds_tizen_indicator_client *client;
+
+    client = tizen_indicator_find_client(indicator, surface);
+    if (client == NULL) {
+        ds_err("tizen_indicator: tizen_indicator_find_client() failed.");
+        return;
+    }
+
+    tizen_indicator_send_flick(client->resource,
+        ds_surface_get_wl_resource(surface), 0);
+}
+
+static struct ds_tizen_indicator_client *
+tizen_indicator_find_client(struct ds_tizen_indicator *indicator,
+    struct ds_surface *surface)
+{
+    struct ds_tizen_indicator_info *info;
+    struct ds_tizen_indicator_client *client;
+
+    wl_list_for_each(client, &indicator->clients, link) {
+        info = tizen_indicator_client_find_info(client, surface);
+        if (info != NULL)
+            return client;
+    }
+
+    return NULL;
+}
+
+static struct ds_tizen_indicator_info *
+tizen_indicator_find_info(struct ds_tizen_indicator *indicator,
+    struct ds_surface *surface)
+{
+    struct ds_tizen_indicator_info *info;
+    struct ds_tizen_indicator_client *client;
+
+    wl_list_for_each(client, &indicator->clients, link) {
+        info = tizen_indicator_client_find_info(client, surface);
+        if (info != NULL)
+            return info;
+    }
+
+    return NULL;
+}
+
+static struct ds_tizen_indicator_info *
+tizen_indicator_client_find_info(struct ds_tizen_indicator_client *client,
+    struct ds_surface *surface)
+{
+    struct ds_tizen_indicator_info *info;
+
+    wl_list_for_each(info, &client->infos, link) {
+        if (surface == info->surface)
+            return info;
+    }
+
+    return NULL;
+}
+
+static struct ds_tizen_indicator_info *
+tizen_indicator_client_get_info(struct ds_tizen_indicator_client *client,
+    struct ds_surface *surface)
+{
+    struct ds_tizen_indicator_info *info;
+
+    info = tizen_indicator_client_find_info(client, surface);
+    if (info)
+        return info;
+
+    info = calloc(1, sizeof *info);
+    if (info == NULL) {
+        ds_err("calloc() failed. tizen_indicator");
+        return NULL;
+    }
+
+    info->surface = surface;
+
+    // The initial values of state, opacity_mode and visible_type are not
+    // each value of enum ds_tizen_indicator_state,
+    // enum ds_tizen_indicator_opacity_mode and
+    // enum ds_tizen_indicator_opacity_mode
+    // because of the first signal emit for change_state signal.
+    info->state = -1;
+    info->opacity_mode = -1;
+    info->visible_type = -1;
+
+    wl_list_insert(&client->infos, &info->link);
+
+    return info;
+}
+
+static void
+indicator_handle_display_destroy(struct wl_listener *listener, void *data)
+{
+    struct ds_tizen_indicator *indicator;
+
+    indicator = wl_container_of(listener, indicator, destroy);
+
+    ds_inf("Global destroy: indicator(%p)", indicator);
+
+    wl_signal_emit(&indicator->events.destroy, indicator);
+    wl_list_remove(&indicator->destroy.link);
+    wl_global_destroy(indicator->global);
+    free(indicator);
+}
+
+static void
+indicator_handle_destroy(struct wl_client *wl_client,
+    struct wl_resource *resource)
+{
+    struct ds_tizen_indicator_client *client;
+
+    client = wl_resource_get_user_data(resource);
+
+    if (!wl_list_empty(&client->infos)) {
+        ds_err("tizen_indicator was destroyed before children");
+        return;
+    }
+
+    wl_resource_destroy(resource);
+}
+
+static void
+indicator_handle_set_state(struct wl_client *wl_client,
+    struct wl_resource *resource, struct wl_resource *surface_resource,
+    int32_t state)
+{
+    struct ds_tizen_indicator_client *client;
+    struct ds_tizen_indicator_info *info;
+    struct ds_surface *surface;
+    enum ds_tizen_indicator_state indicator_state;
+
+    ds_inf("tizen_indicator: set_state : state %d", state);
+
+    client = wl_resource_get_user_data(resource);
+    surface = ds_surface_from_resource(surface_resource);
+
+    info = tizen_indicator_client_get_info(client, surface);
+    if (info == NULL) {
+        ds_err("tizen_indicator_client_get_info() failed. tizen_indicator");
+        wl_client_post_no_memory(wl_client);
+        return;
+    }
+
+    switch (state) {
+        case TIZEN_INDICATOR_STATE_OFF:
+            indicator_state = DS_TIZEN_INDICATOR_STATE_OFF;
+            break;
+        case TIZEN_INDICATOR_STATE_ON:
+            indicator_state = DS_TIZEN_INDICATOR_STATE_ON;
+            break;
+        default:
+            indicator_state = DS_TIZEN_INDICATOR_STATE_UNKNOWN;
+            break;
+    }
+
+    if (info->state != indicator_state) {
+        ds_inf("tizen_indicator: surface : %p, change_state : %d -> %d",
+            surface, info->state, indicator_state);
+        info->state = indicator_state;
+
+        wl_signal_emit(&client->indicator->events.change_state, surface);
+    }
+}
+
+static void
+indicator_handle_set_opacity_mode(struct wl_client *wl_client,
+    struct wl_resource *resource, struct wl_resource *surface_resource,
+    int32_t mode)
+{
+    struct ds_tizen_indicator_client *client;
+    struct ds_tizen_indicator_info *info;
+    struct ds_surface *surface;
+    enum ds_tizen_indicator_opacity_mode opacity_mode;
+
+    ds_inf("tizen_indicator: set_opacity_mode : opacity_mode %d", mode);
+
+    client = wl_resource_get_user_data(resource);
+    surface = ds_surface_from_resource(surface_resource);
+
+    info = tizen_indicator_client_get_info(client, surface);
+    if (info == NULL) {
+        ds_err("tizen_indicator_client_get_info() failed. tizen_indicator");
+        wl_client_post_no_memory(wl_client);
+        return;
+    }
+
+    switch (mode) {
+        case TIZEN_INDICATOR_OPACITY_MODE_OPAQUE:
+            opacity_mode = DS_TIZEN_INDICATOR_OPACITY_MODE_OPAQUE;
+            break;
+        case TIZEN_INDICATOR_OPACITY_MODE_TRANSLUCENT:
+            opacity_mode = DS_TIZEN_INDICATOR_OPACITY_MODE_TRANSLUCENT;
+            break;
+        case TIZEN_INDICATOR_OPACITY_MODE_TRANSPARENT:
+            opacity_mode = DS_TIZEN_INDICATOR_OPACITY_MODE_TRANSPARENT;
+            break;
+        case TIZEN_INDICATOR_OPACITY_MODE_BG_TRANSPARENT:
+            opacity_mode = DS_TIZEN_INDICATOR_OPACITY_MODE_BG_TRANSPARENT;
+            break;
+        default:
+            opacity_mode = DS_TIZEN_INDICATOR_OPACITY_MODE_UNKNOWN;
+            break;
+    }
+
+    if (info->opacity_mode != opacity_mode) {
+        ds_inf("tizen_indicator: surface : %p, change_opacity_mode : %d -> %d",
+            surface, info->opacity_mode, opacity_mode);
+        info->opacity_mode = opacity_mode;
+
+        wl_signal_emit(&client->indicator->events.change_opacity_mode, surface);
+    }
+}
+
+static void
+indicator_handle_set_visible_type(struct wl_client *wl_client,
+    struct wl_resource *resource, struct wl_resource *surface_resource,
+    int32_t type)
+{
+    struct ds_tizen_indicator_client *client;
+    struct ds_tizen_indicator_info *info;
+    struct ds_surface *surface;
+    enum ds_tizen_indicator_visible_type visible_type;
+
+    ds_inf("tizen_indicator: set_visible_type : visible_type %d", type);
+
+    client = wl_resource_get_user_data(resource);
+    surface = ds_surface_from_resource(surface_resource);
+
+    info = tizen_indicator_client_get_info(client, surface);
+    if (info == NULL) {
+        ds_err("tizen_indicator_client_get_info() failed. tizen_indicator");
+        wl_client_post_no_memory(wl_client);
+        return;
+    }
+
+    switch (type) {
+        case TIZEN_INDICATOR_VISIBLE_TYPE_SHOWN:
+            visible_type = DS_TIZEN_INDICATOR_VISIBLE_TYPE_SHOWN;
+            break;
+        default:
+            visible_type = DS_TIZEN_INDICATOR_VISIBLE_TYPE_HIDDEN;
+            break;
+    }
+
+    if (info->visible_type != visible_type) {
+        ds_inf("tizen_indicator: surface : %p, change_visible_type : %d -> %d",
+            surface, info->visible_type, visible_type);
+        info->visible_type = visible_type;
+
+        wl_signal_emit(&client->indicator->events.change_visible_type, surface);
+    }
+}
+
+static const struct tizen_indicator_interface indicator_impl =
+{
+   indicator_handle_destroy,
+   indicator_handle_set_state,
+   indicator_handle_set_opacity_mode,
+   indicator_handle_set_visible_type,
+};
+
+static void
+_tizen_indicator_client_handle_destroy(struct wl_resource *resource)
+{
+    struct ds_tizen_indicator_client *client;
+    struct ds_tizen_indicator_info *info, *tmp;
+
+    client = wl_resource_get_user_data(resource);
+
+    ds_inf("_tizen_indicator_client_handle_destroy (client:%p)", client);
+
+    wl_list_for_each_safe(info, tmp, &client->infos, link) {
+        wl_list_remove(&info->link);
+        free(info);
+    }
+
+    wl_list_remove(&client->link);
+    free(client);
+}
+
+static void
+indicator_bind(struct wl_client *wl_client, void *data, uint32_t version,
+        uint32_t id)
+{
+    struct ds_tizen_indicator *indicator = data;
+    struct ds_tizen_indicator_client *client;
+
+    client = calloc(1, sizeof *client);
+    if (client == NULL) {
+        ds_err("calloc() failed. tizen_indicator");
+        wl_client_post_no_memory(wl_client);
+        return;
+    }
+
+    ds_inf("tizen_indicator_client binds. (client:%p)", client);
+
+    client->indicator = indicator;
+    client->wl_client = wl_client;
+
+    wl_list_init(&client->infos);
+
+    client->resource = wl_resource_create(wl_client, &tizen_indicator_interface,
+            MIN(version, TIZEN_INDICATOR_VERSION), id);
+    if (client->resource == NULL) {
+        ds_err("tizen_indicator : wl_resource_create() failed.");
+        free(client);
+        wl_client_post_no_memory(wl_client);
+        return;
+    }
+
+    wl_resource_set_implementation(client->resource, &indicator_impl, client,
+            _tizen_indicator_client_handle_destroy);
+
+    wl_list_insert(&indicator->clients, &client->link);
+}
diff --git a/src/indicator/meson.build b/src/indicator/meson.build
new file mode 100644 (file)
index 0000000..a87c690
--- /dev/null
@@ -0,0 +1,29 @@
+libds_tizen_indicator_files = [
+  'indicator.c',
+]
+
+libds_tizen_indicator_deps = [
+  deps_libds_tizen,
+  dependency('tizen-extension-server', required: true),
+]
+
+lib_libds_tizen_indicator = shared_library('ds-tizen-indicator', libds_tizen_indicator_files,
+  dependencies: libds_tizen_indicator_deps,
+  include_directories: [ common_inc, include_directories('.'), include_directories('..') ],
+  version: meson.project_version(),
+  install: true
+)
+
+deps_libds_tizen_indicator = declare_dependency(
+  link_with: lib_libds_tizen_indicator,
+  dependencies: libds_tizen_indicator_deps,
+  include_directories: [ common_inc, include_directories('.') ],
+)
+
+pkgconfig = import('pkgconfig')
+pkgconfig.generate(lib_libds_tizen_indicator,
+  version: meson.project_version(),
+  filebase: 'libds-tizen-indicator',
+  name: 'libds-tizen-indicator',
+  description: 'tizen indicator extension of libds-tizen for tizen platform',
+)
index 46d807d..09a7f1a 100644 (file)
@@ -33,3 +33,4 @@ subdir('backend')
 subdir('keyrouter')
 subdir('input_devicemgr')
 subdir('dpms')
+subdir('indicator')