Use libds for wayland compositor
authorSeunghun Lee <shiin.lee@samsung.com>
Tue, 10 May 2022 08:59:00 +0000 (17:59 +0900)
committerSeunghun Lee <shiin.lee@samsung.com>
Tue, 21 Jun 2022 02:08:03 +0000 (11:08 +0900)
This is an attempt to use libds library instead of pepper for building
headless wayland compositor.

Change-Id: If04a01b275af1e6ed42718f73cf1b93da1c15990

configure.ac
packaging/headless-server.spec
src/Makefile.am
src/headless_server.c
src/headless_server.h
src/output/boot_anim.c
src/output/output_internal.h
src/output/output_led.c
src/shell/shell.c

index d8f71d8..3eb5cfc 100644 (file)
@@ -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)
index 89cf51d..f4e789c 100644 (file)
@@ -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.
index 1cdb324..16c0c56 100644 (file)
@@ -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 \
index d4e2de5..0404464 100644 (file)
  * SOFTWARE.
  */
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <signal.h>
+#include <time.h>
 
-#include <pepper.h>
+#include <dlog.h>
 #include <tbm_bufmgr.h>
+#include <wayland-server.h>
+#include <libds/compositor.h>
+#include <libds/surface.h>
+#include <libds-tizen/tbm_server.h>
+
 #include <headless_server.h>
 
+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);
+}
index d176e6e..32cb8cc 100644 (file)
 #ifndef HEADLESS_SERVER_H
 #define HEADLESS_SERVER_H
 
-#include <pepper.h>
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#define DISABLE_INPUT
+
+#include <stdbool.h>
+
+#include <wayland-server.h>
+#include <tizen-extension-server-protocol.h>
+#include <libds/log.h>
+
+#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
 }
index e6c15a5..c1e45c5 100644 (file)
@@ -26,9 +26,8 @@
 #include <string.h>
 #include <unistd.h>
 
-#include <tbm_bufmgr.h>
-#include <wayland-tbm-server.h>
-#include <pepper-output-backend.h>
+#include <wayland-server.h>
+#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;
index 2bfa286..78a1da8 100644 (file)
 #include <string.h>
 #include <unistd.h>
 
-#include <pepper-output-backend.h>
+#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);
index 24931d1..81369df 100644 (file)
 * DEALINGS IN THE SOFTWARE.
 */
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
-#include <tbm_bufmgr.h>
-#include <wayland-tbm-server.h>
-#include <pepper-output-backend.h>
+#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);
 }
index 1612359..fa50597 100644 (file)
 * DEALINGS IN THE SOFTWARE.
 */
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
-#include <pepper.h>
-#include <pepper-output-backend.h>
+#include <libds/surface.h>
 #include <xdg-shell-unstable-v6-server-protocol.h>
-#include <tizen-extension-server-protocol.h>
 
 #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
@@ -297,17 +269,57 @@ zxdg_surface_cb_destroy(struct wl_client *client, struct wl_resource *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;
        }
@@ -470,34 +480,114 @@ zxdg_shell_cb_positioner_create(struct wl_client *client, struct wl_resource *re
 }
 
 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);
 }