From: Seunghun Lee Date: Tue, 10 May 2022 08:59:00 +0000 (+0900) Subject: Use libds for wayland compositor X-Git-Tag: submit/tizen/20220818.083245~19 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4e2b7f0c4e3235219e13aee521ecb919d392aaf3;p=platform%2Fcore%2Fuifw%2Fheadless-server.git Use libds for wayland compositor This is an attempt to use libds library instead of pepper for building headless wayland compositor. Change-Id: If04a01b275af1e6ed42718f73cf1b93da1c15990 --- diff --git a/configure.ac b/configure.ac index d8f71d8..3eb5cfc 100644 --- a/configure.ac +++ b/configure.ac @@ -29,7 +29,7 @@ fi AC_SUBST(GCC_CFLAGS) # headless server -HEADLESS_SERVER_REQUIRES="pepper pepper-inotify pepper-keyrouter pepper-devicemgr pepper-xkb pepper-evdev xkbcommon capi-system-peripheral-io xdg-shell-unstable-v6-server tizen-extension-server wayland-tbm-server" +HEADLESS_SERVER_REQUIRES="xkbcommon capi-system-peripheral-io xdg-shell-unstable-v6-server tizen-extension-server wayland-tbm-server dlog wayland-server libds libds-tizen" PKG_CHECK_MODULES(HEADLESS_SERVER, $[HEADLESS_SERVER_REQUIRES]) AC_SUBST(HEADLESS_SERVER_CFLAGS) diff --git a/packaging/headless-server.spec b/packaging/headless-server.spec index 89cf51d..f4e789c 100644 --- a/packaging/headless-server.spec +++ b/packaging/headless-server.spec @@ -11,12 +11,6 @@ source1001: %name.manifest BuildRequires: autoconf > 2.64 BuildRequires: automake >= 1.11 BuildRequires: libtool >= 2.2 -BuildRequires: pkgconfig(pepper) -BuildRequires: pkgconfig(pepper-inotify) -BuildRequires: pkgconfig(pepper-keyrouter) -BuildRequires: pkgconfig(pepper-xkb) -BuildRequires: pkgconfig(pepper-devicemgr) -BuildRequires: pkgconfig(pepper-evdev) BuildRequires: pkgconfig(xkbcommon) BuildRequires: pkgconfig(wayland-tbm-server) BuildRequires: pkgconfig(tizen-extension-server) @@ -24,11 +18,13 @@ BuildRequires: pkgconfig(capi-system-peripheral-io) BuildRequires: pkgconfig(xdg-shell-unstable-v6-server) BuildRequires: pkgconfig(tizen-extension-server) -Requires: pepper pepper-keyrouter pepper-devicemgr pepper-evdev -Requires: pepper-xkb xkeyboard-config xkb-tizen-data +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(wayland-server) +BuildRequires: pkgconfig(libds) +BuildRequires: pkgconfig(libds-tizen) + Requires: libtbm Requires: capi-system-peripheral-io -Conflicts: pepper-doctor %description Headless server is a display server for headless profile. diff --git a/src/Makefile.am b/src/Makefile.am index 1cdb324..16c0c56 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -6,8 +6,6 @@ headless_server_CFLAGS = $(HEADLESS_SERVER_CFLAGS) headless_server_LDADD = $(HEADLESS_SERVER_LIBS) headless_server_SOURCES = headless_server.c \ - debug/debug.c \ - input/input.c \ output/output_led.c \ output/HL_UI_LED_APA102.c \ output/boot_anim.c \ diff --git a/src/headless_server.c b/src/headless_server.c index d4e2de5..0404464 100644 --- a/src/headless_server.c +++ b/src/headless_server.c @@ -23,16 +23,74 @@ * SOFTWARE. */ +#include #include #include #include +#include -#include +#include #include +#include +#include +#include +#include + #include +typedef struct headless_server headless_server_t; + +typedef struct headless_view headless_view_t; + +struct headless_server +{ + struct wl_display *display; + struct ds_compositor *compositor; + struct ds_tbm_server *tbm_server; + + led_output_t *output; + headless_shell_t *shell; + + headless_view_t *focus_view; + headless_view_t *top_view; + + struct wl_event_source *sigint_source; + struct wl_event_source *idle_source; + + const char *name; + + struct wl_listener new_shell_surface; + + struct wl_list views; // headless_view::link + + bool boot_animating; +}; + +struct headless_view +{ + headless_server_t *server; + headless_shell_surface_t *shell_surface; + struct ds_surface *surface; + struct ds_buffer *buffer; + + struct wl_listener shell_surface_destroy; + struct wl_listener commit; + struct wl_listener map; + struct wl_listener unmap; + struct wl_listener request_activate; + struct wl_listener set_skip_focus; + struct wl_listener unset_skip_focus; + + struct wl_list link; // headless_server::views + + bool mapped; + bool skip_focus; +}; + int use_output = 1; +static void server_handle_new_shell_surface(struct wl_listener *listener, void *data); + static int handle_sigint(int signal_number, void *data) { @@ -42,36 +100,55 @@ handle_sigint(int signal_number, void *data) return 0; } -static pepper_bool_t -init_signal(pepper_compositor_t *compositor) +static bool +init_signal(struct wl_display *display) { - struct wl_display *display; struct wl_event_loop *loop; struct wl_event_source *sigint; - display = pepper_compositor_get_display(compositor); loop = wl_display_get_event_loop(display); sigint = wl_event_loop_add_signal(loop, SIGINT, handle_sigint, display); if (!sigint) - return PEPPER_FALSE; + return false; + + return true; +} + +static int +dlog_level_from_ds_log_level(enum ds_log_level level) +{ + switch (level) { + case DS_INF: + return DLOG_INFO; + case DS_DBG: + return DLOG_DEBUG; + default: + case DS_ERR: + return DLOG_ERROR; + } +} - return PEPPER_TRUE; +static void +handle_ds_log(enum ds_log_level level, const char *fmt, va_list args) +{ + dlog_vprint(dlog_level_from_ds_log_level(level), "HEADLESS_SERVER", + fmt, args); } int main(int argc, char *argv[]) { + headless_server_t server = { 0, }; const char *socket_name = NULL; - pepper_compositor_t *compositor = NULL; - pepper_bool_t ret; + bool ret; tbm_bufmgr bufmgr = NULL; /* set STDOUT/STDERR bufferless */ setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); - if (getenv("PEPPER_DLOG_ENABLE")) { - PEPPER_TRACE("pepper log will be written to dlog !\n"); - pepper_log_dlog_enable(1); + if (getenv("HEADLESS_SERVER_DLOG_ENABLE")) { + HEADLESS_TRACE("ds log will be written to dlog !\n"); + ds_log_init(DS_INF, handle_ds_log); } socket_name = getenv("WAYLAND_DISPLAY"); @@ -87,54 +164,370 @@ int main(int argc, char *argv[]) use_output = 0; } - /* create pepper compositir */ - compositor = pepper_compositor_create(socket_name, NULL); - PEPPER_CHECK(compositor, return EXIT_FAILURE, "Failed to create compositor !"); + server.display = wl_display_create(); + if (!server.display) { + ds_err("Could not create wl_display"); + return EXIT_FAILURE; + } + wl_list_init(&server.views); + + server.compositor = ds_compositor_create(server.display); + HEADLESS_CHECK(server.compositor, goto end, "Failed to create ds_compositor"); + + server.tbm_server = ds_tbm_server_create(server.display); + HEADLESS_CHECK(server.tbm_server, goto end, "Failed to create ds_tbm_server"); + +#ifndef DISABLE_INPUT /* Init event trace */ ret = headless_debug_init(compositor); - PEPPER_CHECK(ret, goto end, "headless_debug_init() failed\n"); + HEADLESS_CHECK(ret, goto end, "headless_debug_init() failed\n"); /* Init input for headless */ ret = headless_input_init(compositor); - PEPPER_CHECK(ret, goto end, "headless_input_init() failed\n"); + HEADLESS_CHECK(ret, goto end, "headless_input_init() failed\n"); +#endif /* Init Output */ if(use_output) { - ret = headless_output_init(compositor); - PEPPER_CHECK(ret, goto end, "headless_output_init() failed.\n"); + server.output = headless_output_create(server.display); + HEADLESS_CHECK(server.output, goto end, "headless_output_create() failed."); + + headless_output_start_boot_ani(server.output); + server.boot_animating = true; } else { bufmgr = tbm_bufmgr_server_init(); - PEPPER_CHECK(bufmgr, goto end, "Failed to init tbm buffer manager !\n"); - ret = tbm_bufmgr_bind_native_display(bufmgr, (void *)pepper_compositor_get_display(compositor)); - PEPPER_CHECK(ret, goto end, "Failed to bind native display with tbm buffer manager !\n"); + HEADLESS_CHECK(bufmgr, goto end, "Failed to init tbm buffer manager !\n"); + ret = tbm_bufmgr_bind_native_display(bufmgr, (void *)server.display); + HEADLESS_CHECK(ret, goto end, "Failed to bind native display with tbm buffer manager !\n"); } /* Init Shell */ - ret = headless_shell_init(compositor); - PEPPER_CHECK(ret, goto end, "headless_shell_init() failed.\n"); + server.shell = headless_shell_create(server.display); + HEADLESS_CHECK(server.shell, goto end, "headless_shell_create() failed.\n"); + + server.new_shell_surface.notify = server_handle_new_shell_surface; + headless_shell_add_new_surface_listener(server.shell, &server.new_shell_surface); /* Init Signal for SIGINT */ - init_signal(compositor); + init_signal(server.display); + + server.name = wl_display_add_socket_auto(server.display); + HEADLESS_CHECK(server.name, goto end, "Could not add socket for wayland"); + + setenv("WAYLAND_DISPLAY", server.name, true); + + ds_inf("Running headless server on WAYLAND_DISPLAY=%s", server.name); /* run event loop */ - wl_display_run(pepper_compositor_get_display(compositor)); + wl_display_run(server.display); end: /* Deinit Process */ - headless_shell_deinit(compositor); - headless_input_deinit(compositor); - if(use_output) - headless_output_deinit(compositor); + if (server.shell) + headless_shell_destroy(server.shell); + + if(use_output && server.output) + headless_output_destroy(server.output); if (bufmgr) { tbm_bufmgr_deinit(bufmgr); bufmgr = NULL; } + +#ifndef DISABLE_INPUT + headless_input_deinit(compositor); headless_debug_deinit(compositor); - pepper_compositor_destroy(compositor); +#endif + + wl_display_destroy_clients(server.display); + wl_display_destroy(server.display); return EXIT_SUCCESS; } + +static void +server_schedule_idle_task(headless_server_t *server); +static void +server_set_focus_view(headless_server_t *server, headless_view_t *view); +static void +server_set_top_view(headless_server_t *server, headless_view_t *view); + +static void +destroy_view(headless_view_t *view) +{ + ds_inf("view(%p) destroyed", view); + + wl_list_remove(&view->commit.link); + wl_list_remove(&view->map.link); + wl_list_remove(&view->unmap.link); + wl_list_remove(&view->request_activate.link); + wl_list_remove(&view->set_skip_focus.link); + wl_list_remove(&view->unset_skip_focus.link); + wl_list_remove(&view->link); + + free(view); +} + +static void +view_handle_shell_surface_destroy(struct wl_listener *listener, void *data) +{ + headless_view_t *view; + headless_server_t *server; + + view = wl_container_of(listener, view, shell_surface_destroy); + server = view->server; + + if (server->top_view == view) + server_set_top_view(server, NULL); + + if (server->focus_view == view) + server_set_focus_view(server, NULL); + + server_schedule_idle_task(server); + + destroy_view(view); +} + +static void +view_handle_surface_commit(struct wl_listener *listener, void *data) +{ + headless_view_t *view; + + view = wl_container_of(listener, view, commit); + view->buffer = ds_surface_get_buffer(view->surface); + + server_schedule_idle_task(view->server); +} + +static void +view_handle_shell_surface_map(struct wl_listener *listener, void *data) +{ + headless_view_t *view; + + view = wl_container_of(listener, view, map); + view->mapped = true; + + server_schedule_idle_task(view->server); +} + +static void +view_handle_shell_surface_unmap(struct wl_listener *listener, void *data) +{ + headless_view_t *view; + + view = wl_container_of(listener, view, unmap); + view->mapped = false; + + server_schedule_idle_task(view->server); +} + +static void +view_handle_request_activate(struct wl_listener *listener, void *data) +{ + headless_view_t *view; + + view = wl_container_of(listener, view, request_activate); + + wl_list_remove(&view->link); + wl_list_insert(&view->server->views, &view->link); + + server_schedule_idle_task(view->server); +} + +static void +view_handle_shell_surface_set_skip_focus(struct wl_listener *listener, + void *data) +{ + headless_view_t *view; + + view = wl_container_of(listener, view, set_skip_focus); + view->skip_focus = true; + + server_schedule_idle_task(view->server); +} + +static void +view_handle_shell_surface_unset_skip_focus(struct wl_listener *listener, + void *data) +{ + headless_view_t *view; + + view = wl_container_of(listener, view, unset_skip_focus); + view->skip_focus = false; + + server_schedule_idle_task(view->server); +} + +static bool +create_view(headless_server_t *server, headless_shell_surface_t *shell_surface) +{ + headless_view_t *view; + + view = calloc(1, sizeof *view); + if (!view) + return false; + + view->server = server; + view->shell_surface = shell_surface; + view->surface = headless_shell_surface_get_surface(shell_surface); + + view->shell_surface_destroy.notify = view_handle_shell_surface_destroy; + headless_shell_surface_add_destroy_listener(shell_surface, + &view->shell_surface_destroy); + + view->commit.notify = view_handle_surface_commit; + ds_surface_add_commit_listener(view->surface, &view->commit); + + view->map.notify = view_handle_shell_surface_map; + headless_shell_surface_add_map_listener(shell_surface, &view->map); + + view->unmap.notify = view_handle_shell_surface_unmap; + headless_shell_surface_add_unmap_listener(shell_surface, &view->unmap); + + view->request_activate.notify = view_handle_request_activate; + headless_shell_surface_add_request_activate_listener(shell_surface, + &view->request_activate); + + view->set_skip_focus.notify = view_handle_shell_surface_set_skip_focus; + headless_shell_surface_add_set_skip_focus_listener(shell_surface, + &view->set_skip_focus); + + view->unset_skip_focus.notify = view_handle_shell_surface_unset_skip_focus; + headless_shell_surface_add_unset_skip_focus_listener(shell_surface, + &view->unset_skip_focus); + + wl_list_insert(&server->views, &view->link); + + ds_inf("Create view(%p)", view); + + return true; +} + +static void +server_handle_new_shell_surface(struct wl_listener *listener, void *data) +{ + headless_server_t *server; + headless_shell_surface_t *shell_surface = data; + + server = wl_container_of(listener, server, new_shell_surface); + + ds_inf("shell surface added, server(%p)", server); + + if (server->boot_animating) { + server->boot_animating = false; + headless_output_stop_boot_ani(server->output); + } + + HEADLESS_CHECK(create_view(server, shell_surface), return, + "Could not create headless_view"); +} + +static void +server_set_focus_view(headless_server_t *server, headless_view_t *view) +{ + if (server->focus_view == view) + return; + + server->focus_view = view; + + // TODO handle input and debug +} + +static void +server_set_top_view(headless_server_t *server, headless_view_t *view) +{ + if (server->top_view == view) + return; + + // TODO handle input and debug + + if (server->top_view) { + headless_shell_send_visibility(server->top_view->shell_surface, + TIZEN_VISIBILITY_VISIBILITY_FULLY_OBSCURED); + } + + if (view) { + headless_shell_send_visibility(view->shell_surface, + TIZEN_VISIBILITY_VISIBILITY_UNOBSCURED); + } + + server->top_view = view; +} + +static void +server_repaint(headless_server_t *server) +{ + struct ds_surface *surface = NULL; + struct ds_buffer *buffer = NULL; + struct timespec now; + void *data = NULL; + uint32_t format; + size_t stride; + bool access = false; + + if (server->top_view) { + surface = server->top_view->surface; + buffer = server->top_view->buffer; + } + + if (buffer) { + access = ds_buffer_begin_data_ptr_access(buffer, + DS_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride); + if (!access) + ds_err("Could not access ds_buffer(%p)", buffer); + } + + headless_output_update_led(server->output, data); + + if (access) + ds_buffer_end_data_ptr_access(buffer); + + if (surface) { + clock_gettime(CLOCK_MONOTONIC, &now); + ds_surface_send_frame_done(surface, &now); + } +} + +static void +idle_task(void *data) +{ + headless_server_t *server = data; + headless_view_t *view, *focus_view = NULL, *top_view = NULL; + + server->idle_source = NULL; + + /* This iterates over all our views and attemps to find focusable and + * visible views on the top. This relies on server->views being ordered + * from top-to-bottom. */ + wl_list_for_each(view, &server->views, link) { + if (!view->mapped) + continue; + + if (!top_view) + top_view = view; + + if (!focus_view && !view->skip_focus) + focus_view = view; + + if (focus_view && top_view) + break; + } + + server_set_focus_view(server, focus_view); + server_set_top_view(server, top_view); + server_repaint(server); +} + +static void +server_schedule_idle_task(headless_server_t *server) +{ + if (server->idle_source) + return; + + server->idle_source = + wl_event_loop_add_idle(wl_display_get_event_loop(server->display), + idle_task, server); +} diff --git a/src/headless_server.h b/src/headless_server.h index d176e6e..32cb8cc 100644 --- a/src/headless_server.h +++ b/src/headless_server.h @@ -24,33 +24,88 @@ #ifndef HEADLESS_SERVER_H #define HEADLESS_SERVER_H -#include - #ifdef __cplusplus extern "C" { #endif +#define DISABLE_INPUT + +#include + +#include +#include +#include + +#define HEADLESS_ERROR(fmt, ...) \ + do { \ + ds_err("%s[%s]: " fmt, __FILE__, __FUNCTION__, ##__VA_ARGS__); \ + } while (0) + +#define HEADLESS_TRACE(fmt, ...) \ + do { \ + ds_dbg("TRACE: %s[%s]: " fmt, \ + __FILE__, __FUNCTION__, ##__VA_ARGS__); \ + } while (0) + +#define HEADLESS_CHECK(exp, action, fmt, ...) \ + do { \ + if (!(exp)) \ + { \ + HEADLESS_ERROR(fmt, ##__VA_ARGS__); \ + action; \ + } \ + } while (0) + +typedef struct led_output led_output_t; + +typedef struct HEADLESS_SHELL headless_shell_t; + +typedef struct HEADLESS_SHELL_SURFACE headless_shell_surface_t; + /* APIs for headless_output */ -PEPPER_API pepper_bool_t headless_output_init(pepper_compositor_t *compositor); -PEPPER_API void headless_output_deinit(pepper_compositor_t *compositor); +led_output_t *headless_output_create(struct wl_display *display); +void headless_output_destroy(led_output_t *output); +void headless_output_start_boot_ani(led_output_t *output); +void headless_output_stop_boot_ani(led_output_t *output); +void headless_output_update_led(led_output_t *output, unsigned char *data); /* APIs for headless_shell */ -PEPPER_API pepper_bool_t headless_shell_init(pepper_compositor_t *compositor); -PEPPER_API void headless_shell_deinit(pepper_compositor_t *compositor); +headless_shell_t *headless_shell_create(struct wl_display *display); +void headless_shell_destroy(headless_shell_t *shell); +void headless_shell_add_new_surface_listener(headless_shell_t *shell, + struct wl_listener *listener); +void headless_shell_surface_add_destroy_listener( + headless_shell_surface_t *shell_surface, struct wl_listener *listener); +void headless_shell_surface_add_map_listener( + headless_shell_surface_t *shell_surface, struct wl_listener *listener); +void headless_shell_surface_add_unmap_listener( + headless_shell_surface_t *shell_surface, struct wl_listener *listener); +void headless_shell_surface_add_request_activate_listener( + headless_shell_surface_t *shell_surface, struct wl_listener *listener); +void headless_shell_surface_add_set_skip_focus_listener( + headless_shell_surface_t *shell_surface, struct wl_listener *listener); +void headless_shell_surface_add_unset_skip_focus_listener( + headless_shell_surface_t *hs_surface, struct wl_listener *listener); +struct ds_surface * +headless_shell_surface_get_surface(headless_shell_surface_t *shell_surface); +void headless_shell_send_visibility(headless_shell_surface_t *hs_surface, + uint8_t visibility); +#ifndef DISABLE_INPUT /* APIs for headless_input */ -PEPPER_API pepper_bool_t headless_input_init(pepper_compositor_t *compositor); -PEPPER_API void headless_input_deinit(pepper_compositor_t *compositor); -PEPPER_API void headless_input_set_focus_view(pepper_compositor_t *compositor, pepper_view_t *view); -PEPPER_API void headless_input_set_top_view(pepper_compositor_t *compositor, pepper_view_t *view); -PEPPER_API void *headless_input_get_keyrouter(pepper_compositor_t *compositor); -PEPPER_API void *headless_input_get_xkb(pepper_compositor_t *compositor); +pepper_bool_t headless_input_init(pepper_compositor_t *compositor); +void headless_input_deinit(pepper_compositor_t *compositor); +void headless_input_set_focus_view(pepper_compositor_t *compositor, pepper_view_t *view); +void headless_input_set_top_view(pepper_compositor_t *compositor, pepper_view_t *view); +void *headless_input_get_keyrouter(pepper_compositor_t *compositor); +void *headless_input_get_xkb(pepper_compositor_t *compositor); /* APIs for headless_debug */ -PEPPER_API pepper_bool_t headless_debug_init(pepper_compositor_t *compositor); -PEPPER_API void headless_debug_deinit(pepper_compositor_t *compositor); -PEPPER_API void headless_debug_set_focus_view(pepper_compositor_t *compositor, pepper_view_t *view); -PEPPER_API void headless_debug_set_top_view(pepper_compositor_t *compositor, pepper_view_t *view); +pepper_bool_t headless_debug_init(pepper_compositor_t *compositor); +void headless_debug_deinit(pepper_compositor_t *compositor); +void headless_debug_set_focus_view(pepper_compositor_t *compositor, pepper_view_t *view); +void headless_debug_set_top_view(pepper_compositor_t *compositor, pepper_view_t *view); +#endif #ifdef __cplusplus } diff --git a/src/output/boot_anim.c b/src/output/boot_anim.c index e6c15a5..c1e45c5 100644 --- a/src/output/boot_anim.c +++ b/src/output/boot_anim.c @@ -26,9 +26,8 @@ #include #include -#include -#include -#include +#include +#include "headless_server.h" #include "HL_UI_LED.h" #include "output_internal.h" @@ -38,8 +37,6 @@ typedef struct { struct wl_event_source *source; uint32_t serial; int index; - - pepper_event_listener_t *surface_add_listener; } boot_ani_t; #define ANI_INTERVAL 40 //20ms @@ -71,39 +68,25 @@ boot_ani_timer_cb(void *data) return 1; } -static void -boot_ani_surface_add_cb(pepper_event_listener_t *listener, - pepper_object_t *object, - uint32_t id, void *info, void *data) -{ - led_output_t *output = (led_output_t *)data; - - boot_ani_stop(output); -} - void boot_ani_start(led_output_t *output) { struct wl_event_loop *loop; boot_ani_t *ani; int ret; - PEPPER_TRACE("[OUTPUT] start boot-animation\n"); + HEADLESS_TRACE("[OUTPUT] start boot-animation\n"); - loop = wl_display_get_event_loop(pepper_compositor_get_display(output->compositor)); - PEPPER_CHECK(loop, return, "failed to wl_display_get_event_loop()\n"); + loop = wl_display_get_event_loop(output->display); + HEADLESS_CHECK(loop, return, "failed to wl_display_get_event_loop()\n"); ani = (boot_ani_t *)calloc(sizeof(boot_ani_t), 1); - PEPPER_CHECK(ani, return, "failed to alloc\n"); + HEADLESS_CHECK(ani, return, "failed to alloc\n"); ani->source = wl_event_loop_add_timer(loop, boot_ani_timer_cb, ani); - PEPPER_CHECK(ani->source, goto err, "failed to wl_event_loop_add_timer()\n"); + HEADLESS_CHECK(ani->source, goto err, "failed to wl_event_loop_add_timer()\n"); ret = wl_event_source_timer_update(ani->source, ANI_INTERVAL); - PEPPER_CHECK(!ret, goto err, "failed to wl_event_source_timer_update\n"); - - ani->surface_add_listener = pepper_object_add_event_listener((pepper_object_t *)output->compositor, - PEPPER_EVENT_COMPOSITOR_SURFACE_ADD, - 0, boot_ani_surface_add_cb, output); + HEADLESS_CHECK(!ret, goto err, "failed to wl_event_source_timer_update\n"); ani->led = output->ui_led; output->boot_ani = ani; @@ -129,11 +112,6 @@ void boot_ani_stop(led_output_t *output) HL_UI_LED_Clear_All(ani->led); wl_event_source_remove(ani->source); - if(ani->surface_add_listener) { - pepper_event_listener_remove(ani->surface_add_listener); - ani->surface_add_listener = NULL; - } - free(ani); output->boot_ani = NULL; diff --git a/src/output/output_internal.h b/src/output/output_internal.h index 2bfa286..78a1da8 100644 --- a/src/output/output_internal.h +++ b/src/output/output_internal.h @@ -26,26 +26,24 @@ #include #include -#include +#include "HL_UI_LED.h" #define NUM_LED 12 -typedef struct { - pepper_compositor_t *compositor; - pepper_output_t *output; - pepper_plane_t *plane; +typedef struct led_output led_output_t; + +struct led_output { + struct wl_display *display; + struct ds_tbm_server *tbm_server; int num_led; HL_UI_LED *ui_led; - struct wayland_tbm_server *tbm_server; struct wl_event_source *frame_done; - pepper_view_t *top_view; - //For booting animation void *boot_ani; -}led_output_t; +}; -PEPPER_API void boot_ani_start(led_output_t *output); -PEPPER_API void boot_ani_stop(led_output_t *output); +void boot_ani_start(led_output_t *output); +void boot_ani_stop(led_output_t *output); diff --git a/src/output/output_led.c b/src/output/output_led.c index 24931d1..81369df 100644 --- a/src/output/output_led.c +++ b/src/output/output_led.c @@ -21,177 +21,69 @@ * DEALINGS IN THE SOFTWARE. */ +#include #include #include #include #include -#include -#include -#include +#include "headless_server.h" #include "HL_UI_LED.h" #include "output_internal.h" -static const int KEY_OUTPUT; -static void led_output_add_frame_done(led_output_t *output); -static void led_output_update(led_output_t *output); - -static void -led_output_destroy(void *data) +led_output_t * +headless_output_create(struct wl_display *display) { - led_output_t *output = (led_output_t *)data; - PEPPER_TRACE("Output Destroy %p base %p\n", output, output->output); + led_output_t *output = (led_output_t*)calloc(sizeof(led_output_t), 1); - if (output->ui_led) { - HL_UI_LED_Close(output->ui_led); - output->ui_led = NULL; - } + HEADLESS_TRACE("Output Init\n"); - if (output->tbm_server) { - wayland_tbm_server_deinit(output->tbm_server); - output->tbm_server = NULL; + if (!output) { + HEADLESS_ERROR("Failed to allocate memory in %s\n", __FUNCTION__); + return false; } -} - -static int32_t -led_output_get_subpixel_order(void *o) -{ - return 0; -} - -static const char * -led_output_get_maker_name(void *o) -{ - return "PePPer LED"; -} - -static const char * -led_output_get_model_name(void *o) -{ - return "PePPer LED"; -} - -static int -led_output_get_mode_count(void *o) -{ - return 1; -} -static void -led_output_get_mode(void *o, int index, pepper_output_mode_t *mode) -{ - led_output_t *output = (led_output_t *)o; + output->display = display; - PEPPER_TRACE("[OUTPUT]\n"); + // FIXME Should we create wl_global for wl_output? - if (index != 0) - return; + output->num_led = NUM_LED; + output->ui_led = HL_UI_LED_Init(output->num_led); + if (output->ui_led) HL_UI_LED_Change_Brightness(output->ui_led, 0x1); - mode->flags = WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED; - mode->w = output->num_led; - mode->h = output->num_led; - mode->refresh = 60000; -} + if (!output->ui_led) + HEADLESS_ERROR("HL_UI_LED_Init() failed.\n"); -static pepper_bool_t -led_output_set_mode(void *o, const pepper_output_mode_t *mode) -{ - return PEPPER_FALSE; + return output; } -static void -led_output_assign_planes(void *o, const pepper_list_t *view_list) +void +headless_output_destroy(led_output_t *output) { - led_output_t *output = (led_output_t *)o; - pepper_list_t *l; - pepper_view_t *view, *top_view = NULL; - - PEPPER_TRACE("[OUTPUT] Assign plane\n"); - pepper_list_for_each_list(l, view_list) { - view = (pepper_view_t*)l->item; + HEADLESS_TRACE("Output Destroy %p", output); - if (pepper_view_is_mapped(view) && pepper_view_is_visible(view)) { - top_view = view; - break; - } + if (output->boot_ani) { + boot_ani_stop(output); } - if (output->top_view != top_view) - PEPPER_TRACE("\tTop-View is changed(%p -> %p)\n", output->top_view, top_view); - - output->top_view = top_view; -} - -static void -led_output_start_repaint_loop(void *o) -{ - led_output_t *output = (led_output_t *)o; - struct timespec ts; - - PEPPER_TRACE("[OUTPUT] Start reapint loop\n"); - pepper_compositor_get_time(output->compositor, &ts); - pepper_output_finish_frame(output->output, &ts); -} - -static void -led_output_repaint(void *o, const pepper_list_t *plane_list) -{ - pepper_list_t *l; - pepper_plane_t *plane; - led_output_t *output = (led_output_t *)o; - - PEPPER_TRACE("[OUTPUT] Repaint\n"); - - pepper_list_for_each_list(l, plane_list) { - plane = (pepper_plane_t *)l->item; - pepper_plane_clear_damage_region(plane); + if (output->ui_led) { + HL_UI_LED_Close(output->ui_led); + output->ui_led = NULL; } - led_output_update(output); - led_output_add_frame_done(output); -} + free(output); -static void -led_output_attach_surface(void *o, pepper_surface_t *surface, int *w, int *h) -{ - *w = 10; - *h = 10; - PEPPER_TRACE("[OUTPUT] attach surface:%p\n", surface); + HEADLESS_TRACE("Output Destroy... DONE\n"); } -static void -led_output_flush_surface_damage(void *o, pepper_surface_t *surface, pepper_bool_t *keep_buffer) -{ - *keep_buffer = PEPPER_TRUE; - PEPPER_TRACE("[OUTPUT] flush_surface_damage surface:%p\n", surface); -} - -struct pepper_output_backend led_output_backend = { - led_output_destroy, - - led_output_get_subpixel_order, - led_output_get_maker_name, - led_output_get_model_name, - - led_output_get_mode_count, - led_output_get_mode, - led_output_set_mode, - - led_output_assign_planes, - led_output_start_repaint_loop, - led_output_repaint, - led_output_attach_surface, - led_output_flush_surface_damage, -}; - -static void -led_output_update_led(led_output_t *output, unsigned char *data) +void +headless_output_update_led(led_output_t *output, unsigned char *data) { int i; uint8_t *ptr = (uint8_t *)data; if (data == NULL) { - PEPPER_TRACE("[OUTPUT] update LED to empty\n"); + HEADLESS_TRACE("[OUTPUT] update LED to empty\n"); HL_UI_LED_Clear_All(output->ui_led); return; } @@ -204,171 +96,20 @@ led_output_update_led(led_output_t *output, unsigned char *data) HL_UI_LED_Refresh(output->ui_led); } -static void -led_output_update(led_output_t *output) -{ - pepper_buffer_t *buf; - pepper_surface_t *surface; - struct wl_resource *buf_res; - tbm_surface_h tbm_surface; - tbm_surface_info_s info; - int ret; - - if (!output->top_view) { - if (!output->ui_led) - PEPPER_TRACE("[UPDATE LED] Empty Display\n"); - else - led_output_update_led(output, NULL); - - return; - } - - surface = pepper_view_get_surface(output->top_view); - PEPPER_CHECK(surface, return, "fail to get a surafce from a view(%p)\n", output->top_view); - - buf = pepper_surface_get_buffer(surface); - PEPPER_CHECK(buf, return, "fail to get a pepper_buffer from a surface(%p)\n", surface); - - buf_res = pepper_buffer_get_resource(buf); - tbm_surface = wayland_tbm_server_get_surface(NULL, buf_res); - PEPPER_CHECK(tbm_surface, return, "fail to get a tbm_surface from a pepper_buffer(%p)\n", buf); - - ret = tbm_surface_map(tbm_surface, TBM_SURF_OPTION_READ, &info); - PEPPER_CHECK(ret == TBM_SURFACE_ERROR_NONE, return, "fail to map the tbm_surface\n"); - - if (!output->ui_led) - PEPPER_TRACE("[UPDATE LED] %s\n", (char*)info.planes[0].ptr); - else - led_output_update_led(output, info.planes[0].ptr); - - tbm_surface_unmap(tbm_surface); -} - -static void -led_output_cb_frame_done(void *data) -{ - led_output_t *output = (led_output_t *)data; - - PEPPER_TRACE("[OUTPUT] frame_done %p\n", output); - output->frame_done = NULL; - - pepper_output_finish_frame(output->output, NULL); -} - -static void -led_output_add_frame_done(led_output_t *output) +void +headless_output_start_boot_ani(led_output_t *output) { - struct wl_event_loop *loop; - - if (!output || output->frame_done) { - PEPPER_TRACE("[OUTPUT] skip add frame_done\n"); + if (output->boot_ani) return; - } - - PEPPER_TRACE("[OUTPUT] Add idle for frame(output:%p, frame_done:%p)\n", output, output->frame_done); - - loop = wl_display_get_event_loop(pepper_compositor_get_display(output->compositor)); - PEPPER_CHECK(loop, return, "[OUTPUT] fail to get event loop\n"); - - output->frame_done = wl_event_loop_add_idle(loop, led_output_cb_frame_done, output); - PEPPER_CHECK(output->frame_done, return, "[OUTPUT] fail to add idle\n"); -} - -static void -pepper_output_bind_display(led_output_t *output) -{ - tbm_bufmgr bufmgr = NULL; - - PEPPER_CHECK(getenv("TBM_DISPLAY_SERVER"), return, "[TBM] run the subcompoitor mode\n"); - - bufmgr = wayland_tbm_server_get_bufmgr(output->tbm_server); - PEPPER_CHECK(bufmgr, return, "fail to get tbm_bufmgr\n"); - - if (!tbm_bufmgr_bind_native_display(bufmgr, (void *)pepper_compositor_get_display(output->compositor))) - { - PEPPER_CHECK(0, return, "fail to tbm_bufmgr_bind_native_display\n"); - } - - return; -} - -pepper_bool_t -headless_output_init(pepper_compositor_t *compositor) -{ - led_output_t *output = (led_output_t*)calloc(sizeof(led_output_t), 1); - - PEPPER_TRACE("Output Init\n"); - - if (!output) { - PEPPER_ERROR("Failed to allocate memory in %s\n", __FUNCTION__); - return PEPPER_FALSE; - } - - output->compositor = compositor; - output->tbm_server = wayland_tbm_server_init(pepper_compositor_get_display(compositor), NULL, -1, 0); - PEPPER_CHECK(output->tbm_server, goto error, "failed to wayland_tbm_server_init.\n"); - - pepper_output_bind_display(output); - - output->num_led = NUM_LED; - output->ui_led = HL_UI_LED_Init(output->num_led); - if (output->ui_led) HL_UI_LED_Change_Brightness(output->ui_led, 0x1); - - if (!output->ui_led) - PEPPER_ERROR("HL_UI_LED_Init() failed.\n"); - else - boot_ani_start(output); - - output->output = pepper_compositor_add_output(compositor, - &led_output_backend, "led_output", - output, WL_OUTPUT_TRANSFORM_NORMAL, 1); - PEPPER_CHECK(output->output, goto error, "pepper_compositor_add_output() failed.\n"); - output->plane = pepper_output_add_plane(output->output, NULL); - PEPPER_CHECK(output->plane, goto error, "pepper_output_add_plane() failed.\n"); - - pepper_object_set_user_data((pepper_object_t *)compositor, - &KEY_OUTPUT, output, NULL); - PEPPER_TRACE("\t Add Output %p, base %p\n", output, output->output); - PEPPER_TRACE("\t Add Output %p, plane %p\n", output, output->plane); - PEPPER_TRACE("\t Userdata %p\n", pepper_object_get_user_data((pepper_object_t *)compositor,&KEY_OUTPUT)); - return PEPPER_TRUE; - -error: - if (output->ui_led) - HL_UI_LED_Close(output->ui_led); - - if (output->tbm_server) - wayland_tbm_server_deinit(output->tbm_server); - - if (output->output) - pepper_output_destroy(output->output); - - if (output) - free(output); - return PEPPER_FALSE; + boot_ani_start(output); } void -headless_output_deinit(pepper_compositor_t *compositor) +headless_output_stop_boot_ani(led_output_t *output) { - led_output_t *output; - - - output = pepper_object_get_user_data((pepper_object_t *)compositor, &KEY_OUTPUT); - - if (output) { - pepper_object_set_user_data((pepper_object_t *)compositor, &KEY_OUTPUT, NULL, NULL); - - if (output->boot_ani) { - boot_ani_stop(output); - } - - pepper_output_destroy(output->output); - led_output_destroy(output); - - free(output); - } + if (!output->boot_ani) + return; - PEPPER_TRACE("Output Deinit ... DONE\n"); + boot_ani_stop(output); } diff --git a/src/shell/shell.c b/src/shell/shell.c index 1612359..fa50597 100644 --- a/src/shell/shell.c +++ b/src/shell/shell.c @@ -21,15 +21,14 @@ * DEALINGS IN THE SOFTWARE. */ +#include #include #include #include #include -#include -#include +#include #include -#include #include "headless_server.h" @@ -47,24 +46,19 @@ typedef struct HEADLESS_SHELL headless_shell_t; typedef struct HEADLESS_SHELL_SURFACE headless_shell_surface_t; struct HEADLESS_SHELL{ - pepper_compositor_t *compositor; + struct wl_display *display; struct wl_global *zxdg_shell; struct wl_global *tizen_policy; struct wl_event_source *cb_idle; - pepper_view_t *focus; - pepper_view_t *top_mapped; - pepper_view_t *top_visible; - - pepper_event_listener_t *surface_add_listener; - pepper_event_listener_t *surface_remove_listener; - pepper_event_listener_t *view_remove_listener; + struct { + struct wl_signal new_surface; + } events; }; struct HEADLESS_SHELL_SURFACE{ headless_shell_t *hs_shell; - pepper_surface_t *surface; - pepper_view_t *view; + struct ds_surface *ds_surface; uint32_t updates; uint8_t visibility; @@ -74,43 +68,35 @@ struct HEADLESS_SHELL_SURFACE{ struct wl_resource *tizen_visibility; uint32_t last_ack_configure; - pepper_bool_t skip_focus; - - pepper_event_listener_t *cb_commit; -}; - -static void -headless_shell_cb_surface_commit(pepper_event_listener_t *listener, - pepper_object_t *object, - uint32_t id, void *info, void *data); -static void -headless_shell_add_idle(headless_shell_t *shell); + struct wl_listener surface_destroy; + struct { + struct wl_signal destroy; + struct wl_signal map; + struct wl_signal unmap; + struct wl_signal request_activate; + struct wl_signal set_skip_focus; + struct wl_signal unset_skip_focus; + } events; -static void -headless_shell_send_visiblity(pepper_view_t *view, uint8_t visibility); + bool added; + bool mapped; +}; -const static int KEY_SHELL = 0; +static void reset_headless_shell_surface(headless_shell_surface_t *hs_surface); +static void destroy_headless_shell_surface(headless_shell_surface_t *hs_surface); +static void map_headless_shell_surface(headless_shell_surface_t *hs_surface); +static void unmap_headless_shell_surface(headless_shell_surface_t *hs_surface); static void zxdg_toplevel_cb_resource_destroy(struct wl_resource *resource) { headless_shell_surface_t *hs_surface = (headless_shell_surface_t *)wl_resource_get_user_data(resource); - PEPPER_CHECK(hs_surface, return, "fail to get headless_surface.\n"); - PEPPER_CHECK((hs_surface->surface_type == HEADLESS_SURFACE_TOPLEVEL), return, "Invalid surface type.\n"); - PEPPER_CHECK((hs_surface->zxdg_surface == resource), return, "Invalid surface."); - - PEPPER_TRACE("[SHELL] zxdg_toplevel_cb_resource_destroy: view:%p, hs_surface:%p\n", hs_surface->view, hs_surface); - - if (hs_surface->view) { - pepper_view_unmap(hs_surface->view); - headless_shell_add_idle(hs_surface->hs_shell); - } + if (!hs_surface) + return; - hs_surface->surface_type = HEADLESS_SURFACE_NONE; - hs_surface->zxdg_surface = NULL; - SET_UPDATE(hs_surface->updates, UPDATE_SURFACE_TYPE); + reset_headless_shell_surface(hs_surface); } static void @@ -233,9 +219,9 @@ zxdg_popup_cb_resource_destroy(struct wl_resource *resource) { headless_shell_surface_t *hs_surface = (headless_shell_surface_t *)wl_resource_get_user_data(resource); - PEPPER_CHECK(hs_surface, return, "fail to get headless_surface.\n"); - PEPPER_CHECK((hs_surface->surface_type == HEADLESS_SURFACE_POPUP), return, "Invalid surface type.\n"); - PEPPER_CHECK((hs_surface->zxdg_surface == resource), return, "Invalid surface."); + HEADLESS_CHECK(hs_surface, return, "fail to get headless_surface.\n"); + HEADLESS_CHECK((hs_surface->surface_type == HEADLESS_SURFACE_POPUP), return, "Invalid surface type.\n"); + HEADLESS_CHECK((hs_surface->zxdg_surface == resource), return, "Invalid surface."); hs_surface->surface_type = HEADLESS_SURFACE_NONE; hs_surface->zxdg_surface = NULL; @@ -268,26 +254,12 @@ zxdg_surface_cb_resource_destroy(struct wl_resource *resource) headless_shell_surface_t *hs_surface; hs_surface = wl_resource_get_user_data(resource); - PEPPER_CHECK(hs_surface, return, "fail to get hs_surface\n"); - - PEPPER_TRACE("[SHELL] zxdg_surface_cb_resource_destroy: hs_surface:%p view:%p\n", hs_surface, hs_surface->view); - - if (hs_surface->view) { - pepper_view_destroy(hs_surface->view); - hs_surface->view = NULL; - } - - if (hs_surface->cb_commit) { - pepper_event_listener_remove(hs_surface->cb_commit); - hs_surface->cb_commit = NULL; - } + if (!hs_surface) + return; - hs_surface->zxdg_shell_surface = NULL; - hs_surface->skip_focus = PEPPER_FALSE; - hs_surface->visibility = TIZEN_VISIBILITY_VISIBILITY_FULLY_OBSCURED; + HEADLESS_TRACE("[SHELL] zxdg_surface_cb_resource_destroy: hs_surface:%p", hs_surface); - SET_UPDATE(hs_surface->updates, UPDATE_SURFACE_TYPE); - headless_shell_add_idle(hs_surface->hs_shell); + destroy_headless_shell_surface(hs_surface); } static void @@ -296,18 +268,58 @@ zxdg_surface_cb_destroy(struct wl_client *client, struct wl_resource *resource) wl_resource_destroy(resource); } +static void +headless_toplevel_handle_surface_commit(struct ds_surface *ds_surface) +{ + headless_shell_surface_t *hs_surface; + + hs_surface = ds_surface_get_role_data(ds_surface); + if (!hs_surface) + return; + + if (!hs_surface->added) { + hs_surface->added = true; + wl_signal_emit(&hs_surface->hs_shell->events.new_surface, hs_surface); + } + + if (ds_surface_get_buffer(hs_surface->ds_surface) && + !hs_surface->mapped) { + map_headless_shell_surface(hs_surface); + } + else if (!ds_surface_get_buffer(hs_surface->ds_surface) && + hs_surface->mapped) { + unmap_headless_shell_surface(hs_surface); + } +} + +static const struct ds_surface_role xdg_toplevel_role = +{ + .name = "headless_shell_surface", + .commit = headless_toplevel_handle_surface_commit, +}; + static void zxdg_surface_cb_toplevel_get(struct wl_client *client, struct wl_resource *resource, uint32_t id) { headless_shell_surface_t *hs_surface = (headless_shell_surface_t *)wl_resource_get_user_data(resource); struct wl_resource *new_res; - PEPPER_CHECK(hs_surface, return, "fail to get headless_surface\n"); - PEPPER_CHECK((hs_surface->zxdg_surface == NULL), return, "alwreay assign zdg_surface:%p role:%d\n", hs_surface->zxdg_surface, hs_surface->surface_type); + HEADLESS_CHECK(hs_surface, return, "fail to get headless_surface\n"); + + if (!ds_surface_set_role(hs_surface->ds_surface, &xdg_toplevel_role, + hs_surface, resource, ZXDG_SHELL_V6_ERROR_ROLE)) + return; + + if (hs_surface->surface_type != HEADLESS_SURFACE_NONE) { + wl_resource_post_error(hs_surface->zxdg_shell_surface, + ZXDG_SURFACE_V6_ERROR_ALREADY_CONSTRUCTED, + "xdg-surface has already been constructed"); + return; + } new_res = wl_resource_create(client, &zxdg_toplevel_v6_interface, 1, id); if (!new_res) { - PEPPER_ERROR("fail to create zxdg_toplevel"); + HEADLESS_ERROR("fail to create zxdg_toplevel"); wl_resource_post_no_memory(resource); return; } @@ -319,8 +331,6 @@ zxdg_surface_cb_toplevel_get(struct wl_client *client, struct wl_resource *resou hs_surface->surface_type = HEADLESS_SURFACE_TOPLEVEL; hs_surface->zxdg_surface = new_res; - - SET_UPDATE(hs_surface->updates, UPDATE_SURFACE_TYPE); } static void @@ -333,12 +343,12 @@ zxdg_surface_cb_popup_get(struct wl_client *client, headless_shell_surface_t *hs_surface = (headless_shell_surface_t *)wl_resource_get_user_data(resource); struct wl_resource *new_res; - PEPPER_CHECK(hs_surface, return, "fail to get headless_surface\n"); - PEPPER_CHECK((hs_surface->zxdg_surface == NULL), return, "alwreay assign zdg_surface:%p role:%d\n", hs_surface->zxdg_surface, hs_surface->surface_type); + HEADLESS_CHECK(hs_surface, return, "fail to get headless_surface\n"); + HEADLESS_CHECK((hs_surface->zxdg_surface == NULL), return, "alwreay assign zdg_surface:%p role:%d\n", hs_surface->zxdg_surface, hs_surface->surface_type); new_res = wl_resource_create(client, &zxdg_popup_v6_interface, 1, id); if (!new_res) { - PEPPER_ERROR("fail to create popup"); + HEADLESS_ERROR("fail to create popup"); wl_resource_post_no_memory(resource); return; } @@ -370,7 +380,7 @@ zxdg_surface_cb_configure_ack(struct wl_client *client, struct wl_resource *reso headless_shell_surface_t *hs_surface; hs_surface = wl_resource_get_user_data(resource); - PEPPER_CHECK(hs_surface, return, "fail to get headless_shell_surface\n"); + HEADLESS_CHECK(hs_surface, return, "fail to get headless_shell_surface\n"); hs_surface->last_ack_configure = serial; } @@ -446,7 +456,7 @@ static const struct zxdg_positioner_v6_interface zxdg_positioner_interface = static void zxdg_shell_cb_destroy(struct wl_client *client, struct wl_resource *resource) { - PEPPER_TRACE("Destroy zxdg_shell\n"); + HEADLESS_TRACE("Destroy zxdg_shell\n"); wl_resource_destroy(resource); } @@ -456,12 +466,12 @@ zxdg_shell_cb_positioner_create(struct wl_client *client, struct wl_resource *re { struct wl_resource *new_res; - PEPPER_TRACE("Create zxdg_positoiner\n"); + HEADLESS_TRACE("Create zxdg_positoiner\n"); new_res = wl_resource_create(client, &zxdg_positioner_v6_interface, 1, id); if (!new_res) { - PEPPER_ERROR("fail to create zxdg_positioner\n"); + HEADLESS_ERROR("fail to create zxdg_positioner\n"); wl_resource_post_no_memory(resource); return; } @@ -469,35 +479,115 @@ zxdg_shell_cb_positioner_create(struct wl_client *client, struct wl_resource *re wl_resource_set_implementation(new_res, &zxdg_positioner_interface, NULL, NULL); } +static void +map_headless_shell_surface(headless_shell_surface_t *hs_surface) +{ + if (hs_surface->mapped) + return; + + hs_surface->mapped = true; + wl_signal_emit(&hs_surface->events.map, hs_surface); +} + +static void +unmap_headless_shell_surface(headless_shell_surface_t *hs_surface) +{ + if (!hs_surface->mapped) + return; + + hs_surface->mapped = false; + wl_signal_emit(&hs_surface->events.unmap, hs_surface); +} + +static void +reset_headless_shell_surface(headless_shell_surface_t *hs_surface) +{ + if (hs_surface->surface_type != HEADLESS_SURFACE_NONE) + unmap_headless_shell_surface(hs_surface); + + if (hs_surface->added) { + wl_signal_emit(&hs_surface->events.destroy, hs_surface); + hs_surface->added = false; + } + + if (hs_surface->zxdg_surface) { + wl_resource_set_user_data(hs_surface->zxdg_surface, NULL); + hs_surface->zxdg_surface = NULL; + } + + hs_surface->surface_type = HEADLESS_SURFACE_NONE; +} + +static void +destroy_headless_shell_surface(headless_shell_surface_t *hs_surface) +{ + HEADLESS_TRACE("[SHELL] hs_surface free ds_surface:%p, " + "zxdg_shell_surface:%p, zxdg_surface:%p", + hs_surface->ds_surface, hs_surface->zxdg_shell_surface, + hs_surface->zxdg_surface); + + reset_headless_shell_surface(hs_surface); + + wl_resource_set_user_data(hs_surface->zxdg_shell_surface, NULL); + + if (hs_surface->tizen_visibility) + wl_resource_set_user_data(hs_surface->tizen_visibility, NULL); + + ds_surface_reset_role_data(hs_surface->ds_surface); + + wl_list_remove(&hs_surface->surface_destroy.link); + + free(hs_surface); +} + +static void +headless_shell_surface_cb_surface_destroy(struct wl_listener *listener, + void *data) +{ + headless_shell_surface_t *hs_surface; + + hs_surface = wl_container_of(listener, hs_surface, surface_destroy); + destroy_headless_shell_surface(hs_surface); +} + static void zxdg_shell_cb_surface_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *wsurface) { headless_shell_t *hs; headless_shell_surface_t *hs_surface = NULL; - pepper_surface_t *psurface; - const char *role; + struct ds_surface *ds_surface; hs = wl_resource_get_user_data(resource); if (!hs) { - PEPPER_ERROR("fail to get headless_shell\n"); + HEADLESS_ERROR("fail to get headless_shell\n"); wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "failed to get headless shell"); return; } - psurface = wl_resource_get_user_data(wsurface); - PEPPER_CHECK(psurface, goto error, "faile to get pepper_surface\n"); + ds_surface = ds_surface_from_resource(wsurface); + HEADLESS_CHECK(ds_surface, goto error, "faile to get ds_surface\n"); - hs_surface = (headless_shell_surface_t *)pepper_object_get_user_data((pepper_object_t *)psurface, wsurface); + hs_surface = calloc(1, sizeof *hs_surface); if (!hs_surface) { - PEPPER_ERROR("fail to get headless_shell_surface_t: %p key:%p\n", psurface, wsurface); wl_resource_post_no_memory(resource); return; } + hs_surface->hs_shell = hs; + hs_surface->ds_surface = ds_surface; + hs_surface->visibility = TIZEN_VISIBILITY_VISIBILITY_FULLY_OBSCURED; + + wl_signal_init(&hs_surface->events.destroy); + wl_signal_init(&hs_surface->events.map); + wl_signal_init(&hs_surface->events.unmap); + wl_signal_init(&hs_surface->events.request_activate); + wl_signal_init(&hs_surface->events.set_skip_focus); + wl_signal_init(&hs_surface->events.unset_skip_focus); + hs_surface->zxdg_shell_surface = wl_resource_create(client, &zxdg_surface_v6_interface, 1, id); if (!hs_surface->zxdg_shell_surface) { - PEPPER_ERROR("fail to create the zxdg_surface\n"); + HEADLESS_ERROR("fail to create the zxdg_surface\n"); wl_resource_post_no_memory(resource); goto error; } @@ -507,52 +597,23 @@ zxdg_shell_cb_surface_get(struct wl_client *client, struct wl_resource *resource hs_surface, zxdg_surface_cb_resource_destroy); - hs_surface->view = pepper_compositor_add_view(hs->compositor); - if (!hs_surface->view) { - PEPPER_ERROR("fail to create the pepper_view\n"); - wl_resource_post_no_memory(resource); - goto error; - } - - if (!pepper_view_set_surface(hs_surface->view, psurface)) { - PEPPER_ERROR("fail to set surface\n"); - wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, - "Assign set psurface to pview"); - goto error; - } + hs_surface->surface_destroy.notify = + headless_shell_surface_cb_surface_destroy; + ds_surface_add_destroy_listener(ds_surface, &hs_surface->surface_destroy); - hs_surface->cb_commit = pepper_object_add_event_listener((pepper_object_t *)psurface, - PEPPER_EVENT_SURFACE_COMMIT, 0, headless_shell_cb_surface_commit, hs_surface); - - role = pepper_surface_get_role(psurface); - if (!role) { - if (!pepper_surface_set_role(psurface, "xdg_surface")) { - PEPPER_ERROR("fail to set role\n"); - wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, - "Assign \"xdg_surface\" to wl_surface failed\n"); - goto error; - } - } else { - PEPPER_CHECK(!strcmp(role, "xdg_surface"), goto error, "surface has alweady role %s\n", role); - } - - PEPPER_TRACE("[SHELL] create zxdg_surface:%p, pview:%p, psurface:%p\n", + HEADLESS_TRACE("[SHELL] create zxdg_surface:%p, ds_surface:%p\n", hs_surface->zxdg_shell_surface, - hs_surface->view, - psurface); + hs_surface->ds_surface); return; error: if (hs_surface) { - if (hs_surface->view) { - pepper_view_destroy(hs_surface->view); - hs_surface->view = NULL; - } - if (hs_surface->zxdg_shell_surface) { wl_resource_destroy(hs_surface->zxdg_shell_surface); hs_surface->zxdg_shell_surface = NULL; } + + free(hs_surface); } } @@ -576,14 +637,14 @@ zxdg_shell_cb_bind(struct wl_client *client, void *data, uint32_t version, uint3 struct wl_resource *resource; headless_shell_t *hs = (headless_shell_t *)data; - PEPPER_TRACE("Bind zxdg_shell\n"); + HEADLESS_TRACE("Bind zxdg_shell\n"); /* Create resource for zxdg_shell_v6 */ resource = wl_resource_create(client, &zxdg_shell_v6_interface, version, id); - PEPPER_CHECK(resource, goto err_shell, "fail to create the zxdg_shell_v6\n"); + HEADLESS_CHECK(resource, goto err_shell, "fail to create the zxdg_shell_v6\n"); wl_resource_set_implementation(resource, &zxdg_shell_interface, hs, NULL); @@ -592,17 +653,13 @@ err_shell: wl_client_post_no_memory(client); } -static pepper_bool_t +static bool zxdg_init(headless_shell_t *shell) { - struct wl_display *display; - - display = pepper_compositor_get_display(shell->compositor); + shell->zxdg_shell = wl_global_create(shell->display, &zxdg_shell_v6_interface, 1, shell, zxdg_shell_cb_bind); + HEADLESS_CHECK(shell->zxdg_shell, return false, "fail to create zxdg_shell\n"); - shell->zxdg_shell = wl_global_create(display, &zxdg_shell_v6_interface, 1, shell, zxdg_shell_cb_bind); - PEPPER_CHECK(shell->zxdg_shell, return PEPPER_FALSE, "fail to create zxdg_shell\n"); - - return PEPPER_TRUE; + return true; } void @@ -628,7 +685,9 @@ tizen_visibility_cb_vis_destroy(struct wl_resource *res_tzvis) { headless_shell_surface_t *hs_surface = (headless_shell_surface_t *)wl_resource_get_user_data(res_tzvis); - PEPPER_CHECK(hs_surface, return, "[SHELL] cannot get headless_shell_surface_t\n"); + if (!hs_surface) + return; + hs_surface->tizen_visibility = NULL; } @@ -654,22 +713,30 @@ tizen_position_cb_pos_destroy(struct wl_resource *res_tzpos) { } +static headless_shell_surface_t * +headless_shell_surface_from_ds_surface(struct ds_surface *ds_surface) +{ + if (ds_surface_get_role(ds_surface) != &xdg_toplevel_role) + return NULL; + return ds_surface_get_role_data(ds_surface); +} + static void tizen_policy_cb_vis_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surf) { - pepper_surface_t *psurface; + struct ds_surface *ds_surface; headless_shell_surface_t *hs_surface; struct wl_resource *new_res; - psurface = wl_resource_get_user_data(surf); - PEPPER_CHECK(psurface, return, "fail to get pepper_surface_t\n"); + ds_surface = ds_surface_from_resource(surf); + HEADLESS_CHECK(ds_surface, return, "fail to get ds_surface_t\n"); - hs_surface = pepper_object_get_user_data((pepper_object_t *)psurface, surf); - PEPPER_CHECK(hs_surface, return, "fail to get headless_shell_surface\n"); + hs_surface = headless_shell_surface_from_ds_surface(ds_surface); + HEADLESS_CHECK(hs_surface, return, "fail to get headless_shell_surface\n"); new_res = wl_resource_create(client, &tizen_visibility_interface, 5, id); if (!new_res) { - PEPPER_ERROR("fail to create tizen_visibility"); + HEADLESS_ERROR("fail to create tizen_visibility"); wl_resource_post_no_memory(resource); return; } @@ -692,7 +759,7 @@ tizen_policy_cb_pos_get(struct wl_client *client, struct wl_resource *resource, new_res = wl_resource_create(client, &tizen_position_interface, 1, id); if (!new_res) { - PEPPER_ERROR("fail to create tizen_visibility"); + HEADLESS_ERROR("fail to create tizen_visibility"); wl_resource_post_no_memory(resource); return; } @@ -706,19 +773,16 @@ tizen_policy_cb_pos_get(struct wl_client *client, struct wl_resource *resource, static void tizen_policy_cb_activate(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surf) { - pepper_surface_t *psurface; + struct ds_surface *ds_surface; headless_shell_surface_t *hs_surface; - psurface = wl_resource_get_user_data(surf); - PEPPER_CHECK(psurface, return, "fail to get pepper_surface_t\n"); + ds_surface = ds_surface_from_resource(surf); + HEADLESS_CHECK(ds_surface, return, "fail to get ds_surface\n"); - hs_surface = pepper_object_get_user_data((pepper_object_t *)psurface, surf); - PEPPER_CHECK(hs_surface, return, "fail to get headless_shell_surface\n"); - PEPPER_CHECK(hs_surface->view, return, "invalid view from headless_shell_surface\n"); + hs_surface = headless_shell_surface_from_ds_surface(ds_surface); + HEADLESS_CHECK(hs_surface, return, "fail to get headless_shell_surface\n"); - pepper_view_stack_top(hs_surface->view, PEPPER_TRUE); - - headless_shell_add_idle(hs_surface->hs_shell); + wl_signal_emit(&hs_surface->events.request_activate, hs_surface); } static void @@ -744,31 +808,31 @@ tizen_policy_cb_lower_by_res_id(struct wl_client *client, struct wl_resource *re static void tizen_policy_cb_focus_skip_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surf) { - pepper_surface_t *psurface; + struct ds_surface *ds_surface; headless_shell_surface_t *hs_surface; - psurface = wl_resource_get_user_data(surf); - PEPPER_CHECK(psurface, return, "fail to get pepper_surface_t\n"); + ds_surface = ds_surface_from_resource(surf); + HEADLESS_CHECK(ds_surface, return, "fail to get ds_surface\n"); - hs_surface = pepper_object_get_user_data((pepper_object_t *)psurface, surf); - PEPPER_CHECK(hs_surface, return, "fail to get headless_shell_surface\n"); + hs_surface = headless_shell_surface_from_ds_surface(ds_surface); + HEADLESS_CHECK(hs_surface, return, "fail to get headless_shell_surface\n"); - hs_surface->skip_focus = PEPPER_TRUE; + wl_signal_emit(&hs_surface->events.set_skip_focus, hs_surface); } static void tizen_policy_cb_focus_skip_unset(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surf) { - pepper_surface_t *psurface; + struct ds_surface *ds_surface; headless_shell_surface_t *hs_surface; - psurface = wl_resource_get_user_data(surf); - PEPPER_CHECK(psurface, return, "fail to get pepper_surface_t\n"); + ds_surface = ds_surface_from_resource(surf); + HEADLESS_CHECK(ds_surface, return, "fail to get ds_surface\n"); - hs_surface = pepper_object_get_user_data((pepper_object_t *)psurface, surf); - PEPPER_CHECK(hs_surface, return, "fail to get headless_shell_surface\n"); + hs_surface = headless_shell_surface_from_ds_surface(ds_surface); + HEADLESS_CHECK(hs_surface, return, "fail to get headless_shell_surface\n"); - hs_surface->skip_focus = PEPPER_FALSE; + wl_signal_emit(&hs_surface->events.unset_skip_focus, hs_surface); } static void @@ -986,13 +1050,13 @@ tizen_policy_cb_bind(struct wl_client *client, void *data, uint32_t ver, uint32_ headless_shell_t *shell = (headless_shell_t *)data; struct wl_resource *resource; - PEPPER_CHECK(shell, goto err, "data is NULL\n"); + HEADLESS_CHECK(shell, goto err, "data is NULL\n"); resource = wl_resource_create(client, &tizen_policy_interface, ver, id); - PEPPER_CHECK(resource, goto err, "fail to create tizen_policy\n"); + HEADLESS_CHECK(resource, goto err, "fail to create tizen_policy\n"); wl_resource_set_implementation(resource, &tizen_policy_iface, @@ -1004,17 +1068,13 @@ err: wl_client_post_no_memory(client); } -static pepper_bool_t +static bool tizen_policy_init(headless_shell_t *shell) { - struct wl_display *display; + shell->tizen_policy = wl_global_create(shell->display, &tizen_policy_interface, 7, shell, tizen_policy_cb_bind); + HEADLESS_CHECK(shell->tizen_policy, return false, "faile to create tizen_policy\n"); - display = pepper_compositor_get_display(shell->compositor); - - shell->tizen_policy = wl_global_create(display, &tizen_policy_interface, 7, shell, tizen_policy_cb_bind); - PEPPER_CHECK(shell->tizen_policy, return PEPPER_FALSE, "faile to create tizen_policy\n"); - - return PEPPER_TRUE; + return true; } void @@ -1024,311 +1084,107 @@ tizen_policy_deinit(headless_shell_t *shell) wl_global_destroy(shell->tizen_policy); } -static void -headless_shell_send_visiblity(pepper_view_t *view, uint8_t visibility) +void +headless_shell_destroy(headless_shell_t *shell) { - pepper_surface_t *surface; - headless_shell_surface_t *hs_surface; - - if (view == NULL) return; - - surface = pepper_view_get_surface(view); - PEPPER_CHECK(surface, return, "[SHELL] Invalid object surface:%p\n", surface); - - hs_surface = pepper_object_get_user_data((pepper_object_t *)surface, pepper_surface_get_resource(surface)); - PEPPER_CHECK(hs_surface, return, "[SHELL] Invalid object headless_surface:%p\n", hs_surface); - - if (hs_surface->visibility == visibility) { - PEPPER_TRACE("[SHELL] Same Visibility hs_surface:%p, visibility:%d\n", hs_surface, visibility); + if (!shell) return; - } - - if (hs_surface->tizen_visibility) - tizen_visibility_send_notify(hs_surface->tizen_visibility, visibility); - hs_surface->visibility = visibility; - PEPPER_TRACE("[SHELL] Set Visibility hs_surface:%p, visibility:%d\n", hs_surface, visibility); + zxdg_deinit(shell); + tizen_policy_deinit(shell); + free(shell); } -static void -headless_shell_cb_idle(void *data) +headless_shell_t * +headless_shell_create(struct wl_display *display) { - headless_shell_t *hs_shell = (headless_shell_t *)data; - const pepper_list_t *list; - pepper_list_t *l = NULL; - pepper_view_t *view; - pepper_surface_t *surface; - headless_shell_surface_t *hs_surface; - - pepper_view_t *focus = NULL, *top = NULL, *top_visible = NULL; - - PEPPER_TRACE("[SHELL] Enter Idle\n"); - list = pepper_compositor_get_view_list(hs_shell->compositor); - - pepper_list_for_each_list(l, list) { - if (!l) break; - - view = (pepper_view_t *)l->item; - PEPPER_CHECK(view, continue, "[SHELL] idle_cb, Invalid object view:%p\n", view); - - surface = pepper_view_get_surface(view); - PEPPER_CHECK(surface, continue, "[SHELL] idle_cb, Invalid object surface:%p\n", surface); - - hs_surface = pepper_object_get_user_data((pepper_object_t *)surface, pepper_surface_get_resource(surface)); - PEPPER_CHECK(hs_surface, continue, "[SHELL] idle_cb, Invalid object headless_surface:%p\n", hs_surface); - - if (!pepper_view_is_mapped(view)) { - headless_shell_send_visiblity(view, TIZEN_VISIBILITY_VISIBILITY_FULLY_OBSCURED); - continue; - } - - if (!top) - top = view; + headless_shell_t *shell; - if (!focus && !hs_surface->skip_focus) - focus = view; + shell = (headless_shell_t*)calloc(sizeof(headless_shell_t), 1); + HEADLESS_CHECK(shell, goto error, "fail to alloc for shell\n"); - if (!top_visible && pepper_surface_get_buffer(surface)) - top_visible = view; + shell->display = display; - if (focus && top_visible) - break; - } + wl_signal_init(&shell->events.new_surface); - if (top != hs_shell->top_mapped) { - const pepper_list_t *l; - pepper_list_t *ll; + HEADLESS_CHECK(zxdg_init(shell), goto error, "zxdg_init() failed\n"); + HEADLESS_CHECK(tizen_policy_init(shell), goto error, "tizen_policy_init() failed\n"); - PEPPER_TRACE("[SHELL] IDLE : top-view change: %p to %p\n", hs_shell->top_mapped , top); - hs_shell->top_mapped = top; - headless_input_set_top_view(hs_shell->compositor, hs_shell->top_mapped); - headless_debug_set_top_view(hs_shell->compositor, hs_shell->top_mapped); + return shell; - /*Force update the output*/ - l = pepper_compositor_get_output_list(hs_shell->compositor); - pepper_list_for_each_list(ll, l) { - pepper_output_add_damage_region((pepper_output_t *)ll->item, NULL); - } - } - - if (focus != hs_shell->focus) { - PEPPER_TRACE("[SHELL] IDLE : focus-view change: %p to %p\n", hs_shell->focus , focus); - hs_shell->focus = focus; - headless_input_set_focus_view(hs_shell->compositor, hs_shell->focus); - headless_debug_set_focus_view(hs_shell->compositor, hs_shell->focus); - } - - if (top_visible != hs_shell->top_visible) { - PEPPER_TRACE("[SHELL] IDLE : visible-view change: %p to %p\n", hs_shell->top_visible, top_visible); - headless_shell_send_visiblity(hs_shell->top_visible, TIZEN_VISIBILITY_VISIBILITY_FULLY_OBSCURED); - headless_shell_send_visiblity(top_visible, TIZEN_VISIBILITY_VISIBILITY_UNOBSCURED); - hs_shell->top_visible = top_visible; - } +error: + headless_shell_destroy(shell); - hs_shell->cb_idle = NULL; + return NULL; } -static void -headless_shell_cb_surface_commit(pepper_event_listener_t *listener, - pepper_object_t *object, - uint32_t id, void *info, void *data) +void +headless_shell_add_new_surface_listener(headless_shell_t *shell, + struct wl_listener *listener) { - headless_shell_surface_t * hs_surface = (headless_shell_surface_t *)data; - - PEPPER_CHECK(((pepper_object_t *)hs_surface->surface == object), return, "Invalid object\n"); - - /*TODO - 1. Check the changes(buffer, map status...) - */ - if (IS_UPDATE(hs_surface->updates, UPDATE_SURFACE_TYPE)) { - if (hs_surface->surface_type != HEADLESS_SURFACE_NONE) - pepper_view_map(hs_surface->view); - else - pepper_view_unmap(hs_surface->view); - - PEPPER_TRACE("Surface type change. view:%p, type:%d, res:%p\n", hs_surface->view, hs_surface->surface_type, hs_surface->zxdg_surface); - } - - hs_surface->updates = 0; - - headless_shell_add_idle(hs_surface->hs_shell); + wl_signal_add(&shell->events.new_surface, listener); } -static void -headless_shell_cb_surface_free(void *data) +void +headless_shell_surface_add_destroy_listener( + headless_shell_surface_t *hs_surface, struct wl_listener *listener) { - headless_shell_surface_t *surface = (headless_shell_surface_t *)data; - - PEPPER_TRACE("[SHELL] hs_surface free surface:%p, view:%p, zxdg_shell_surface:%p, zxdg_surface:%p\n", - surface->surface, surface->view, - surface->zxdg_shell_surface, surface->zxdg_surface); - - free(surface); + wl_signal_add(&hs_surface->events.destroy, listener); } -static void -headless_shell_cb_surface_add(pepper_event_listener_t *listener, - pepper_object_t *object, - uint32_t id, void *info, void *data) +void +headless_shell_surface_add_map_listener( + headless_shell_surface_t *hs_surface, struct wl_listener *listener) { - headless_shell_surface_t *hs_surface; - pepper_surface_t *surface = (pepper_surface_t *)info; - - hs_surface = (headless_shell_surface_t*)calloc(sizeof(headless_shell_surface_t), 1); - PEPPER_CHECK(hs_surface, return, "fail to alloc for headless_shell_surface\n"); - - hs_surface->hs_shell = (headless_shell_t *)data; - hs_surface->surface = (pepper_surface_t *)surface; - hs_surface->visibility = TIZEN_VISIBILITY_VISIBILITY_FULLY_OBSCURED; - - pepper_object_set_user_data((pepper_object_t *)surface, - pepper_surface_get_resource(surface), - hs_surface, - headless_shell_cb_surface_free); - PEPPER_TRACE("[SHELL] surface_Add: pepper_surface:%, headless_shell:%p to p\n", surface, hs_surface); + wl_signal_add(&hs_surface->events.map, listener); } -static void -headless_shell_cb_surface_remove(pepper_event_listener_t *listener, - pepper_object_t *object, - uint32_t id, void *info, void *data) -{ - headless_shell_surface_t *hs_surface; - pepper_surface_t *surface = (pepper_surface_t *)info; - - hs_surface = pepper_object_get_user_data((pepper_object_t *)surface, pepper_surface_get_resource(surface)); - PEPPER_CHECK(hs_surface, return, "[SHELL] cb_surface_remove, Invalid object headless_surface:%p\n", hs_surface); - PEPPER_TRACE("[SHELL] surface_remove: pepper_surface:%p, headless_shell:%p\n", object, hs_surface); - - if (hs_surface->zxdg_surface) { - wl_resource_set_user_data(hs_surface->zxdg_surface, NULL); - hs_surface->zxdg_surface = NULL; - } - - if (hs_surface->zxdg_shell_surface) { - wl_resource_set_user_data(hs_surface->zxdg_shell_surface, NULL); - hs_surface->zxdg_shell_surface = NULL; - } - - if (hs_surface->view) { - pepper_view_destroy(hs_surface->view); - hs_surface->view = NULL; - } - - SET_UPDATE(hs_surface->updates, UPDATE_SURFACE_TYPE); - headless_shell_add_idle(hs_surface->hs_shell); -} - -static void -headless_shell_cb_view_remove(pepper_event_listener_t *listener, - pepper_object_t *object, - uint32_t id, void *info, void *data) +void +headless_shell_surface_add_unmap_listener( + headless_shell_surface_t *hs_surface, struct wl_listener *listener) { - pepper_view_t *view = (pepper_view_t *)info; - headless_shell_t *shell = (headless_shell_t *)data; - - if (view == shell->top_mapped) - shell->top_mapped = NULL; - - if (view == shell->top_visible) - shell->top_visible = NULL; - - if (view == shell->focus) - shell->focus = NULL; - - headless_shell_add_idle(shell); + wl_signal_add(&hs_surface->events.unmap, listener); } -static void -headless_shell_add_idle(headless_shell_t *shell) +void +headless_shell_surface_add_request_activate_listener( + headless_shell_surface_t *hs_surface, struct wl_listener *listener) { - struct wl_event_loop *loop; - - if (!shell || shell->cb_idle) - return; - - loop = wl_display_get_event_loop(pepper_compositor_get_display(shell->compositor)); - PEPPER_CHECK(loop, return, "fail to get event loop\n"); - - shell->cb_idle = wl_event_loop_add_idle(loop, headless_shell_cb_idle, shell); - PEPPER_CHECK(shell->cb_idle, return, "fail to add idle\n"); + wl_signal_add(&hs_surface->events.request_activate, listener); } -static void -headless_shell_init_listeners(headless_shell_t *shell) +void +headless_shell_surface_add_set_skip_focus_listener( + headless_shell_surface_t *hs_surface, struct wl_listener *listener) { - shell->surface_add_listener = pepper_object_add_event_listener((pepper_object_t *)shell->compositor, - PEPPER_EVENT_COMPOSITOR_SURFACE_ADD, - 0, headless_shell_cb_surface_add, shell); - - shell->surface_remove_listener = pepper_object_add_event_listener((pepper_object_t *)shell->compositor, - PEPPER_EVENT_COMPOSITOR_SURFACE_REMOVE, - 0, headless_shell_cb_surface_remove, shell); - - shell->view_remove_listener = pepper_object_add_event_listener((pepper_object_t *)shell->compositor, - PEPPER_EVENT_COMPOSITOR_VIEW_REMOVE, - 0, headless_shell_cb_view_remove, shell); + wl_signal_add(&hs_surface->events.set_skip_focus, listener); } -static void -headless_shell_deinit_listeners(headless_shell_t *shell) +void +headless_shell_surface_add_unset_skip_focus_listener( + headless_shell_surface_t *hs_surface, struct wl_listener *listener) { - pepper_event_listener_remove(shell->surface_add_listener); - pepper_event_listener_remove(shell->surface_remove_listener); - pepper_event_listener_remove(shell->view_remove_listener); + wl_signal_add(&hs_surface->events.unset_skip_focus, listener); } -static void -headless_shell_destroy(headless_shell_t *shell) +struct ds_surface * +headless_shell_surface_get_surface(headless_shell_surface_t *hs_surface) { - if (!shell) - return; - - if (shell->cb_idle) - wl_event_source_remove(shell->cb_idle); - - headless_shell_deinit_listeners(shell); - zxdg_deinit(shell); - tizen_policy_deinit(shell); + return hs_surface->ds_surface; } void -headless_shell_deinit(pepper_compositor_t *compositor) -{ - headless_shell_t *shell; - - PEPPER_CHECK(compositor, return, "compositor is NULL\n"); - - shell = (headless_shell_t *)pepper_object_get_user_data((pepper_object_t *)compositor, &KEY_SHELL); - PEPPER_CHECK(shell, return, "shell is NULL\n"); - - headless_shell_destroy(shell); - - pepper_object_set_user_data((pepper_object_t *)shell->compositor, &KEY_SHELL, NULL, NULL); - free(shell); -} - -pepper_bool_t -headless_shell_init(pepper_compositor_t *compositor) +headless_shell_send_visibility(headless_shell_surface_t *hs_surface, + uint8_t visibility) { - headless_shell_t *shell; - - shell = (headless_shell_t*)calloc(sizeof(headless_shell_t), 1); - PEPPER_CHECK(shell, goto error, "fail to alloc for shell\n"); - shell->compositor = compositor; - - headless_shell_init_listeners(shell); - PEPPER_CHECK(zxdg_init(shell), goto error, "zxdg_init() failed\n"); - PEPPER_CHECK(tizen_policy_init(shell), goto error, "tizen_policy_init() failed\n"); - - pepper_object_set_user_data((pepper_object_t *)compositor, &KEY_SHELL, shell, NULL); + if (hs_surface->visibility == visibility) { + HEADLESS_TRACE("[SHELL] Same Visibility hs_surface:%p, visibility:%d\n", hs_surface, visibility); + return; + } - return PEPPER_TRUE; + if (hs_surface->tizen_visibility) + tizen_visibility_send_notify(hs_surface->tizen_visibility, visibility); -error: - if (shell) { - headless_shell_destroy(shell); - free(shell); - } - return PEPPER_FALSE; + hs_surface->visibility = visibility; + HEADLESS_TRACE("[SHELL] Set Visibility hs_surface:%p, visibility:%d\n", hs_surface, visibility); }