ilmControl: when called from AddNotification, notify of surface creation.
[profile/ivi/wayland-ivi-extension.git] / ivi-layermanagement-api / ilmControl / src / ilm_control_wayland_platform.c
index a86156f..41f2555 100644 (file)
@@ -19,6 +19,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <memory.h>
+#include <errno.h>
 #include <pthread.h>
 #include <signal.h>
 #include <stdbool.h>
 #include <unistd.h>
 #include <poll.h>
 
+#include <sys/eventfd.h>
+
 #include "ilm_common.h"
 #include "ilm_control_platform.h"
 #include "wayland-util.h"
 #include "ivi-controller-client-protocol.h"
 
-static ilmErrorTypes wayland_getPropertiesOfLayer(t_ilm_uint layerID,
-                         struct ilmLayerProperties* pLayerProperties);
-static ilmErrorTypes wayland_getPropertiesOfScreen(t_ilm_display screenID,
-                         struct ilmScreenProperties* pScreenProperties);
-static ilmErrorTypes wayland_getNumberOfHardwareLayers(t_ilm_uint screenID,
-                         t_ilm_uint* pNumberOfHardwareLayers);
-static ilmErrorTypes wayland_getScreenIDs(t_ilm_uint* pNumberOfIDs,
-                         t_ilm_uint** ppIDs);
-static ilmErrorTypes wayland_getLayerIDs(t_ilm_int* pLength,
-                         t_ilm_layer** ppArray);
-static ilmErrorTypes wayland_getLayerIDsOnScreen(t_ilm_uint screenId,
-                         t_ilm_int* pLength, t_ilm_layer** ppArray);
-static ilmErrorTypes wayland_getSurfaceIDs(t_ilm_int* pLength,
-                         t_ilm_surface** ppArray);
-static ilmErrorTypes wayland_getSurfaceIDsOnLayer(t_ilm_layer layer,
-                         t_ilm_int* pLength, t_ilm_surface** ppArray);
-static ilmErrorTypes wayland_layerCreateWithDimension(t_ilm_layer* pLayerId,
-                         t_ilm_uint width, t_ilm_uint height);
-static ilmErrorTypes wayland_layerRemove(t_ilm_layer layerId);
-static ilmErrorTypes wayland_layerGetType(t_ilm_layer layerId,
-                         ilmLayerType* pLayerType);
-static ilmErrorTypes wayland_layerSetVisibility(t_ilm_layer layerId,
-                         t_ilm_bool newVisibility);
-static ilmErrorTypes wayland_layerGetVisibility(t_ilm_layer layerId,
-                         t_ilm_bool *pVisibility);
-static ilmErrorTypes wayland_layerSetOpacity(t_ilm_layer layerId,
-                         t_ilm_float opacity);
-static ilmErrorTypes wayland_layerGetOpacity(t_ilm_layer layerId,
-                         t_ilm_float *pOpacity);
-static ilmErrorTypes wayland_layerSetSourceRectangle(t_ilm_layer layerId,
-                         t_ilm_uint x, t_ilm_uint y,
-                         t_ilm_uint width, t_ilm_uint height);
-static ilmErrorTypes wayland_layerSetDestinationRectangle(t_ilm_layer layerId,
-                         t_ilm_int x, t_ilm_int y,
-                         t_ilm_int width, t_ilm_int height);
-static ilmErrorTypes wayland_layerGetDimension(t_ilm_layer layerId,
-                         t_ilm_uint *pDimension);
-static ilmErrorTypes wayland_layerSetDimension(t_ilm_layer layerId,
-                         t_ilm_uint *pDimension);
-static ilmErrorTypes wayland_layerGetPosition(t_ilm_layer layerId,
-                         t_ilm_uint *pPosition);
-static ilmErrorTypes wayland_layerSetPosition(t_ilm_layer layerId,
-                         t_ilm_uint *pPosition);
-static ilmErrorTypes wayland_layerSetOrientation(t_ilm_layer layerId,
-                         ilmOrientation orientation);
-static ilmErrorTypes wayland_layerGetOrientation(t_ilm_layer layerId,
-                         ilmOrientation *pOrientation);
-static ilmErrorTypes wayland_layerSetChromaKey(t_ilm_layer layerId,
-                         t_ilm_int* pColor);
-static ilmErrorTypes wayland_layerSetRenderOrder(t_ilm_layer layerId,
-                         t_ilm_layer *pSurfaceId,
-                         t_ilm_int number);
-static ilmErrorTypes wayland_layerGetCapabilities(t_ilm_layer layerId,
-                         t_ilm_layercapabilities *pCapabilities);
-static ilmErrorTypes wayland_layerTypeGetCapabilities(ilmLayerType layerType,
-                         t_ilm_layercapabilities *pCapabilities);
-static ilmErrorTypes wayland_surfaceSetVisibility(t_ilm_surface surfaceId,
-                         t_ilm_bool newVisibility);
-static ilmErrorTypes wayland_surfaceSetOpacity(t_ilm_surface surfaceId,
-                         t_ilm_float opacity);
-static ilmErrorTypes wayland_surfaceGetOpacity(t_ilm_surface surfaceId,
-                         t_ilm_float *pOpacity);
-static ilmErrorTypes wayland_SetKeyboardFocusOn(t_ilm_surface surfaceId);
-static ilmErrorTypes wayland_GetKeyboardFocusSurfaceId(
-                         t_ilm_surface* pSurfaceId);
-static ilmErrorTypes wayland_surfaceSetDestinationRectangle(
-                         t_ilm_surface surfaceId,
-                         t_ilm_int x, t_ilm_int y,
-                         t_ilm_int width, t_ilm_int height);
-static ilmErrorTypes wayland_surfaceSetDimension(t_ilm_surface surfaceId,
-                         t_ilm_uint *pDimension);
-static ilmErrorTypes wayland_surfaceGetPosition(t_ilm_surface surfaceId,
-                         t_ilm_uint *pPosition);
-static ilmErrorTypes wayland_surfaceSetPosition(t_ilm_surface surfaceId,
-                         t_ilm_uint *pPosition);
-static ilmErrorTypes wayland_surfaceSetOrientation(t_ilm_surface surfaceId,
-                         ilmOrientation orientation);
-static ilmErrorTypes wayland_surfaceGetOrientation(t_ilm_surface surfaceId,
-                         ilmOrientation *pOrientation);
-static ilmErrorTypes wayland_surfaceGetPixelformat(t_ilm_layer surfaceId,
-                         ilmPixelFormat *pPixelformat);
-static ilmErrorTypes wayland_surfaceSetChromaKey(t_ilm_surface surfaceId,
-                         t_ilm_int* pColor);
-static ilmErrorTypes wayland_displaySetRenderOrder(t_ilm_display display,
-                         t_ilm_layer *pLayerId, const t_ilm_uint number);
-static ilmErrorTypes wayland_takeScreenshot(t_ilm_uint screen,
-                         t_ilm_const_string filename);
-static ilmErrorTypes wayland_takeLayerScreenshot(t_ilm_const_string filename,
-                         t_ilm_layer layerid);
-static ilmErrorTypes wayland_takeSurfaceScreenshot(t_ilm_const_string filename,
-                         t_ilm_surface surfaceid);
-static ilmErrorTypes wayland_SetOptimizationMode(ilmOptimization id,
-                         ilmOptimizationMode mode);
-static ilmErrorTypes wayland_GetOptimizationMode(ilmOptimization id,
-                         ilmOptimizationMode* pMode);
-static ilmErrorTypes wayland_layerAddNotification(t_ilm_layer layer,
-                         layerNotificationFunc callback);
-static ilmErrorTypes wayland_layerRemoveNotification(t_ilm_layer layer);
-static ilmErrorTypes wayland_surfaceAddNotification(t_ilm_surface surface,
-                         surfaceNotificationFunc callback);
-static ilmErrorTypes wayland_surfaceRemoveNotification(t_ilm_surface surface);
-static ilmErrorTypes wayland_init(t_ilm_nativedisplay nativedisplay);
-static void wayland_destroy(void);
-static ilmErrorTypes wayland_getNativeHandle(t_ilm_uint pid,
-                         t_ilm_int *n_handle,
-                         t_ilm_nativehandle **p_handles);
-static ilmErrorTypes wayland_getPropertiesOfSurface(t_ilm_uint surfaceID,
-                         struct ilmSurfaceProperties* pSurfaceProperties);
-static ilmErrorTypes wayland_layerAddSurface(t_ilm_layer layerId,
-                         t_ilm_surface surfaceId);
-static ilmErrorTypes wayland_layerRemoveSurface(t_ilm_layer layerId,
-                         t_ilm_surface surfaceId);
-static ilmErrorTypes wayland_surfaceGetDimension(t_ilm_surface surfaceId,
-                         t_ilm_uint *pDimension);
-static ilmErrorTypes wayland_surfaceGetVisibility(t_ilm_surface surfaceId,
-                         t_ilm_bool *pVisibility);
-static ilmErrorTypes wayland_surfaceSetSourceRectangle(t_ilm_surface surfaceId,
-                         t_ilm_int x, t_ilm_int y,
-                         t_ilm_int width, t_ilm_int height);
-static ilmErrorTypes wayland_commitChanges(void);
-
-void init_ilmControlPlatformTable(void)
-{
-    gIlmControlPlatformFunc.getPropertiesOfLayer =
-        wayland_getPropertiesOfLayer;
-    gIlmControlPlatformFunc.getPropertiesOfScreen =
-        wayland_getPropertiesOfScreen;
-    gIlmControlPlatformFunc.getNumberOfHardwareLayers =
-        wayland_getNumberOfHardwareLayers;
-    gIlmControlPlatformFunc.getScreenIDs =
-        wayland_getScreenIDs;
-    gIlmControlPlatformFunc.getLayerIDs =
-        wayland_getLayerIDs;
-    gIlmControlPlatformFunc.getLayerIDsOnScreen =
-        wayland_getLayerIDsOnScreen;
-    gIlmControlPlatformFunc.getSurfaceIDs =
-        wayland_getSurfaceIDs;
-    gIlmControlPlatformFunc.getSurfaceIDsOnLayer =
-        wayland_getSurfaceIDsOnLayer;
-    gIlmControlPlatformFunc.layerCreateWithDimension =
-        wayland_layerCreateWithDimension;
-    gIlmControlPlatformFunc.layerRemove =
-        wayland_layerRemove;
-    gIlmControlPlatformFunc.layerGetType =
-        wayland_layerGetType;
-    gIlmControlPlatformFunc.layerSetVisibility =
-        wayland_layerSetVisibility;
-    gIlmControlPlatformFunc.layerGetVisibility =
-        wayland_layerGetVisibility;
-    gIlmControlPlatformFunc.layerSetOpacity =
-        wayland_layerSetOpacity;
-    gIlmControlPlatformFunc.layerGetOpacity =
-        wayland_layerGetOpacity;
-    gIlmControlPlatformFunc.layerSetSourceRectangle =
-        wayland_layerSetSourceRectangle;
-    gIlmControlPlatformFunc.layerSetDestinationRectangle =
-        wayland_layerSetDestinationRectangle;
-    gIlmControlPlatformFunc.layerGetDimension =
-        wayland_layerGetDimension;
-    gIlmControlPlatformFunc.layerSetDimension =
-        wayland_layerSetDimension;
-    gIlmControlPlatformFunc.layerGetPosition =
-        wayland_layerGetPosition;
-    gIlmControlPlatformFunc.layerSetPosition =
-        wayland_layerSetPosition;
-    gIlmControlPlatformFunc.layerSetOrientation =
-        wayland_layerSetOrientation;
-    gIlmControlPlatformFunc.layerGetOrientation =
-        wayland_layerGetOrientation;
-    gIlmControlPlatformFunc.layerSetChromaKey =
-        wayland_layerSetChromaKey;
-    gIlmControlPlatformFunc.layerSetRenderOrder =
-        wayland_layerSetRenderOrder;
-    gIlmControlPlatformFunc.layerGetCapabilities =
-        wayland_layerGetCapabilities;
-    gIlmControlPlatformFunc.layerTypeGetCapabilities =
-        wayland_layerTypeGetCapabilities;
-    gIlmControlPlatformFunc.surfaceSetVisibility =
-        wayland_surfaceSetVisibility;
-    gIlmControlPlatformFunc.surfaceSetOpacity =
-        wayland_surfaceSetOpacity;
-    gIlmControlPlatformFunc.surfaceGetOpacity =
-        wayland_surfaceGetOpacity;
-    gIlmControlPlatformFunc.SetKeyboardFocusOn =
-        wayland_SetKeyboardFocusOn;
-    gIlmControlPlatformFunc.GetKeyboardFocusSurfaceId =
-        wayland_GetKeyboardFocusSurfaceId;
-    gIlmControlPlatformFunc.surfaceSetDestinationRectangle =
-        wayland_surfaceSetDestinationRectangle;
-    gIlmControlPlatformFunc.surfaceSetDimension =
-        wayland_surfaceSetDimension;
-    gIlmControlPlatformFunc.surfaceGetPosition =
-        wayland_surfaceGetPosition;
-    gIlmControlPlatformFunc.surfaceSetPosition =
-        wayland_surfaceSetPosition;
-    gIlmControlPlatformFunc.surfaceSetOrientation =
-        wayland_surfaceSetOrientation;
-    gIlmControlPlatformFunc.surfaceGetOrientation =
-        wayland_surfaceGetOrientation;
-    gIlmControlPlatformFunc.surfaceGetPixelformat =
-        wayland_surfaceGetPixelformat;
-    gIlmControlPlatformFunc.surfaceSetChromaKey =
-        wayland_surfaceSetChromaKey;
-    gIlmControlPlatformFunc.displaySetRenderOrder =
-        wayland_displaySetRenderOrder;
-    gIlmControlPlatformFunc.takeScreenshot =
-        wayland_takeScreenshot;
-    gIlmControlPlatformFunc.takeLayerScreenshot =
-        wayland_takeLayerScreenshot;
-    gIlmControlPlatformFunc.takeSurfaceScreenshot =
-        wayland_takeSurfaceScreenshot;
-    gIlmControlPlatformFunc.SetOptimizationMode =
-        wayland_SetOptimizationMode;
-    gIlmControlPlatformFunc.GetOptimizationMode =
-        wayland_GetOptimizationMode;
-    gIlmControlPlatformFunc.layerAddNotification =
-        wayland_layerAddNotification;
-    gIlmControlPlatformFunc.layerRemoveNotification =
-        wayland_layerRemoveNotification;
-    gIlmControlPlatformFunc.surfaceAddNotification =
-        wayland_surfaceAddNotification;
-    gIlmControlPlatformFunc.surfaceRemoveNotification =
-        wayland_surfaceRemoveNotification;
-    gIlmControlPlatformFunc.init =
-        wayland_init;
-    gIlmControlPlatformFunc.destroy =
-        wayland_destroy;
-    gIlmControlPlatformFunc.getNativeHandle =
-        wayland_getNativeHandle;
-    gIlmControlPlatformFunc.getPropertiesOfSurface =
-        wayland_getPropertiesOfSurface;
-    gIlmControlPlatformFunc.layerAddSurface =
-        wayland_layerAddSurface;
-    gIlmControlPlatformFunc.layerRemoveSurface =
-        wayland_layerRemoveSurface;
-    gIlmControlPlatformFunc.surfaceGetDimension =
-        wayland_surfaceGetDimension;
-    gIlmControlPlatformFunc.surfaceGetVisibility =
-        wayland_surfaceGetVisibility;
-    gIlmControlPlatformFunc.surfaceSetSourceRectangle =
-        wayland_surfaceSetSourceRectangle;
-    gIlmControlPlatformFunc.commitChanges =
-        wayland_commitChanges;
-}
+/* GCC visibility */
+#if defined(__GNUC__) && __GNUC__ >= 4
+#define ILM_EXPORT __attribute__ ((visibility("default")))
+#else
+#define ILM_EXPORT
+#endif
 
 struct surface_context {
     struct wl_list link;
@@ -291,6 +56,7 @@ struct surface_context {
     } order;
 
     struct wayland_context *ctx;
+    bool is_surface_creation_noticed;
 };
 
 struct layer_context {
@@ -356,6 +122,7 @@ struct ilm_control_context {
 
     pthread_t thread;
     pthread_mutex_t mutex;
+    int shutdown_fd;
     uint32_t internal_id_surface;
 };
 
@@ -402,6 +169,7 @@ static inline void unlock_context(struct ilm_control_context *ctx)
 static int init_control(void);
 
 static struct ilm_control_context* sync_and_acquire_instance(void);
+static struct surface_context* get_surface_context(struct wayland_context *, uint32_t);
 
 static void release_instance(void);
 
@@ -964,6 +732,12 @@ controller_surface_listener_destroyed(void *data,
 {
     struct surface_context *ctx_surf = data;
 
+    if (ctx_surf->notification != NULL) {
+        ctx_surf->notification(ctx_surf->id_surface,
+                               &ctx_surf->prop,
+                               ILM_NOTIFICATION_CONTENT_REMOVED);
+    }
+
     wl_list_remove(&ctx_surf->link);
     free(ctx_surf);
 }
@@ -973,28 +747,44 @@ controller_surface_listener_content(void *data,
                    struct ivi_controller_surface *controller,
                    int32_t content_state)
 {
+    struct surface_context *ctx_surf = data;
+
     // if client surface (=content) was removed with ilm_surfaceDestroy()
     // the expected behavior within ILM API mandates a full removal
     // of the surface from the scene. We must remove the controller
     // from scene, too.
     if (IVI_CONTROLLER_SURFACE_CONTENT_STATE_CONTENT_REMOVED == content_state)
     {
-        struct surface_context *ctx_surf = data;
+        if (ctx_surf->notification != NULL) {
+            ctx_surf->notification(ctx_surf->id_surface,
+                                   &ctx_surf->prop,
+                                   ILM_NOTIFICATION_CONTENT_REMOVED);
+        }
 
         ivi_controller_surface_destroy(controller, 1);
 
         wl_list_remove(&ctx_surf->link);
         free(ctx_surf);
     }
+    else if (IVI_CONTROLLER_SURFACE_CONTENT_STATE_CONTENT_AVAILABLE == content_state)
+    {
+        if (ctx_surf->notification != NULL) {
+            ctx_surf->notification(ctx_surf->id_surface,
+                                    &ctx_surf->prop,
+                                    ILM_NOTIFICATION_CONTENT_AVAILABLE);
+        }
+    }
 }
 
 static void
 controller_surface_listener_input_focus(void *data,
                    struct ivi_controller_surface *controller,
+                   uint32_t device,
                    int32_t enabled)
 {
     (void)data;
     (void)controller;
+    (void)device;
     (void)enabled;
 }
 
@@ -1036,13 +826,22 @@ controller_listener_surface(void *data,
 {
     struct wayland_context *ctx = data;
     struct surface_context *ctx_surf = NULL;
-    int32_t is_inside = 0;
 
-    is_inside = wayland_controller_is_inside_surface_list(
-                    &ctx->list_surface, id_surface);
-
-    if (is_inside != 0) {
-        fprintf(stderr, "invalid id_surface in controller_listener_surface\n");
+    ctx_surf = get_surface_context(ctx, id_surface);
+    if (ctx_surf != NULL) {
+        if (!ctx_surf->is_surface_creation_noticed) {
+            if (ctx_surf->notification != NULL) {
+                ctx_surf->notification(ctx_surf->id_surface,
+                                       &ctx_surf->prop,
+                                       ILM_NOTIFICATION_CONTENT_AVAILABLE);
+                ctx_surf->is_surface_creation_noticed = true;
+            }
+            ctx_surf->controller = ivi_controller_surface_create(
+                                       controller, id_surface);
+        }
+        else {
+            fprintf(stderr, "invalid id_surface in controller_listener_surface\n");
+        }
         return;
     }
 
@@ -1062,6 +861,7 @@ controller_listener_surface(void *data,
     ctx_surf->id_surface = id_surface;
     ctx_surf->prop.inputDevicesAcceptance = ILM_INPUT_DEVICE_ALL;
     ctx_surf->ctx = ctx;
+    ctx_surf->is_surface_creation_noticed = true;
 
     wl_list_init(&ctx_surf->link);
     wl_list_insert(&ctx->list_surface, &ctx_surf->link);
@@ -1174,23 +974,49 @@ registry_control_listener= {
     NULL
 };
 
-static struct ilm_control_context ilm_context = {0};
+static struct ilm_control_context ilm_context;
 
-static void
-destroy_control_resources(void)
+static void destroy_control_resources(void)
 {
     struct ilm_control_context *ctx = &ilm_context;
-    struct screen_context *ctx_scrn;
-    struct screen_context *next;
 
-    wl_list_for_each_safe(ctx_scrn, next, &ctx->wl.list_screen, link) {
-        if (ctx_scrn->output != NULL) {
-            wl_list_remove(&ctx_scrn->link);
-            wl_output_destroy(ctx_scrn->output);
-            free(ctx_scrn);
-        }
-    }
     if (ctx->wl.controller != NULL) {
+        {
+            struct surface_context *l;
+            struct surface_context *n;
+            wl_list_for_each_safe(l, n, &ctx->wl.list_surface, link) {
+                wl_list_remove(&l->link);
+                wl_list_remove(&l->order.link);
+                ivi_controller_surface_destroy(l->controller, 0);
+                free(l);
+            }
+        }
+
+        {
+            struct layer_context *l;
+            struct layer_context *n;
+            wl_list_for_each_safe(l, n, &ctx->wl.list_layer, link) {
+                wl_list_remove(&l->link);
+                wl_list_remove(&l->order.link);
+                free(l);
+            }
+        }
+
+        {
+            struct screen_context *ctx_scrn;
+            struct screen_context *next;
+
+            wl_list_for_each_safe(ctx_scrn, next, &ctx->wl.list_screen, link) {
+                if (ctx_scrn->output != NULL) {
+                    wl_output_destroy(ctx_scrn->output);
+                }
+
+                wl_list_remove(&ctx_scrn->link);
+                ivi_controller_screen_destroy(ctx_scrn->controller);
+                free(ctx_scrn);
+            }
+        }
+
         ivi_controller_destroy(ctx->wl.controller);
         ctx->wl.controller = NULL;
     }
@@ -1200,25 +1026,41 @@ destroy_control_resources(void)
     wl_event_queue_destroy(ctx->wl.queue);
     ctx->wl.queue = NULL;
 
+    wl_registry_destroy(ctx->wl.registry);
+    ctx->wl.registry = NULL;
+
     if (0 != pthread_mutex_destroy(&ctx->mutex)) {
         fprintf(stderr, "failed to destroy pthread_mutex\n");
     }
 }
 
-static void
-wayland_destroy(void)
+static void send_shutdown_event(struct ilm_control_context *ctx)
+{
+    uint64_t buf = 1;
+    while (write(ctx->shutdown_fd, &buf, sizeof buf) == -1 && errno == EINTR)
+       ;
+}
+
+ILM_EXPORT void
+ilmControl_destroy(void)
 {
     struct ilm_control_context *ctx = &ilm_context;
-    pthread_cancel(ctx->thread);
+
+    send_shutdown_event(ctx);
+
     if (0 != pthread_join(ctx->thread, NULL)) {
         fprintf(stderr, "failed to join control thread\n");
     }
+
     destroy_control_resources();
+
+    close(ctx->shutdown_fd);
+
     memset(ctx, 0, sizeof *ctx);
 }
 
-static ilmErrorTypes
-wayland_init(t_ilm_nativedisplay nativedisplay)
+ILM_EXPORT ilmErrorTypes
+ilmControl_init(t_ilm_nativedisplay nativedisplay)
 {
     struct ilm_control_context *ctx = &ilm_context;
 
@@ -1263,34 +1105,35 @@ wayland_init(t_ilm_nativedisplay nativedisplay)
        pthread_mutexattr_destroy(&a);
     }
 
-    return init_control() == 0 ? ILM_SUCCESS : ILM_FAILED;
-}
+    ctx->shutdown_fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
 
-static void cancel_read(void *d)
-{
-    wl_display_cancel_read(d);
+    if (ctx->shutdown_fd == -1)
+    {
+        fprintf(stderr, "Could not setup shutdown-fd: %s\n", strerror(errno));
+        return ILM_FAILED;
+    }
+
+    return init_control() == 0 ? ILM_SUCCESS : ILM_FAILED;
 }
 
 static void*
 control_thread(void *p_ret)
 {
-    struct ilm_control_context *ctx = &ilm_context;
-    struct wayland_context *wl = &ctx->wl;
-    struct wl_display *display = wl->display;
-    struct wl_event_queue *queue = wl->queue;
-    int fd = wl_display_get_fd(display);
-
+    struct ilm_control_context *const ctx = &ilm_context;
+    struct wayland_context *const wl = &ctx->wl;
+    struct wl_display *const display = wl->display;
+    struct wl_event_queue *const queue = wl->queue;
+    int const fd = wl_display_get_fd(display);
+    int const shutdown_fd = ctx->shutdown_fd;
     (void) p_ret;
 
     while (1)
     {
-        if (wl_display_prepare_read_queue(display, queue) != 0)
+        while (wl_display_prepare_read_queue(display, queue) != 0)
         {
             lock_context(ctx);
             wl_display_dispatch_queue_pending(display, queue);
             unlock_context(ctx);
-
-            continue;
         }
 
         if (wl_display_flush(display) == -1)
@@ -1298,19 +1141,13 @@ control_thread(void *p_ret)
             break;
         }
 
-        struct pollfd pfd;
-
-        pfd.fd = fd;
-        pfd.events = POLLIN;
-        pfd.revents = 0;
-
-        int pollret = -1;
+        struct pollfd pfd[2] = {
+           { .fd = fd,          .events = POLLIN },
+           { .fd = shutdown_fd, .events = POLLIN }
+        };
 
-        pthread_cleanup_push(cancel_read, display);
-        pollret = poll(&pfd, 1, -1);
-        pthread_cleanup_pop(0);
-
-        if (pollret != -1 && (pfd.revents & POLLIN))
+        int pollret = poll(pfd, 2, -1);
+        if (pollret != -1 && (pfd[0].revents & POLLIN))
         {
             wl_display_read_events(display);
 
@@ -1326,6 +1163,11 @@ control_thread(void *p_ret)
         else
         {
             wl_display_cancel_read(display);
+
+            if (pollret == -1 || (pfd[1].revents & POLLIN))
+            {
+                break;
+            }
         }
     }
 
@@ -1347,6 +1189,8 @@ init_control(void)
     /* registry_add_listener for request by ivi-controller */
     wl->registry = wl_display_get_registry(wl->display);
     if (wl->registry == NULL) {
+        wl_event_queue_destroy(wl->queue);
+        wl->queue = NULL;
         fprintf(stderr, "Failed to get registry\n");
         return -1;
     }
@@ -1377,14 +1221,16 @@ init_control(void)
     return 0;
 }
 
-static struct ilm_control_context*
-sync_and_acquire_instance(void)
-{
-    struct ilm_control_context *ctx = &ilm_context;
-    lock_context(ctx);
-    display_roundtrip_queue(ctx->wl.display, ctx->wl.queue);
-    return ctx;
-}
+#define sync_and_acquire_instance() ({ \
+    struct ilm_control_context *ctx = &ilm_context; \
+    if (! ctx->initialized) { \
+        fputs("Not initialized\n", stderr); \
+        return ILM_FAILED; \
+    } \
+    lock_context(ctx); \
+    display_roundtrip_queue(ctx->wl.display, ctx->wl.queue); \
+    ctx; \
+})
 
 static void release_instance(void)
 {
@@ -1455,8 +1301,8 @@ get_screen_context_by_id(struct wayland_context *ctx, uint32_t id_screen)
     return NULL;
 }
 
-static ilmErrorTypes
-wayland_getPropertiesOfLayer(t_ilm_uint layerID,
+ILM_EXPORT ilmErrorTypes
+ilm_getPropertiesOfLayer(t_ilm_uint layerID,
                          struct ilmLayerProperties* pLayerProperties)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
@@ -1506,8 +1352,8 @@ create_layerids(struct screen_context *ctx_screen,
     }
 }
 
-static ilmErrorTypes
-wayland_getPropertiesOfScreen(t_ilm_display screenID,
+ILM_EXPORT ilmErrorTypes
+ilm_getPropertiesOfScreen(t_ilm_display screenID,
                               struct ilmScreenProperties* pScreenProperties)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
@@ -1532,8 +1378,8 @@ wayland_getPropertiesOfScreen(t_ilm_display screenID,
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_getNumberOfHardwareLayers(t_ilm_uint screenID,
+ILM_EXPORT ilmErrorTypes
+ilm_getNumberOfHardwareLayers(t_ilm_uint screenID,
                                   t_ilm_uint* pNumberOfHardwareLayers)
 {
     (void)screenID;
@@ -1546,8 +1392,8 @@ wayland_getNumberOfHardwareLayers(t_ilm_uint screenID,
     }
 }
 
-static ilmErrorTypes
-wayland_getScreenIDs(t_ilm_uint* pNumberOfIDs, t_ilm_uint** ppIDs)
+ILM_EXPORT ilmErrorTypes
+ilm_getScreenIDs(t_ilm_uint* pNumberOfIDs, t_ilm_uint** ppIDs)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
     struct ilm_control_context *ctx = sync_and_acquire_instance();
@@ -1557,7 +1403,7 @@ wayland_getScreenIDs(t_ilm_uint* pNumberOfIDs, t_ilm_uint** ppIDs)
         t_ilm_uint length = wl_list_length(&ctx->wl.list_screen);
         *pNumberOfIDs = 0;
 
-        *ppIDs = (t_ilm_uint*)malloc(length * sizeof *ppIDs);
+        *ppIDs = (t_ilm_uint*)malloc(length * sizeof **ppIDs);
         if (*ppIDs != NULL) {
             t_ilm_uint* ids = *ppIDs;
             wl_list_for_each(ctx_scrn, &ctx->wl.list_screen, link) {
@@ -1574,8 +1420,8 @@ wayland_getScreenIDs(t_ilm_uint* pNumberOfIDs, t_ilm_uint** ppIDs)
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_getLayerIDs(t_ilm_int* pLength, t_ilm_layer** ppArray)
+ILM_EXPORT ilmErrorTypes
+ilm_getLayerIDs(t_ilm_int* pLength, t_ilm_layer** ppArray)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
     struct ilm_control_context *ctx = sync_and_acquire_instance();
@@ -1585,7 +1431,7 @@ wayland_getLayerIDs(t_ilm_int* pLength, t_ilm_layer** ppArray)
         t_ilm_uint length = wl_list_length(&ctx->wl.list_layer);
         *pLength = 0;
 
-        *ppArray = (t_ilm_layer*)malloc(length * sizeof *ppArray);
+        *ppArray = (t_ilm_layer*)malloc(length * sizeof **ppArray);
         if (*ppArray != NULL) {
             // compositor sends layers in opposite order
             // write ids from back to front to turn them around
@@ -1605,8 +1451,8 @@ wayland_getLayerIDs(t_ilm_int* pLength, t_ilm_layer** ppArray)
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_getLayerIDsOnScreen(t_ilm_uint screenId,
+ILM_EXPORT ilmErrorTypes
+ilm_getLayerIDsOnScreen(t_ilm_uint screenId,
                             t_ilm_int* pLength,
                             t_ilm_layer** ppArray)
 {
@@ -1622,7 +1468,7 @@ wayland_getLayerIDsOnScreen(t_ilm_uint screenId,
 
             if (0 < length)
             {
-                *ppArray = (t_ilm_layer*)malloc(length * sizeof *ppArray);
+                *ppArray = (t_ilm_layer*)malloc(length * sizeof **ppArray);
                 if (*ppArray != NULL) {
                     // compositor sends layers in opposite order
                     // write ids from back to front to turn them around
@@ -1649,8 +1495,8 @@ wayland_getLayerIDsOnScreen(t_ilm_uint screenId,
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_getSurfaceIDs(t_ilm_int* pLength, t_ilm_surface** ppArray)
+ILM_EXPORT ilmErrorTypes
+ilm_getSurfaceIDs(t_ilm_int* pLength, t_ilm_surface** ppArray)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
     struct ilm_control_context *ctx = sync_and_acquire_instance();
@@ -1660,7 +1506,7 @@ wayland_getSurfaceIDs(t_ilm_int* pLength, t_ilm_surface** ppArray)
         t_ilm_uint length = wl_list_length(&ctx->wl.list_surface);
         *pLength = 0;
 
-        *ppArray = (t_ilm_surface*)malloc(length * sizeof *ppArray);
+        *ppArray = (t_ilm_surface*)malloc(length * sizeof **ppArray);
         if (*ppArray != NULL) {
             t_ilm_surface* ids = *ppArray;
             wl_list_for_each_reverse(ctx_surf, &ctx->wl.list_surface, link) {
@@ -1677,8 +1523,8 @@ wayland_getSurfaceIDs(t_ilm_int* pLength, t_ilm_surface** ppArray)
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_getSurfaceIDsOnLayer(t_ilm_layer layer,
+ILM_EXPORT ilmErrorTypes
+ilm_getSurfaceIDsOnLayer(t_ilm_layer layer,
                              t_ilm_int* pLength,
                              t_ilm_surface** ppArray)
 {
@@ -1702,7 +1548,7 @@ wayland_getSurfaceIDsOnLayer(t_ilm_layer layer,
     }
 
     length = wl_list_length(&ctx_layer->order.list_surface);
-    *ppArray = (t_ilm_surface*)malloc(length * sizeof *ppArray);
+    *ppArray = (t_ilm_surface*)malloc(length * sizeof **ppArray);
     if (*ppArray == NULL) {
         release_instance();
         return ILM_FAILED;
@@ -1749,8 +1595,8 @@ static int create_controller_layer(struct wayland_context *ctx, t_ilm_uint width
      return 0;
 }
 
-static ilmErrorTypes
-wayland_layerCreateWithDimension(t_ilm_layer* pLayerId,
+ILM_EXPORT ilmErrorTypes
+ilm_layerCreateWithDimension(t_ilm_layer* pLayerId,
                                  t_ilm_uint width,
                                  t_ilm_uint height)
 {
@@ -1790,8 +1636,8 @@ wayland_layerCreateWithDimension(t_ilm_layer* pLayerId,
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_layerRemove(t_ilm_layer layerId)
+ILM_EXPORT ilmErrorTypes
+ilm_layerRemove(t_ilm_layer layerId)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
     struct ilm_control_context *ctx = sync_and_acquire_instance();
@@ -1815,8 +1661,8 @@ wayland_layerRemove(t_ilm_layer layerId)
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_layerGetType(t_ilm_layer layerId, ilmLayerType* pLayerType)
+ILM_EXPORT ilmErrorTypes
+ilm_layerGetType(t_ilm_layer layerId, ilmLayerType* pLayerType)
 {
     if (!pLayerType)
     {
@@ -1833,8 +1679,8 @@ wayland_layerGetType(t_ilm_layer layerId, ilmLayerType* pLayerType)
     return ILM_SUCCESS; // even if non existent?
 }
 
-static ilmErrorTypes
-wayland_layerSetVisibility(t_ilm_layer layerId, t_ilm_bool newVisibility)
+ILM_EXPORT ilmErrorTypes
+ilm_layerSetVisibility(t_ilm_layer layerId, t_ilm_bool newVisibility)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
     struct ilm_control_context *ctx = sync_and_acquire_instance();
@@ -1857,8 +1703,8 @@ wayland_layerSetVisibility(t_ilm_layer layerId, t_ilm_bool newVisibility)
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_layerGetVisibility(t_ilm_layer layerId, t_ilm_bool *pVisibility)
+ILM_EXPORT ilmErrorTypes
+ilm_layerGetVisibility(t_ilm_layer layerId, t_ilm_bool *pVisibility)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
     struct ilm_control_context *ctx = sync_and_acquire_instance();
@@ -1880,8 +1726,8 @@ wayland_layerGetVisibility(t_ilm_layer layerId, t_ilm_bool *pVisibility)
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_layerSetOpacity(t_ilm_layer layerId, t_ilm_float opacity)
+ILM_EXPORT ilmErrorTypes
+ilm_layerSetOpacity(t_ilm_layer layerId, t_ilm_float opacity)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
     struct ilm_control_context *ctx = sync_and_acquire_instance();
@@ -1901,8 +1747,8 @@ wayland_layerSetOpacity(t_ilm_layer layerId, t_ilm_float opacity)
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_layerGetOpacity(t_ilm_layer layerId, t_ilm_float *pOpacity)
+ILM_EXPORT ilmErrorTypes
+ilm_layerGetOpacity(t_ilm_layer layerId, t_ilm_float *pOpacity)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
     struct ilm_control_context *ctx = sync_and_acquire_instance();
@@ -1924,8 +1770,8 @@ wayland_layerGetOpacity(t_ilm_layer layerId, t_ilm_float *pOpacity)
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_layerSetSourceRectangle(t_ilm_layer layerId,
+ILM_EXPORT ilmErrorTypes
+ilm_layerSetSourceRectangle(t_ilm_layer layerId,
                                 t_ilm_uint x, t_ilm_uint y,
                                 t_ilm_uint width, t_ilm_uint height)
 {
@@ -1949,8 +1795,8 @@ wayland_layerSetSourceRectangle(t_ilm_layer layerId,
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_layerSetDestinationRectangle(t_ilm_layer layerId,
+ILM_EXPORT ilmErrorTypes
+ilm_layerSetDestinationRectangle(t_ilm_layer layerId,
                                  t_ilm_int x, t_ilm_int y,
                                  t_ilm_int width, t_ilm_int height)
 {
@@ -1973,8 +1819,8 @@ wayland_layerSetDestinationRectangle(t_ilm_layer layerId,
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_layerGetDimension(t_ilm_layer layerId, t_ilm_uint *pDimension)
+ILM_EXPORT ilmErrorTypes
+ilm_layerGetDimension(t_ilm_layer layerId, t_ilm_uint *pDimension)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
     struct ilm_control_context *ctx = sync_and_acquire_instance();
@@ -1995,8 +1841,8 @@ wayland_layerGetDimension(t_ilm_layer layerId, t_ilm_uint *pDimension)
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_layerSetDimension(t_ilm_layer layerId, t_ilm_uint *pDimension)
+ILM_EXPORT ilmErrorTypes
+ilm_layerSetDimension(t_ilm_layer layerId, t_ilm_uint *pDimension)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
     struct ilm_control_context *ctx = sync_and_acquire_instance();
@@ -2019,8 +1865,8 @@ wayland_layerSetDimension(t_ilm_layer layerId, t_ilm_uint *pDimension)
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_layerGetPosition(t_ilm_layer layerId, t_ilm_uint *pPosition)
+ILM_EXPORT ilmErrorTypes
+ilm_layerGetPosition(t_ilm_layer layerId, t_ilm_uint *pPosition)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
     struct ilm_control_context *ctx = sync_and_acquire_instance();
@@ -2041,8 +1887,8 @@ wayland_layerGetPosition(t_ilm_layer layerId, t_ilm_uint *pPosition)
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_layerSetPosition(t_ilm_layer layerId, t_ilm_uint *pPosition)
+ILM_EXPORT ilmErrorTypes
+ilm_layerSetPosition(t_ilm_layer layerId, t_ilm_uint *pPosition)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
     struct ilm_control_context *ctx = sync_and_acquire_instance();
@@ -2065,8 +1911,8 @@ wayland_layerSetPosition(t_ilm_layer layerId, t_ilm_uint *pPosition)
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_layerSetOrientation(t_ilm_layer layerId, ilmOrientation orientation)
+ILM_EXPORT ilmErrorTypes
+ilm_layerSetOrientation(t_ilm_layer layerId, ilmOrientation orientation)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
     struct ilm_control_context *ctx = sync_and_acquire_instance();
@@ -2109,8 +1955,8 @@ wayland_layerSetOrientation(t_ilm_layer layerId, ilmOrientation orientation)
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_layerGetOrientation(t_ilm_layer layerId, ilmOrientation *pOrientation)
+ILM_EXPORT ilmErrorTypes
+ilm_layerGetOrientation(t_ilm_layer layerId, ilmOrientation *pOrientation)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
     struct ilm_control_context *ctx = sync_and_acquire_instance();
@@ -2130,8 +1976,8 @@ wayland_layerGetOrientation(t_ilm_layer layerId, ilmOrientation *pOrientation)
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_layerSetChromaKey(t_ilm_layer layerId, t_ilm_int* pColor)
+ILM_EXPORT ilmErrorTypes
+ilm_layerSetChromaKey(t_ilm_layer layerId, t_ilm_int* pColor)
 {
     (void)layerId;
     (void)pColor;
@@ -2139,8 +1985,8 @@ wayland_layerSetChromaKey(t_ilm_layer layerId, t_ilm_int* pColor)
     return ILM_FAILED;
 }
 
-static ilmErrorTypes
-wayland_layerSetRenderOrder(t_ilm_layer layerId,
+ILM_EXPORT ilmErrorTypes
+ilm_layerSetRenderOrder(t_ilm_layer layerId,
                         t_ilm_surface *pSurfaceId,
                         t_ilm_int number)
 {
@@ -2167,8 +2013,8 @@ wayland_layerSetRenderOrder(t_ilm_layer layerId,
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_layerGetCapabilities(t_ilm_layer layerId,
+ILM_EXPORT ilmErrorTypes
+ilm_layerGetCapabilities(t_ilm_layer layerId,
                          t_ilm_layercapabilities *pCapabilities)
 {
     (void)layerId;
@@ -2177,8 +2023,8 @@ wayland_layerGetCapabilities(t_ilm_layer layerId,
     return ILM_FAILED;
 }
 
-static ilmErrorTypes
-wayland_layerTypeGetCapabilities(ilmLayerType layerType,
+ILM_EXPORT ilmErrorTypes
+ilm_layerTypeGetCapabilities(ilmLayerType layerType,
                              t_ilm_layercapabilities *pCapabilities)
 {
     (void)layerType;
@@ -2187,8 +2033,8 @@ wayland_layerTypeGetCapabilities(ilmLayerType layerType,
     return ILM_FAILED;
 }
 
-static ilmErrorTypes
-wayland_surfaceSetVisibility(t_ilm_surface surfaceId, t_ilm_bool newVisibility)
+ILM_EXPORT ilmErrorTypes
+ilm_surfaceSetVisibility(t_ilm_surface surfaceId, t_ilm_bool newVisibility)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
     struct ilm_control_context *ctx = sync_and_acquire_instance();
@@ -2209,8 +2055,8 @@ wayland_surfaceSetVisibility(t_ilm_surface surfaceId, t_ilm_bool newVisibility)
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_surfaceSetOpacity(t_ilm_surface surfaceId, t_ilm_float opacity)
+ILM_EXPORT ilmErrorTypes
+ilm_surfaceSetOpacity(t_ilm_surface surfaceId, t_ilm_float opacity)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
     struct ilm_control_context *ctx = sync_and_acquire_instance();
@@ -2229,8 +2075,8 @@ wayland_surfaceSetOpacity(t_ilm_surface surfaceId, t_ilm_float opacity)
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_surfaceGetOpacity(t_ilm_surface surfaceId, t_ilm_float *pOpacity)
+ILM_EXPORT ilmErrorTypes
+ilm_surfaceGetOpacity(t_ilm_surface surfaceId, t_ilm_float *pOpacity)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
     struct ilm_control_context *ctx = sync_and_acquire_instance();
@@ -2248,8 +2094,8 @@ wayland_surfaceGetOpacity(t_ilm_surface surfaceId, t_ilm_float *pOpacity)
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_SetKeyboardFocusOn(t_ilm_surface surfaceId)
+ILM_EXPORT ilmErrorTypes
+ilm_SetKeyboardFocusOn(t_ilm_surface surfaceId)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
     (void)surfaceId;
@@ -2257,8 +2103,8 @@ wayland_SetKeyboardFocusOn(t_ilm_surface surfaceId)
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_GetKeyboardFocusSurfaceId(t_ilm_surface* pSurfaceId)
+ILM_EXPORT ilmErrorTypes
+ilm_GetKeyboardFocusSurfaceId(t_ilm_surface* pSurfaceId)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
     (void)pSurfaceId;
@@ -2266,8 +2112,8 @@ wayland_GetKeyboardFocusSurfaceId(t_ilm_surface* pSurfaceId)
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_surfaceSetDestinationRectangle(t_ilm_surface surfaceId,
+ILM_EXPORT ilmErrorTypes
+ilm_surfaceSetDestinationRectangle(t_ilm_surface surfaceId,
                                    t_ilm_int x, t_ilm_int y,
                                    t_ilm_int width, t_ilm_int height)
 {
@@ -2287,8 +2133,8 @@ wayland_surfaceSetDestinationRectangle(t_ilm_surface surfaceId,
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_surfaceSetDimension(t_ilm_surface surfaceId, t_ilm_uint *pDimension)
+ILM_EXPORT ilmErrorTypes
+ilm_surfaceSetDimension(t_ilm_surface surfaceId, t_ilm_uint *pDimension)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
     struct ilm_control_context *ctx = sync_and_acquire_instance();
@@ -2310,8 +2156,8 @@ wayland_surfaceSetDimension(t_ilm_surface surfaceId, t_ilm_uint *pDimension)
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_surfaceGetPosition(t_ilm_surface surfaceId, t_ilm_uint *pPosition)
+ILM_EXPORT ilmErrorTypes
+ilm_surfaceGetPosition(t_ilm_surface surfaceId, t_ilm_uint *pPosition)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
     struct ilm_control_context *ctx = sync_and_acquire_instance();
@@ -2330,8 +2176,8 @@ wayland_surfaceGetPosition(t_ilm_surface surfaceId, t_ilm_uint *pPosition)
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_surfaceSetPosition(t_ilm_surface surfaceId, t_ilm_uint *pPosition)
+ILM_EXPORT ilmErrorTypes
+ilm_surfaceSetPosition(t_ilm_surface surfaceId, t_ilm_uint *pPosition)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
     struct ilm_control_context *ctx = sync_and_acquire_instance();
@@ -2353,8 +2199,8 @@ wayland_surfaceSetPosition(t_ilm_surface surfaceId, t_ilm_uint *pPosition)
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_surfaceSetOrientation(t_ilm_surface surfaceId,
+ILM_EXPORT ilmErrorTypes
+ilm_surfaceSetOrientation(t_ilm_surface surfaceId,
                               ilmOrientation orientation)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
@@ -2397,8 +2243,8 @@ wayland_surfaceSetOrientation(t_ilm_surface surfaceId,
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_surfaceGetOrientation(t_ilm_surface surfaceId,
+ILM_EXPORT ilmErrorTypes
+ilm_surfaceGetOrientation(t_ilm_surface surfaceId,
                               ilmOrientation *pOrientation)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
@@ -2417,8 +2263,8 @@ wayland_surfaceGetOrientation(t_ilm_surface surfaceId,
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_surfaceGetPixelformat(t_ilm_layer surfaceId,
+ILM_EXPORT ilmErrorTypes
+ilm_surfaceGetPixelformat(t_ilm_layer surfaceId,
                               ilmPixelFormat *pPixelformat)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
@@ -2437,8 +2283,8 @@ wayland_surfaceGetPixelformat(t_ilm_layer surfaceId,
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_surfaceSetChromaKey(t_ilm_surface surfaceId, t_ilm_int* pColor)
+ILM_EXPORT ilmErrorTypes
+ilm_surfaceSetChromaKey(t_ilm_surface surfaceId, t_ilm_int* pColor)
 {
     (void)surfaceId;
     (void)pColor;
@@ -2446,8 +2292,8 @@ wayland_surfaceSetChromaKey(t_ilm_surface surfaceId, t_ilm_int* pColor)
     return ILM_FAILED;
 }
 
-static ilmErrorTypes
-wayland_displaySetRenderOrder(t_ilm_display display,
+ILM_EXPORT ilmErrorTypes
+ilm_displaySetRenderOrder(t_ilm_display display,
                           t_ilm_layer *pLayerId, const t_ilm_uint number)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
@@ -2470,8 +2316,8 @@ wayland_displaySetRenderOrder(t_ilm_display display,
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_takeScreenshot(t_ilm_uint screen, t_ilm_const_string filename)
+ILM_EXPORT ilmErrorTypes
+ilm_takeScreenshot(t_ilm_uint screen, t_ilm_const_string filename)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
     struct ilm_control_context *ctx = sync_and_acquire_instance();
@@ -2489,8 +2335,8 @@ wayland_takeScreenshot(t_ilm_uint screen, t_ilm_const_string filename)
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_takeLayerScreenshot(t_ilm_const_string filename, t_ilm_layer layerid)
+ILM_EXPORT ilmErrorTypes
+ilm_takeLayerScreenshot(t_ilm_const_string filename, t_ilm_layer layerid)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
     struct ilm_control_context *ctx = sync_and_acquire_instance();
@@ -2509,8 +2355,8 @@ wayland_takeLayerScreenshot(t_ilm_const_string filename, t_ilm_layer layerid)
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_takeSurfaceScreenshot(t_ilm_const_string filename,
+ILM_EXPORT ilmErrorTypes
+ilm_takeSurfaceScreenshot(t_ilm_const_string filename,
                               t_ilm_surface surfaceid)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
@@ -2529,8 +2375,8 @@ wayland_takeSurfaceScreenshot(t_ilm_const_string filename,
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_SetOptimizationMode(ilmOptimization id, ilmOptimizationMode mode)
+ILM_EXPORT ilmErrorTypes
+ilm_SetOptimizationMode(ilmOptimization id, ilmOptimizationMode mode)
 {
     (void)id;
     (void)mode;
@@ -2538,8 +2384,8 @@ wayland_SetOptimizationMode(ilmOptimization id, ilmOptimizationMode mode)
     return ILM_FAILED;
 }
 
-static ilmErrorTypes
-wayland_GetOptimizationMode(ilmOptimization id, ilmOptimizationMode* pMode)
+ILM_EXPORT ilmErrorTypes
+ilm_GetOptimizationMode(ilmOptimization id, ilmOptimizationMode* pMode)
 {
     (void)id;
     (void)pMode;
@@ -2547,9 +2393,8 @@ wayland_GetOptimizationMode(ilmOptimization id, ilmOptimizationMode* pMode)
     return ILM_FAILED;
 }
 
-// TODO
-static ilmErrorTypes
-wayland_layerAddNotification(t_ilm_layer layer,
+ILM_EXPORT ilmErrorTypes
+ilm_layerAddNotification(t_ilm_layer layer,
                              layerNotificationFunc callback)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
@@ -2570,16 +2415,14 @@ wayland_layerAddNotification(t_ilm_layer layer,
     return returnValue;
 }
 
-// TODO
-static ilmErrorTypes
-wayland_layerRemoveNotification(t_ilm_layer layer)
+ILM_EXPORT ilmErrorTypes
+ilm_layerRemoveNotification(t_ilm_layer layer)
 {
-   return wayland_layerAddNotification(layer, NULL);
+   return ilm_layerAddNotification(layer, NULL);
 }
 
-// TODO
-static ilmErrorTypes
-wayland_surfaceAddNotification(t_ilm_surface surface,
+ILM_EXPORT ilmErrorTypes
+ilm_surfaceAddNotification(t_ilm_surface surface,
                              surfaceNotificationFunc callback)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
@@ -2589,8 +2432,19 @@ wayland_surfaceAddNotification(t_ilm_surface surface,
     ctx_surf = (struct surface_context*)get_surface_context(
                     &ctx->wl, (uint32_t)surface);
     if (ctx_surf == NULL) {
+        if (callback != NULL) {
+            callback((uint32_t)surface, NULL, ILM_NOTIFICATION_CONTENT_REMOVED);
+            controller_listener_surface(ctx, ctx->wl.controller, (uint32_t)surface);
+            ctx_surf = (struct surface_context*)get_surface_context(
+                        &ctx->wl, (uint32_t)surface);
+            ctx_surf->is_surface_creation_noticed = false;
+        }
+    }
+
+    if (ctx_surf == NULL) {
         returnValue = ILM_ERROR_INVALID_ARGUMENTS;
-    } else {
+    }
+    else {
         ctx_surf->notification = callback;
 
         returnValue = ILM_SUCCESS;
@@ -2600,15 +2454,14 @@ wayland_surfaceAddNotification(t_ilm_surface surface,
     return returnValue;
 }
 
-// TODO
-static ilmErrorTypes
-wayland_surfaceRemoveNotification(t_ilm_surface surface)
+ILM_EXPORT ilmErrorTypes
+ilm_surfaceRemoveNotification(t_ilm_surface surface)
 {
-    return wayland_surfaceAddNotification(surface, NULL);
+    return ilm_surfaceAddNotification(surface, NULL);
 }
 
-static ilmErrorTypes
-wayland_getNativeHandle(t_ilm_uint pid, t_ilm_int *n_handle,
+ILM_EXPORT ilmErrorTypes
+ilm_getNativeHandle(t_ilm_uint pid, t_ilm_int *n_handle,
                         t_ilm_nativehandle **p_handles)
 {
     struct ilm_control_context *ctx = sync_and_acquire_instance();
@@ -2633,8 +2486,8 @@ wayland_getNativeHandle(t_ilm_uint pid, t_ilm_int *n_handle,
     return (*n_handle > 0) ? ILM_SUCCESS : ILM_FAILED;
 }
 
-static ilmErrorTypes
-wayland_getPropertiesOfSurface(t_ilm_uint surfaceID,
+ILM_EXPORT ilmErrorTypes
+ilm_getPropertiesOfSurface(t_ilm_uint surfaceID,
                         struct ilmSurfaceProperties* pSurfaceProperties)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
@@ -2655,8 +2508,8 @@ wayland_getPropertiesOfSurface(t_ilm_uint surfaceID,
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_layerAddSurface(t_ilm_layer layerId,
+ILM_EXPORT ilmErrorTypes
+ilm_layerAddSurface(t_ilm_layer layerId,
                         t_ilm_surface surfaceId)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
@@ -2677,8 +2530,8 @@ wayland_layerAddSurface(t_ilm_layer layerId,
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_layerRemoveSurface(t_ilm_layer layerId,
+ILM_EXPORT ilmErrorTypes
+ilm_layerRemoveSurface(t_ilm_layer layerId,
                            t_ilm_surface surfaceId)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
@@ -2699,8 +2552,8 @@ wayland_layerRemoveSurface(t_ilm_layer layerId,
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_surfaceGetDimension(t_ilm_surface surfaceId,
+ILM_EXPORT ilmErrorTypes
+ilm_surfaceGetDimension(t_ilm_surface surfaceId,
                             t_ilm_uint *pDimension)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
@@ -2721,8 +2574,8 @@ wayland_surfaceGetDimension(t_ilm_surface surfaceId,
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_surfaceGetVisibility(t_ilm_surface surfaceId,
+ILM_EXPORT ilmErrorTypes
+ilm_surfaceGetVisibility(t_ilm_surface surfaceId,
                              t_ilm_bool *pVisibility)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
@@ -2741,8 +2594,8 @@ wayland_surfaceGetVisibility(t_ilm_surface surfaceId,
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_surfaceSetSourceRectangle(t_ilm_surface surfaceId,
+ILM_EXPORT ilmErrorTypes
+ilm_surfaceSetSourceRectangle(t_ilm_surface surfaceId,
                                   t_ilm_int x, t_ilm_int y,
                                   t_ilm_int width, t_ilm_int height)
 {
@@ -2764,8 +2617,8 @@ wayland_surfaceSetSourceRectangle(t_ilm_surface surfaceId,
     return returnValue;
 }
 
-static ilmErrorTypes
-wayland_commitChanges(void)
+ILM_EXPORT ilmErrorTypes
+ilm_commitChanges(void)
 {
     ilmErrorTypes returnValue = ILM_FAILED;
     struct ilm_control_context *ctx = sync_and_acquire_instance();