From d63e154e2c3427e6d0f1f4509eaddd99638bff38 Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Wed, 20 Jul 2022 16:11:22 +0900 Subject: [PATCH] impelement libds-tizen-clipboard This is the server implementation for tizen_clipboard protocol. Change-Id: Idb03da717fd867bb9fd31e8bf9878e1006553ada --- include/libds-tizen/clipboard.h | 50 ++++++ packaging/libds-tizen.spec | 29 ++++ src/clipboard/clipboard.c | 366 ++++++++++++++++++++++++++++++++++++++++ src/clipboard/meson.build | 29 ++++ src/meson.build | 1 + 5 files changed, 475 insertions(+) create mode 100644 include/libds-tizen/clipboard.h create mode 100644 src/clipboard/clipboard.c create mode 100644 src/clipboard/meson.build diff --git a/include/libds-tizen/clipboard.h b/include/libds-tizen/clipboard.h new file mode 100644 index 0000000..697c9e7 --- /dev/null +++ b/include/libds-tizen/clipboard.h @@ -0,0 +1,50 @@ +#ifndef LIBDS_TIZEN_CLIPBOARD_H +#define LIBDS_TIZEN_CLIPBOARD_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct ds_tizen_clipboard; +struct ds_tizen_clipboard_client; + +struct ds_tizen_clipboard * +ds_tizen_clipboard_create(struct wl_display *display); + +void +ds_tizen_clipboard_add_destroy_listener(struct ds_tizen_clipboard *clipboard, + struct wl_listener *listener); + +void +ds_tizen_clipboard_add_show_listener( + struct ds_tizen_clipboard *clipboard, struct wl_listener *listener); + +void +ds_tizen_clipboard_add_hide_listener( + struct ds_tizen_clipboard *clipboard, struct wl_listener *listener); + +void +ds_tizen_clipboard_add_set_data_only_listener( + struct ds_tizen_clipboard *clipboard, struct wl_listener *listener); + +uint32_t +ds_tizen_clipboard_client_get_data_only( + struct ds_tizen_clipboard_client *client); + +void +ds_tizen_clipboard_send_data_selected(struct ds_tizen_clipboard *clipboard, + struct ds_surface *surface); + +void +ds_tizen_clipboard_client_send_allowed_data_only( + struct ds_tizen_clipboard_client *client, uint32_t allowed); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/packaging/libds-tizen.spec b/packaging/libds-tizen.spec index 8935d5d..bb5c681 100644 --- a/packaging/libds-tizen.spec +++ b/packaging/libds-tizen.spec @@ -137,6 +137,21 @@ Group: Development/Libraries %description indicator-devel Development package for tizen indicator +## libds-tizen-clipboard +%package clipboard +Summary: Library for tizen clipboard +Group: Development/Libraries + +%description clipboard +Library for tizen clipboard + +%package clipboard-devel +Summary: Development package for tizen clipboard +Group: Development/Libraries + +%description clipboard-devel +Development package for tizen clipboard + %prep %setup -q cp %{SOURCE1001} . @@ -262,3 +277,17 @@ ninja -C builddir install %{_libdir}/pkgconfig/libds-tizen-indicator.pc %{_libdir}/libds-tizen-indicator.so %{_bindir}/libds-tizen-indicator-tests + +%files clipboard +%manifest %{name}.manifest +%defattr(-,root,root,-) +%license LICENSE +%{_libdir}/libds-tizen-clipboard.so.* + +%files clipboard-devel +%manifest %{name}.manifest +%defattr(-,root,root,-) +%license LICENSE +%{_includedir}/libds-tizen/clipboard.h +%{_libdir}/pkgconfig/libds-tizen-clipboard.pc +%{_libdir}/libds-tizen-clipboard.so diff --git a/src/clipboard/clipboard.c b/src/clipboard/clipboard.c new file mode 100644 index 0000000..bfa9595 --- /dev/null +++ b/src/clipboard/clipboard.c @@ -0,0 +1,366 @@ +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "libds-tizen/clipboard.h" + +#define TIZEN_CLIPBOARD_VERSION 2 + +struct ds_tizen_clipboard +{ + struct wl_global *global; + + struct wl_list clients; + + struct wl_listener destroy; + + struct { + struct wl_signal destroy; + struct wl_signal show; + struct wl_signal hide; + struct wl_signal set_data_only; + } events; +}; + +struct ds_tizen_clipboard_client +{ + struct ds_tizen_clipboard *clipboard; + + struct wl_resource *resource; + struct wl_client *wl_client; + + struct wl_list infos; + + uint32_t data_only; + + struct wl_list link; // ds_tizen_clipboard::clients +}; + +struct ds_tizen_clipboard_info +{ + struct ds_surface *surface; + + struct wl_list link; // ds_tizen_clipboard_client::infos +}; + +static void clipboard_handle_display_destroy(struct wl_listener *listener, + void *data); + +static void clipboard_bind(struct wl_client *wl_client, void *data, + uint32_t version, uint32_t id); + +static struct ds_tizen_clipboard_client *tizen_clipboard_find_client( + struct ds_tizen_clipboard *clipboard, + struct ds_surface *surface); + +static struct ds_tizen_clipboard_info *tizen_clipboard_client_find_info( + struct ds_tizen_clipboard_client *client, + struct ds_surface *surface); + +static struct ds_tizen_clipboard_info *tizen_clipboard_client_get_info( + struct ds_tizen_clipboard_client *client, + struct ds_surface *surface); + +WL_EXPORT struct ds_tizen_clipboard * +ds_tizen_clipboard_create(struct wl_display *display) +{ + struct ds_tizen_clipboard *clipboard; + + clipboard = calloc(1, sizeof *clipboard); + if (!clipboard) { + ds_err("calloc() failed."); + return NULL; + } + + clipboard->global = wl_global_create(display, &tizen_clipboard_interface, + TIZEN_CLIPBOARD_VERSION, clipboard, clipboard_bind); + if (!clipboard->global) { + ds_err("wl_global_create() failed. tizen_clipboard_interface"); + free(clipboard); + return NULL; + } + + wl_list_init(&clipboard->clients); + + clipboard->destroy.notify = clipboard_handle_display_destroy; + wl_display_add_destroy_listener(display, &clipboard->destroy); + + wl_signal_init(&clipboard->events.destroy); + wl_signal_init(&clipboard->events.show); + wl_signal_init(&clipboard->events.hide); + wl_signal_init(&clipboard->events.set_data_only); + + ds_inf("Global created: tizen_clipboard(%p)", clipboard); + + return clipboard; +} + +WL_EXPORT void +ds_tizen_clipboard_add_destroy_listener(struct ds_tizen_clipboard *clipboard, + struct wl_listener *listener) +{ + wl_signal_add(&clipboard->events.destroy, listener); +} + +WL_EXPORT void +ds_tizen_clipboard_add_show_listener( + struct ds_tizen_clipboard *clipboard, struct wl_listener *listener) +{ + wl_signal_add(&clipboard->events.show, listener); +} + +WL_EXPORT void +ds_tizen_clipboard_add_hide_listener( + struct ds_tizen_clipboard *clipboard, struct wl_listener *listener) +{ + wl_signal_add(&clipboard->events.hide, listener); +} + +WL_EXPORT void +ds_tizen_clipboard_add_set_data_only_listener( + struct ds_tizen_clipboard *clipboard, struct wl_listener *listener) +{ + wl_signal_add(&clipboard->events.set_data_only, listener); +} + +WL_EXPORT uint32_t +ds_tizen_clipboard_client_get_data_only( + struct ds_tizen_clipboard_client *client) +{ + return client->data_only; +} + +WL_EXPORT void +ds_tizen_clipboard_send_data_selected(struct ds_tizen_clipboard *clipboard, + struct ds_surface *surface) +{ + struct ds_tizen_clipboard_client *client; + + client = tizen_clipboard_find_client(clipboard, surface); + if (client == NULL) { + ds_err("tizen_clipboard: tizen_clipboard_find_client() failed."); + return; + } + + tizen_clipboard_send_data_selected(client->resource, + ds_surface_get_wl_resource(surface)); +} + +WL_EXPORT void +ds_tizen_clipboard_client_send_allowed_data_only( + struct ds_tizen_clipboard_client *client, uint32_t allowed) +{ + tizen_clipboard_send_allowed_data_only(client->resource, allowed); +} + +static struct ds_tizen_clipboard_client * +tizen_clipboard_find_client(struct ds_tizen_clipboard *clipboard, + struct ds_surface *surface) +{ + struct ds_tizen_clipboard_info *info; + struct ds_tizen_clipboard_client *client; + + wl_list_for_each(client, &clipboard->clients, link) { + info = tizen_clipboard_client_find_info(client, surface); + if (info != NULL) + return client; + } + + return NULL; +} + +static struct ds_tizen_clipboard_info * +tizen_clipboard_client_find_info(struct ds_tizen_clipboard_client *client, + struct ds_surface *surface) +{ + struct ds_tizen_clipboard_info *info; + + wl_list_for_each(info, &client->infos, link) { + if (surface == info->surface) + return info; + } + + return NULL; +} + +static struct ds_tizen_clipboard_info * +tizen_clipboard_client_get_info(struct ds_tizen_clipboard_client *client, + struct ds_surface *surface) +{ + struct ds_tizen_clipboard_info *info; + + info = tizen_clipboard_client_find_info(client, surface); + if (info) + return info; + + info = calloc(1, sizeof *info); + if (info == NULL) { + ds_err("calloc() failed. tizen_clipboard"); + return NULL; + } + + info->surface = surface; + + wl_list_insert(&client->infos, &info->link); + + return info; +} + +static void +clipboard_handle_display_destroy(struct wl_listener *listener, void *data) +{ + struct ds_tizen_clipboard *clipboard; + + clipboard = wl_container_of(listener, clipboard, destroy); + + ds_inf("Global destroy: clipboard(%p)", clipboard); + + wl_signal_emit(&clipboard->events.destroy, clipboard); + wl_list_remove(&clipboard->destroy.link); + wl_global_destroy(clipboard->global); + free(clipboard); +} + +static void +clipboard_handle_destroy(struct wl_client *wl_client, + struct wl_resource *resource) +{ + struct ds_tizen_clipboard_client *client; + + client = wl_resource_get_user_data(resource); + + if (!wl_list_empty(&client->infos)) { + ds_err("tizen_clipboard was destroyed before children"); + return; + } + + wl_resource_destroy(resource); +} + +static void +clipboard_handle_show(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource) +{ + struct ds_tizen_clipboard_client *client; + struct ds_tizen_clipboard_info *info; + struct ds_surface *surface; + + ds_inf("tizen_clipboard: show"); + + client = wl_resource_get_user_data(resource); + surface = ds_surface_from_resource(surface_resource); + + info = tizen_clipboard_client_get_info(client, surface); + if (info == NULL) { + ds_err("tizen_clipboard_client_get_info() failed. tizen_clipboard"); + wl_client_post_no_memory(wl_client); + return; + } + + wl_signal_emit(&client->clipboard->events.show, surface); +} + +static void +clipboard_handle_hide(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *surface_resource) +{ + struct ds_tizen_clipboard_client *client; + struct ds_tizen_clipboard_info *info; + struct ds_surface *surface; + + ds_inf("tizen_clipboard: hide"); + + client = wl_resource_get_user_data(resource); + surface = ds_surface_from_resource(surface_resource); + + info = tizen_clipboard_client_get_info(client, surface); + if (info == NULL) { + ds_err("tizen_clipboard_client_get_info() failed. tizen_clipboard"); + wl_client_post_no_memory(wl_client); + return; + } + + wl_signal_emit(&client->clipboard->events.hide, surface); +} + +static void +clipboard_handle_set_data_only(struct wl_client *wl_client, + struct wl_resource *resource, uint32_t set) +{ + struct ds_tizen_clipboard_client *client; + + ds_inf("tizen_clipboard: set_data_only. set(%d)", set); + + client = wl_resource_get_user_data(resource); + client->data_only = set; + + wl_signal_emit(&client->clipboard->events.set_data_only, client); +} + +static const struct tizen_clipboard_interface clipboard_impl = +{ + clipboard_handle_destroy, + clipboard_handle_show, + clipboard_handle_hide, + clipboard_handle_set_data_only, +}; + +static void +_tizen_clipboard_client_handle_destroy(struct wl_resource *resource) +{ + struct ds_tizen_clipboard_client *client; + struct ds_tizen_clipboard_info *info, *tmp; + + client = wl_resource_get_user_data(resource); + + ds_inf("_tizen_clipboard_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 +clipboard_bind(struct wl_client *wl_client, void *data, uint32_t version, + uint32_t id) +{ + struct ds_tizen_clipboard *clipboard = data; + struct ds_tizen_clipboard_client *client; + + client = calloc(1, sizeof *client); + if (client == NULL) { + ds_err("calloc() failed. tizen_clipboard"); + wl_client_post_no_memory(wl_client); + return; + } + + ds_inf("tizen_clipboard_client binds. (client:%p)", client); + + client->clipboard = clipboard; + client->wl_client = wl_client; + + wl_list_init(&client->infos); + + client->resource = wl_resource_create(wl_client, &tizen_clipboard_interface, + MIN(version, TIZEN_CLIPBOARD_VERSION), id); + + if (client->resource == NULL) { + ds_err("tizen_clipboard : wl_resource_create() failed."); + free(client); + wl_client_post_no_memory(wl_client); + return; + } + + wl_resource_set_implementation(client->resource, &clipboard_impl, client, + _tizen_clipboard_client_handle_destroy); + + wl_list_insert(&clipboard->clients, &client->link); +} diff --git a/src/clipboard/meson.build b/src/clipboard/meson.build new file mode 100644 index 0000000..2889c22 --- /dev/null +++ b/src/clipboard/meson.build @@ -0,0 +1,29 @@ +libds_tizen_clipboard_files = [ + 'clipboard.c', +] + +libds_tizen_clipboard_deps = [ + deps_libds_tizen, + dependency('tizen-extension-server', required: true), +] + +lib_libds_tizen_clipboard = shared_library('ds-tizen-clipboard', libds_tizen_clipboard_files, + dependencies: libds_tizen_clipboard_deps, + include_directories: [ common_inc, include_directories('.'), include_directories('..') ], + version: meson.project_version(), + install: true +) + +deps_libds_tizen_clipboard = declare_dependency( + link_with: lib_libds_tizen_clipboard, + dependencies: libds_tizen_clipboard_deps, + include_directories: [ common_inc, include_directories('.') ], +) + +pkgconfig = import('pkgconfig') +pkgconfig.generate(lib_libds_tizen_clipboard, + version: meson.project_version(), + filebase: 'libds-tizen-clipboard', + name: 'libds-tizen-clipboard', + description: 'tizen clipboard extension of libds-tizen for tizen platform', +) diff --git a/src/meson.build b/src/meson.build index 09a7f1a..73c169c 100644 --- a/src/meson.build +++ b/src/meson.build @@ -34,3 +34,4 @@ subdir('keyrouter') subdir('input_devicemgr') subdir('dpms') subdir('indicator') +subdir('clipboard') -- 2.7.4