e_policy/e_service: added policy system and tizen_ws_shell interfaces 52/81152/2
authorMinJeong Kim <minjjj.kim@samsung.com>
Fri, 22 Jul 2016 07:31:07 +0000 (16:31 +0900)
committerGwanglim Lee <gl77.lee@samsung.com>
Mon, 25 Jul 2016 13:34:25 +0000 (22:34 +0900)
Change-Id: Iad5fb635573d4d65aa2cd357be23a93794496833
Signed-off-by: MinJeong Kim <minjjj.kim@samsung.com>
31 files changed:
configure.ac
packaging/enlightenment.spec
src/bin/Makefile.mk
src/bin/e_includes.h
src/bin/e_main.c
src/bin/e_policy.c [new file with mode: 0644]
src/bin/e_policy.h [new file with mode: 0644]
src/bin/e_policy_conformant.c [new file with mode: 0644]
src/bin/e_policy_conformant.h [new file with mode: 0644]
src/bin/e_policy_keyboard.c [new file with mode: 0644]
src/bin/e_policy_keyboard.h [new file with mode: 0644]
src/bin/e_policy_private_data.h [new file with mode: 0644]
src/bin/e_policy_softkey.c [new file with mode: 0644]
src/bin/e_policy_stack.c [new file with mode: 0644]
src/bin/e_policy_transform_mode.c [new file with mode: 0644]
src/bin/e_policy_transform_mode.h [new file with mode: 0644]
src/bin/e_policy_visibility.c [new file with mode: 0644]
src/bin/e_policy_wl.c [new file with mode: 0644]
src/bin/e_policy_wl.h [new file with mode: 0644]
src/bin/e_policy_wl_display.c [new file with mode: 0644]
src/bin/e_policy_wl_display.h [new file with mode: 0644]
src/bin/services/e_service_gesture.c [new file with mode: 0644]
src/bin/services/e_service_gesture.h [new file with mode: 0644]
src/bin/services/e_service_lockscreen.c [new file with mode: 0644]
src/bin/services/e_service_lockscreen.h [new file with mode: 0644]
src/bin/services/e_service_quickpanel.c [new file with mode: 0644]
src/bin/services/e_service_quickpanel.h [new file with mode: 0644]
src/bin/services/e_service_region.c [new file with mode: 0644]
src/bin/services/e_service_region.h [new file with mode: 0644]
src/bin/services/e_service_volume.c [new file with mode: 0644]
src/bin/services/e_service_volume.h [new file with mode: 0644]

index 0d5ff97..74f7776 100755 (executable)
@@ -460,6 +460,27 @@ AM_CONDITIONAL([HAVE_WAYLAND], [test "x${have_wayland}" = "xyes"])
 AM_CONDITIONAL([HAVE_WAYLAND_TBM], [test "x${have_wayland_tbm}" = "xyes"])
 AM_CONDITIONAL([HAVE_HWC], [test "x${have_hwc}" = "xyes"])
 
+#capi-system-device
+PKG_CHECK_MODULES([CAPI_SYSTEM_DEVICE],
+                  [capi-system-device])
+#cynara
+PKG_CHECK_MODULES(CYNARA,
+                  [cynara-client, cynara-creds-socket, cynara-session],
+                  [have_cynara="yes"], [have_cynara="no"])
+if test "x${have_cynara}" = "xyes"; then
+    AC_DEFINE([HAVE_CYNARA], [1], [Define to 1 if you have cynara])
+fi
+
+#tzsh-server
+PKG_CHECK_MODULES(TZSH,
+                  [tzsh-server],
+                  [have_tzsh="yes"])
+
+POLICY_CFLAGS="${CAPI_SYSTEM_DEVICE_CFLAGS} ${CYNARA_CFLAGS} ${TZSH_CFLAGS}"
+POLICY_LIBS="${CAPI_SYSTEM_DEVICE_LIBS} ${CYNARA_LIBS} ${TZSH_LIBS}"
+AC_SUBST(POLICY_CFLAGS)
+AC_SUBST(POLICY_LIBS)
+
 WL_DESKTOP_SHELL=false
 define([CHECK_MODULE_WL_DESKTOP_SHELL],
 [
index 266e0ba..75a8ff9 100755 (executable)
@@ -34,6 +34,10 @@ BuildRequires:  pkgconfig(wayland-tbm-server)
 BuildRequires:  pkgconfig(ecore-drm)
 BuildRequires:  pkgconfig(libtdm)
 BuildRequires:  pkgconfig(gbm)
+BuildRequires:  pkgconfig(capi-system-device)
+BuildRequires:  pkgconfig(tzsh-server)
+BuildRequires:  pkgconfig(cynara-client)
+BuildRequires:  pkgconfig(cynara-creds-socket)
 Requires:       libwayland-extension-server
 
 %description
index da260f1..a4b8000 100644 (file)
@@ -93,6 +93,19 @@ ENLIGHTENMENTHEADERS += \
 src/bin/e_comp_wl_tbm.h
 endif
 
+ENLIGHTENMENTHEADERS += \
+src/bin/services/e_service_gesture.h \
+src/bin/services/e_service_lockscreen.h \
+src/bin/services/e_service_quickpanel.h \
+src/bin/services/e_service_region.h \
+src/bin/services/e_service_volume.h \
+src/bin/e_policy.h \
+src/bin/e_policy_keyboard.h \
+src/bin/e_policy_private_data.h \
+src/bin/e_policy_transform_mode.h \
+src/bin/e_policy_wl.h \
+src/bin/e_policy_wl_display.h
+
 enlightenment_src = \
 src/bin/e_actions.c \
 src/bin/e_bg.c \
@@ -166,7 +179,23 @@ enlightenment_src += \
 src/bin/e_comp_wl_tbm.c
 endif
 
-src_bin_enlightenment_CPPFLAGS = $(E_CPPFLAGS) -DEFL_BETA_API_SUPPORT -DEFL_EO_API_SUPPORT -DE_LOGGING=1 @WAYLAND_CFLAGS@ $(TTRACE_CFLAGS) $(DLOG_CFLAGS)
+enlightenment_src += \
+src/bin/services/e_service_gesture.c \
+src/bin/services/e_service_lockscreen.c \
+src/bin/services/e_service_quickpanel.c \
+src/bin/services/e_service_region.c \
+src/bin/services/e_service_volume.c \
+src/bin/e_policy.c \
+src/bin/e_policy_conformant.c \
+src/bin/e_policy_keyboard.c \
+src/bin/e_policy_softkey.c \
+src/bin/e_policy_stack.c  \
+src/bin/e_policy_transform_mode.c \
+src/bin/e_policy_visibility.c \
+src/bin/e_policy_wl.c \
+src/bin/e_policy_wl_display.c
+
+src_bin_enlightenment_CPPFLAGS = $(E_CPPFLAGS) -DEFL_BETA_API_SUPPORT -DEFL_EO_API_SUPPORT -DE_LOGGING=1 @WAYLAND_CFLAGS@ $(TTRACE_CFLAGS) $(DLOG_CFLAGS) $(POLICY_CFLAGS)
 if HAVE_WAYLAND_TBM
 src_bin_enlightenment_CPPFLAGS += @WAYLAND_TBM_CFLAGS@ @ECORE_DRM_CFLAGS@
 endif
@@ -179,7 +208,7 @@ src/bin/e_main.c \
 $(enlightenment_src)
 
 src_bin_enlightenment_LDFLAGS = -export-dynamic
-src_bin_enlightenment_LDADD = @e_libs@ @dlopen_libs@ @cf_libs@ @VALGRIND_LIBS@ @WAYLAND_LIBS@ -lm @SHM_OPEN_LIBS@ $(TTRACE_LIBS) $(DLOG_LIBS)
+src_bin_enlightenment_LDADD = @e_libs@ @dlopen_libs@ @cf_libs@ @VALGRIND_LIBS@ @WAYLAND_LIBS@ -lm @SHM_OPEN_LIBS@ $(TTRACE_LIBS) $(DLOG_LIBS) $(POLICY_LIBS)
 if HAVE_WAYLAND_TBM
 src_bin_enlightenment_LDADD += @WAYLAND_TBM_LIBS@ @ECORE_DRM_LIBS@
 endif
index b890392..7752281 100644 (file)
@@ -60,3 +60,4 @@
 #ifdef HAVE_WAYLAND_TBM
 # include "e_comp_wl_tbm.h"
 #endif
+#include "e_policy.h"
index bd7acf1..4dd01f7 100644 (file)
@@ -281,6 +281,16 @@ _e_main_subsystem_defer(void *data EINA_UNUSED)
    TS("[DEFERRED] Compositor's deferred job Done");
 
    TRACE_DS_END();
+   if (e_config->use_e_policy)
+     {
+        TRACE_DS_BEGIN(MAIN:DEFERRED POLICY JOB);
+
+        TS("[DEFERRED] E_Policy's deferred job");
+        e_policy_deferred_job();
+        TS("[DEFERRED] E_Policy's deferred job Done");
+
+        TRACE_DS_END();
+     }
    TRACE_DS_BEGIN(MAIN:DEFERRED MODULE JOB);
 
    TS("[DEFERRED] E_Module's deferred job");
@@ -661,6 +671,18 @@ main(int argc, char **argv)
    TS("E_Icon Init Done");
    _e_main_shutdown_push(e_icon_shutdown);
 
+   if (e_config->use_e_policy)
+     {
+        TS("E_Policy Init");
+        if (!e_policy_init())
+          {
+             e_error_message_show(_("Enlightenment cannot setup policy system!\n"));
+             _e_main_shutdown(-1);
+          }
+        TS("E_Policy Init Done");
+        _e_main_shutdown_push(e_policy_shutdown);
+     }
+
    TS("Load Modules");
    _e_main_modules_load(safe_mode);
    TS("Load Modules Done");
diff --git a/src/bin/e_policy.c b/src/bin/e_policy.c
new file mode 100644 (file)
index 0000000..382b1a0
--- /dev/null
@@ -0,0 +1,1409 @@
+#include "e.h"
+#include "e_policy_keyboard.h"
+#include "e_policy_transform_mode.h"
+#include "e_policy_conformant.h"
+#include "e_policy_wl.h"
+
+E_Policy *e_policy = NULL;
+Eina_Hash *hash_policy_desks = NULL;
+Eina_Hash *hash_policy_clients = NULL;
+E_Policy_System_Info e_policy_system_info =
+{
+   {NULL, EINA_FALSE},
+   { -1, -1, EINA_FALSE}
+};
+
+static Eina_List *handlers = NULL;
+static Eina_List *hooks_ec = NULL;
+static Eina_List *hooks_cp = NULL;
+
+static E_Policy_Client *_e_policy_client_add(E_Client *ec);
+static void        _e_policy_client_del(E_Policy_Client *pc);
+static Eina_Bool   _e_policy_client_normal_check(E_Client *ec);
+static Eina_Bool   _e_policy_client_maximize_policy_apply(E_Policy_Client *pc);
+static void        _e_policy_client_maximize_policy_cancel(E_Policy_Client *pc);
+static void        _e_policy_client_floating_policy_apply(E_Policy_Client *pc);
+static void        _e_policy_client_floating_policy_cancel(E_Policy_Client *pc);
+static void        _e_policy_client_launcher_set(E_Policy_Client *pc);
+
+static void        _e_policy_cb_hook_client_eval_pre_new_client(void *d EINA_UNUSED, E_Client *ec);
+static void        _e_policy_cb_hook_client_eval_pre_fetch(void *d EINA_UNUSED, E_Client *ec);
+static void        _e_policy_cb_hook_client_eval_pre_post_fetch(void *d EINA_UNUSED, E_Client *ec);
+static void        _e_policy_cb_hook_client_eval_post_fetch(void *d EINA_UNUSED, E_Client *ec);
+static void        _e_policy_cb_hook_client_eval_post_new_client(void *d EINA_UNUSED, E_Client *ec);
+static void        _e_policy_cb_hook_client_desk_set(void *d EINA_UNUSED, E_Client *ec);
+static void        _e_policy_cb_hook_client_fullscreen_pre(void *data EINA_UNUSED, E_Client *ec);
+
+static void        _e_policy_cb_hook_pixmap_del(void *data EINA_UNUSED, E_Pixmap *cp);
+static void        _e_policy_cb_hook_pixmap_unusable(void *data EINA_UNUSED, E_Pixmap *cp);
+
+static void        _e_policy_cb_desk_data_free(void *data);
+static void        _e_policy_cb_client_data_free(void *data);
+static Eina_Bool   _e_policy_cb_zone_add(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
+static Eina_Bool   _e_policy_cb_zone_del(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
+static Eina_Bool   _e_policy_cb_zone_move_resize(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
+static Eina_Bool   _e_policy_cb_zone_desk_count_set(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
+static Eina_Bool   _e_policy_cb_zone_display_state_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
+static Eina_Bool   _e_policy_cb_desk_show(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
+static Eina_Bool   _e_policy_cb_client_add(void *data EINA_UNUSED, int type, void *event);
+static Eina_Bool   _e_policy_cb_client_move(void *data EINA_UNUSED, int type, void *event);
+static Eina_Bool   _e_policy_cb_client_resize(void *data EINA_UNUSED, int type, void *event);
+static Eina_Bool   _e_policy_cb_client_stack(void *data EINA_UNUSED, int type, void *event);
+static Eina_Bool   _e_policy_cb_client_property(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
+static Eina_Bool   _e_policy_cb_client_vis_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED);
+
+static void
+_e_policy_client_launcher_set(E_Policy_Client *pc)
+{
+   E_Policy_Client *pc2;
+
+   pc2 = e_policy_client_launcher_get(pc->ec->zone);
+   if (pc2) return;
+
+   if (pc->ec->netwm.type != e_config->launcher.type)
+     return;
+
+   if (e_util_strcmp(pc->ec->icccm.class,
+                     e_config->launcher.clas))
+     return;
+
+
+   if (e_util_strcmp(pc->ec->icccm.title,
+                     e_config->launcher.title))
+     {
+        /* check netwm name instead, because comp_x had ignored
+         * icccm name when fetching */
+        if (e_util_strcmp(pc->ec->netwm.name,
+                          e_config->launcher.title))
+          {
+             return;
+          }
+     }
+
+   e_policy->launchers = eina_list_append(e_policy->launchers, pc);
+}
+
+static E_Policy_Client *
+_e_policy_client_add(E_Client *ec)
+{
+   E_Policy_Client *pc;
+
+   if (e_object_is_del(E_OBJECT(ec))) return NULL;
+
+   pc = eina_hash_find(hash_policy_clients, &ec);
+   if (pc) return NULL;
+
+   pc = E_NEW(E_Policy_Client, 1);
+   pc->ec = ec;
+
+   eina_hash_add(hash_policy_clients, &ec, pc);
+
+   return pc;
+}
+
+static void
+_e_policy_client_del(E_Policy_Client *pc)
+{
+   eina_hash_del_by_key(hash_policy_clients, &pc->ec);
+}
+
+static Eina_Bool
+_e_policy_client_normal_check(E_Client *ec)
+{
+   E_Policy_Client *pc;
+
+   if ((e_client_util_ignored_get(ec)) ||
+       (!ec->pixmap))
+     {
+        return EINA_FALSE;
+     }
+
+   if (e_policy_client_is_quickpanel(ec))
+     {
+        return EINA_FALSE;
+     }
+
+   if (e_policy_client_is_keyboard(ec) ||
+       e_policy_client_is_keyboard_sub(ec))
+     {
+        e_policy_keyboard_layout_apply(ec);
+        goto cancel_max;
+     }
+   else if (e_policy_client_is_volume_tv(ec))
+     goto cancel_max;
+   else if (!e_util_strcmp("e_demo", ec->icccm.window_role))
+     goto cancel_max;
+   else if (e_policy_client_is_floating(ec))
+     {
+        pc = eina_hash_find(hash_policy_clients, &ec);
+        _e_policy_client_maximize_policy_cancel(pc);
+        _e_policy_client_floating_policy_apply(pc);
+        return EINA_FALSE;
+     }
+   else if (e_policy_client_is_subsurface(ec))
+     goto cancel_max;
+
+   if ((ec->netwm.type == E_WINDOW_TYPE_NORMAL) ||
+       (ec->netwm.type == E_WINDOW_TYPE_UNKNOWN) ||
+       (ec->netwm.type == E_WINDOW_TYPE_NOTIFICATION))
+     {
+        return EINA_TRUE;
+     }
+
+   return EINA_FALSE;
+
+cancel_max:
+   pc = eina_hash_find(hash_policy_clients, &ec);
+   _e_policy_client_maximize_policy_cancel(pc);
+
+   return EINA_FALSE;
+}
+
+static void
+_e_policy_client_maximize_pre(E_Policy_Client *pc)
+{
+   E_Client *ec;
+   int zx, zy, zw, zh;
+
+   ec = pc->ec;
+
+   if (ec->desk->visible)
+     e_zone_useful_geometry_get(ec->zone, &zx, &zy, &zw, &zh);
+   else
+     {
+        zx = ec->zone->x;
+        zy = ec->zone->y;
+        zw = ec->zone->w;
+        zh = ec->zone->h;
+     }
+
+   ec->x = ec->client.x = zx;
+   ec->y = ec->client.y = zy;
+   ec->w = ec->client.w = zw;
+   ec->h = ec->client.h = zh;
+
+   EC_CHANGED(ec);
+}
+
+static Eina_Bool
+_e_policy_client_maximize_policy_apply(E_Policy_Client *pc)
+{
+   E_Client *ec;
+
+   if (!pc) return EINA_FALSE;
+   if (pc->max_policy_state) return EINA_FALSE;
+   if (pc->allow_user_geom) return EINA_FALSE;
+
+   ec = pc->ec;
+   if (ec->netwm.type == E_WINDOW_TYPE_UTILITY) return EINA_FALSE;
+
+   pc->max_policy_state = EINA_TRUE;
+
+#undef _SET
+# define _SET(a) pc->orig.a = pc->ec->a
+   _SET(borderless);
+   _SET(fullscreen);
+   _SET(maximized);
+   _SET(lock_user_location);
+   _SET(lock_client_location);
+   _SET(lock_user_size);
+   _SET(lock_client_size);
+   _SET(lock_client_stacking);
+   _SET(lock_user_shade);
+   _SET(lock_client_shade);
+   _SET(lock_user_maximize);
+   _SET(lock_client_maximize);
+   _SET(lock_user_fullscreen);
+   _SET(lock_client_fullscreen);
+#undef _SET
+
+   _e_policy_client_launcher_set(pc);
+
+   if (ec->remember)
+     {
+        e_remember_del(ec->remember);
+        ec->remember = NULL;
+     }
+
+   /* skip hooks of e_remeber for eval_pre_post_fetch and eval_post_new_client */
+   ec->internal_no_remember = 1;
+
+   if (!ec->borderless)
+     {
+        ec->borderless = 1;
+        ec->border.changed = 1;
+        EC_CHANGED(pc->ec);
+     }
+
+   if (!ec->maximized)
+     {
+        e_client_maximize(ec, E_MAXIMIZE_EXPAND | E_MAXIMIZE_BOTH);
+
+        if (ec->changes.need_maximize)
+          _e_policy_client_maximize_pre(pc);
+     }
+
+   /* do not allow client to change these properties */
+   ec->lock_user_location = 1;
+   ec->lock_client_location = 1;
+   ec->lock_user_size = 1;
+   ec->lock_client_size = 1;
+   ec->lock_user_shade = 1;
+   ec->lock_client_shade = 1;
+   ec->lock_user_maximize = 1;
+   ec->lock_client_maximize = 1;
+   ec->lock_user_fullscreen = 1;
+   ec->lock_client_fullscreen = 1;
+   ec->skip_fullscreen = 1;
+
+   if (!e_policy_client_is_home_screen(ec))
+     ec->lock_client_stacking = 1;
+
+   return EINA_TRUE;
+}
+
+static void
+_e_policy_client_maximize_policy_cancel(E_Policy_Client *pc)
+{
+   E_Client *ec;
+   Eina_Bool changed = EINA_FALSE;
+
+   if (!pc) return;
+   if (!pc->max_policy_state) return;
+
+   pc->max_policy_state = EINA_FALSE;
+
+   ec = pc->ec;
+
+   if (pc->orig.borderless != ec->borderless)
+     {
+        ec->border.changed = 1;
+        changed = EINA_TRUE;
+     }
+
+   if ((pc->orig.fullscreen != ec->fullscreen) &&
+       (pc->orig.fullscreen))
+     {
+        ec->need_fullscreen = 1;
+        changed = EINA_TRUE;
+     }
+
+   if (pc->orig.maximized != ec->maximized)
+     {
+        if (pc->orig.maximized)
+          ec->changes.need_maximize = 1;
+        else
+          e_client_unmaximize(ec, ec->maximized);
+
+        changed = EINA_TRUE;
+     }
+
+#undef _SET
+# define _SET(a) ec->a = pc->orig.a
+   _SET(borderless);
+   _SET(fullscreen);
+   _SET(maximized);
+   _SET(lock_user_location);
+   _SET(lock_client_location);
+   _SET(lock_user_size);
+   _SET(lock_client_size);
+   _SET(lock_client_stacking);
+   _SET(lock_user_shade);
+   _SET(lock_client_shade);
+   _SET(lock_user_maximize);
+   _SET(lock_client_maximize);
+   _SET(lock_user_fullscreen);
+   _SET(lock_client_fullscreen);
+#undef _SET
+
+   ec->skip_fullscreen = 0;
+
+   /* only set it if the border is changed or fullscreen/maximize has changed */
+   if (changed)
+     EC_CHANGED(pc->ec);
+
+   e_policy->launchers = eina_list_remove(e_policy->launchers, pc);
+}
+
+static void
+_e_policy_client_floating_policy_apply(E_Policy_Client *pc)
+{
+   E_Client *ec;
+
+   if (!pc) return;
+   if (pc->flt_policy_state) return;
+
+   pc->flt_policy_state = EINA_TRUE;
+   ec = pc->ec;
+
+#undef _SET
+# define _SET(a) pc->orig.a = pc->ec->a
+   _SET(fullscreen);
+   _SET(lock_client_stacking);
+   _SET(lock_user_shade);
+   _SET(lock_client_shade);
+   _SET(lock_user_maximize);
+   _SET(lock_client_maximize);
+   _SET(lock_user_fullscreen);
+   _SET(lock_client_fullscreen);
+#undef _SET
+
+   ec->skip_fullscreen = 1;
+   ec->lock_client_stacking = 1;
+   ec->lock_user_shade = 1;
+   ec->lock_client_shade = 1;
+   ec->lock_user_maximize = 1;
+   ec->lock_client_maximize = 1;
+   ec->lock_user_fullscreen = 1;
+   ec->lock_client_fullscreen = 1;
+}
+
+static void
+_e_policy_client_floating_policy_cancel(E_Policy_Client *pc)
+{
+   E_Client *ec;
+   Eina_Bool changed = EINA_FALSE;
+
+   if (!pc) return;
+   if (!pc->flt_policy_state) return;
+
+   pc->flt_policy_state = EINA_FALSE;
+   ec = pc->ec;
+
+   if ((pc->orig.fullscreen != ec->fullscreen) &&
+       (pc->orig.fullscreen))
+     {
+        ec->need_fullscreen = 1;
+        changed = EINA_TRUE;
+     }
+
+   if (pc->orig.maximized != ec->maximized)
+     {
+        if (pc->orig.maximized)
+          ec->changes.need_maximize = 1;
+        else
+          e_client_unmaximize(ec, ec->maximized);
+
+        changed = EINA_TRUE;
+     }
+
+   ec->skip_fullscreen = 0;
+
+#undef _SET
+# define _SET(a) ec->a = pc->orig.a
+   _SET(fullscreen);
+   _SET(lock_client_stacking);
+   _SET(lock_user_shade);
+   _SET(lock_client_shade);
+   _SET(lock_user_maximize);
+   _SET(lock_client_maximize);
+   _SET(lock_user_fullscreen);
+   _SET(lock_client_fullscreen);
+#undef _SET
+
+   if (changed)
+     EC_CHANGED(pc->ec);
+}
+
+E_Config_Policy_Desk *
+_e_policy_desk_get_by_num(unsigned int zone_num, int x, int y)
+{
+   Eina_List *l;
+   E_Config_Policy_Desk *d2;
+
+   EINA_LIST_FOREACH(e_config->policy_desks, l, d2)
+     {
+        if ((d2->zone_num == zone_num) &&
+            (d2->x == x) && (d2->y == y))
+          {
+             return d2;
+          }
+     }
+
+   return NULL;
+}
+
+
+static void
+_e_policy_cb_hook_client_new(void *d EINA_UNUSED, E_Client *ec)
+{
+   if (EINA_UNLIKELY(!ec))
+     return;
+
+   _e_policy_client_add(ec);
+}
+
+static void
+_e_policy_cb_hook_client_del(void *d EINA_UNUSED, E_Client *ec)
+{
+   E_Policy_Client *pc;
+
+   if (EINA_UNLIKELY(!ec))
+     return;
+
+   e_policy_wl_win_brightness_apply(ec);
+   e_policy_wl_client_del(ec);
+
+   if (e_policy_client_is_lockscreen(ec))
+     e_policy_stack_clients_restack_above_lockscreen(ec, EINA_FALSE);
+
+   e_policy_stack_cb_client_remove(ec);
+   e_client_visibility_calculate();
+
+   pc = eina_hash_find(hash_policy_clients, &ec);
+   _e_policy_client_del(pc);
+}
+
+static void
+_e_policy_cb_hook_client_eval_pre_new_client(void *d EINA_UNUSED, E_Client *ec)
+{
+   short ly;
+
+   if (e_object_is_del(E_OBJECT(ec))) return;
+
+   if (e_policy_client_is_keyboard_sub(ec))
+     {
+        ec->placed = 1;
+        ec->exp_iconify.skip_iconify = EINA_TRUE;
+
+        EINA_SAFETY_ON_NULL_RETURN(ec->frame);
+        if (ec->layer != E_LAYER_CLIENT_ABOVE)
+          evas_object_layer_set(ec->frame, E_LAYER_CLIENT_ABOVE);
+     }
+   if (e_policy_client_is_noti(ec))
+     {
+        if (ec->frame)
+          {
+             ly = evas_object_layer_get(ec->frame);
+             ELOGF("NOTI", "         |ec->layer:%d object->layer:%d", ec->pixmap, ec, ec->layer, ly);
+             if (ly != ec->layer)
+               evas_object_layer_set(ec->frame, ec->layer);
+          }
+     }
+   if (e_policy_client_is_floating(ec))
+     {
+        if (ec->frame)
+          {
+             if (ec->layer != E_LAYER_CLIENT_ABOVE)
+               evas_object_layer_set(ec->frame, E_LAYER_CLIENT_ABOVE);
+          }
+     }
+}
+
+static void
+_e_policy_cb_hook_client_eval_pre_fetch(void *d EINA_UNUSED, E_Client *ec)
+{
+   if (e_object_is_del(E_OBJECT(ec))) return;
+
+   e_policy_stack_hook_pre_fetch(ec);
+}
+
+static void
+_e_policy_cb_hook_client_eval_pre_post_fetch(void *d EINA_UNUSED, E_Client *ec)
+{
+   if (e_object_is_del(E_OBJECT(ec))) return;
+
+   e_policy_stack_hook_pre_post_fetch(ec);
+   e_policy_wl_notification_level_fetch(ec);
+   e_policy_wl_eval_pre_post_fetch(ec);
+}
+
+static void
+_e_policy_cb_hook_client_eval_post_fetch(void *d EINA_UNUSED, E_Client *ec)
+{
+   E_Policy_Client *pc;
+   E_Policy_Desk *pd;
+
+   if (e_object_is_del(E_OBJECT(ec))) return;
+   /* Following E_Clients will be added to module hash and will be managed.
+    *
+    *  - Not new client: Updating internal info of E_Client has been finished
+    *    by e main evaluation, thus module can classify E_Client and manage it.
+    *
+    *  - New client that has valid buffer: This E_Client has been passed e main
+    *    evaluation, and it has handled first wl_surface::commit request.
+    */
+   if ((ec->new_client) && (!e_pixmap_usable_get(ec->pixmap))) return;
+
+   if (e_policy_client_is_keyboard(ec) ||
+       e_policy_client_is_keyboard_sub(ec))
+     {
+        E_Policy_Client *pc;
+        pc = eina_hash_find(hash_policy_clients, &ec);
+        _e_policy_client_maximize_policy_cancel(pc);
+
+        e_policy_keyboard_layout_apply(ec);
+     }
+
+   if (!e_util_strcmp("wl_pointer-cursor", ec->icccm.window_role))
+     {
+        E_Policy_Client *pc;
+        pc = eina_hash_find(hash_policy_clients, &ec);
+        _e_policy_client_maximize_policy_cancel(pc);
+        return;
+     }
+
+   if (e_policy_client_is_floating(ec))
+     {
+        E_Policy_Client *pc;
+        pc = eina_hash_find(hash_policy_clients, &ec);
+        _e_policy_client_maximize_policy_cancel(pc);
+        _e_policy_client_floating_policy_apply(pc);
+        return;
+     }
+
+   if (!_e_policy_client_normal_check(ec)) return;
+
+   pd = eina_hash_find(hash_policy_desks, &ec->desk);
+   if (!pd) return;
+
+   pc = eina_hash_find(hash_policy_clients, &ec);
+   if (!pc) return;
+
+   if (pc->flt_policy_state)
+     _e_policy_client_floating_policy_cancel(pc);
+
+   _e_policy_client_maximize_policy_apply(pc);
+}
+
+static void
+_e_policy_cb_hook_client_eval_post_new_client(void *d EINA_UNUSED, E_Client *ec)
+{
+   if (e_object_is_del(E_OBJECT(ec))) return;
+   if ((ec->new_client) && (!e_pixmap_usable_get(ec->pixmap))) return;
+
+   if (e_policy_client_is_lockscreen(ec))
+     e_policy_stack_clients_restack_above_lockscreen(ec, EINA_TRUE);
+}
+
+static void
+_e_policy_cb_hook_client_desk_set(void *d EINA_UNUSED, E_Client *ec)
+{
+   E_Policy_Client *pc;
+   E_Policy_Desk *pd;
+
+   if (e_object_is_del(E_OBJECT(ec))) return;
+   if (!_e_policy_client_normal_check(ec)) return;
+   if (ec->internal) return;
+   if (ec->new_client) return;
+
+   pc = eina_hash_find(hash_policy_clients, &ec);
+   if (EINA_UNLIKELY(!pc))
+     return;
+
+   pd = eina_hash_find(hash_policy_desks, &ec->desk);
+
+   if (pd)
+     _e_policy_client_maximize_policy_apply(pc);
+   else
+     _e_policy_client_maximize_policy_cancel(pc);
+}
+
+static void
+_e_policy_cb_hook_client_fullscreen_pre(void* data EINA_UNUSED, E_Client *ec)
+{
+   if (e_object_is_del(E_OBJECT(ec))) return;
+   if (!_e_policy_client_normal_check(ec)) return;
+   if (ec->internal) return;
+
+   ec->skip_fullscreen = 1;
+}
+
+static void
+_e_policy_cb_hook_client_visibility(void *d EINA_UNUSED, E_Client *ec)
+{
+   if (ec->visibility.changed)
+     {
+        e_policy_client_visibility_send(ec);
+
+        if (ec->visibility.obscured == E_VISIBILITY_UNOBSCURED)
+          {
+             e_policy_client_uniconify_by_visibility(ec);
+          }
+        else
+          {
+             e_policy_client_iconify_by_visibility(ec);
+          }
+
+        e_policy_wl_win_brightness_apply(ec);
+     }
+   else
+     {
+        if (ec->visibility.obscured == E_VISIBILITY_FULLY_OBSCURED)
+          {
+             Eina_Bool obscured_by_alpha_opaque = EINA_FALSE;
+             Eina_Bool find_above = EINA_FALSE;
+             E_Client *above_ec;
+             Evas_Object *o;
+
+             if (ec->zone->display_state == E_ZONE_DISPLAY_STATE_ON)
+               {
+                  for (o = evas_object_above_get(ec->frame); o; o = evas_object_above_get(o))
+                    {
+                       above_ec = evas_object_data_get(o, "E_Client");
+                       if (!above_ec) continue;
+                       if (e_client_util_ignored_get(above_ec)) continue;
+
+                       if (above_ec->exp_iconify.by_client) continue;
+                       if (above_ec->exp_iconify.skip_iconify) continue;
+
+                       if (!above_ec->iconic)
+                         {
+                            if (above_ec->argb && (above_ec->visibility.opaque > 0))
+                              obscured_by_alpha_opaque = EINA_TRUE;
+                         }
+                       find_above = EINA_TRUE;
+                       break;
+                    }
+
+                  if (!find_above) return;
+                  if (obscured_by_alpha_opaque)
+                    {
+                       e_policy_client_uniconify_by_visibility(ec);
+                    }
+                  else
+                    {
+                       e_policy_client_iconify_by_visibility(ec);
+                    }
+               }
+             else if (ec->zone->display_state == E_ZONE_DISPLAY_STATE_OFF)
+               {
+                  if (e_client_util_ignored_get(ec)) return;
+                  if (ec->exp_iconify.by_client) return;
+                  if (ec->exp_iconify.skip_iconify) return;
+                  if (!ec->iconic)
+                    {
+                       e_policy_client_iconify_by_visibility(ec);
+                    }
+               }
+          }
+     }
+}
+
+static void
+_e_policy_cb_hook_pixmap_del(void *data EINA_UNUSED, E_Pixmap *cp)
+{
+   e_policy_wl_pixmap_del(cp);
+}
+
+static void
+_e_policy_cb_hook_pixmap_unusable(void *data EINA_UNUSED, E_Pixmap *cp)
+{
+   E_Client *ec = (E_Client *)e_pixmap_client_get(cp);
+
+   if (!ec) return;
+   if (!ec->iconic) return;
+   if (ec->exp_iconify.by_client) return;
+   if (ec->exp_iconify.skip_iconify) return;
+
+   ec->exp_iconify.not_raise = 1;
+   e_client_uniconify(ec);
+   e_policy_wl_iconify_state_change_send(ec, 0);
+}
+
+static void
+_e_policy_cb_desk_data_free(void *data)
+{
+   free(data);
+}
+
+static void
+_e_policy_cb_client_data_free(void *data)
+{
+   free(data);
+}
+
+static Eina_Bool
+_e_policy_cb_zone_add(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+   E_Event_Zone_Add *ev;
+   E_Zone *zone;
+   E_Config_Policy_Desk *d;
+   int i, n;
+
+   ev = event;
+   zone = ev->zone;
+   n = zone->desk_y_count * zone->desk_x_count;
+   for (i = 0; i < n; i++)
+     {
+        d = _e_policy_desk_get_by_num(zone->num,
+                                      zone->desks[i]->x,
+                                      zone->desks[i]->y);
+        if (d)
+          e_policy_desk_add(zone->desks[i]);
+     }
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_policy_cb_zone_del(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+   E_Event_Zone_Del *ev;
+   E_Zone *zone;
+   E_Policy_Desk *pd;
+   int i, n;
+
+   ev = event;
+   zone = ev->zone;
+   n = zone->desk_y_count * zone->desk_x_count;
+   for (i = 0; i < n; i++)
+     {
+        pd = eina_hash_find(hash_policy_desks, &zone->desks[i]);
+        if (pd) e_policy_desk_del(pd);
+     }
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_policy_cb_zone_move_resize(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+   E_Event_Zone_Move_Resize *ev;
+   E_Policy_Softkey *softkey;
+
+   ev = event;
+
+   if (e_config->use_softkey)
+     {
+        softkey = e_policy_softkey_get(ev->zone);
+        e_policy_softkey_update(softkey);
+     }
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_policy_cb_zone_desk_count_set(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+   E_Event_Zone_Desk_Count_Set *ev;
+   E_Zone *zone;
+   E_Desk *desk;
+   Eina_Iterator *it;
+   E_Policy_Desk *pd;
+   E_Config_Policy_Desk *d;
+   int i, n;
+   Eina_Bool found;
+   Eina_List *desks_del = NULL;
+
+   ev = event;
+   zone = ev->zone;
+
+   /* remove deleted desk from hash */
+   it = eina_hash_iterator_data_new(hash_policy_desks);
+   while (eina_iterator_next(it, (void **)&pd))
+     {
+        if (pd->zone != zone) continue;
+
+        found = EINA_FALSE;
+        n = zone->desk_y_count * zone->desk_x_count;
+        for (i = 0; i < n; i++)
+          {
+             if (pd->desk == zone->desks[i])
+               {
+                  found = EINA_TRUE;
+                  break;
+               }
+          }
+        if (!found)
+          desks_del = eina_list_append(desks_del, pd->desk);
+     }
+   eina_iterator_free(it);
+
+   EINA_LIST_FREE(desks_del, desk)
+     {
+        pd = eina_hash_find(hash_policy_desks, &desk);
+        if (pd) e_policy_desk_del(pd);
+     }
+
+   /* add newly added desk to hash */
+   n = zone->desk_y_count * zone->desk_x_count;
+   for (i = 0; i < n; i++)
+     {
+        d = _e_policy_desk_get_by_num(zone->num,
+                                      zone->desks[i]->x,
+                                      zone->desks[i]->y);
+        if (d)
+          e_policy_desk_add(zone->desks[i]);
+     }
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_policy_cb_zone_display_state_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+   E_Event_Zone_Display_State_Change *ev;
+
+   ev = event;
+   if (!ev) return ECORE_CALLBACK_PASS_ON;
+
+   e_client_visibility_calculate();
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_policy_cb_desk_show(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+   E_Event_Desk_Show *ev;
+   E_Policy_Softkey *softkey;
+
+   ev = event;
+
+   if (e_config->use_softkey)
+     {
+        softkey = e_policy_softkey_get(ev->desk->zone);
+        if (eina_hash_find(hash_policy_desks, &ev->desk))
+          e_policy_softkey_show(softkey);
+        else
+          e_policy_softkey_hide(softkey);
+     }
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_policy_cb_client_add(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+   E_Event_Client *ev;
+
+   ev = event;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
+
+   e_policy_wl_client_add(ev->ec);
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_policy_cb_client_move(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+   E_Event_Client *ev;
+
+   ev = event;
+   if (!ev) goto end;
+
+   e_policy_wl_position_send(ev->ec);
+   e_client_visibility_calculate();
+
+end:
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_policy_cb_client_resize(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+   E_Event_Client *ev;
+   E_Client *ec;
+   int zh = 0;
+
+   ev = (E_Event_Client *)event;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
+
+   ec = ev->ec;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, ECORE_CALLBACK_PASS_ON);
+
+   /* re-calculate window's position with changed size */
+   if (e_policy_client_is_volume_tv(ec))
+     {
+        e_zone_useful_geometry_get(ec->zone, NULL, NULL, NULL, &zh);
+        evas_object_move(ec->frame, 0, (zh / 2) - (ec->h / 2));
+
+        evas_object_pass_events_set(ec->frame, 1);
+     }
+
+   /* calculate e_client visibility */
+   e_client_visibility_calculate();
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_policy_cb_client_stack(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+   E_Event_Client *ev;
+
+   ev = event;
+   if (!ev) return ECORE_CALLBACK_PASS_ON;
+   /* calculate e_client visibility */
+   e_client_visibility_calculate();
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_policy_cb_client_property(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+   E_Event_Client_Property *ev;
+
+   ev = event;
+   if (!ev || (!ev->ec)) return ECORE_CALLBACK_PASS_ON;
+   if (ev->property & E_CLIENT_PROPERTY_CLIENT_TYPE)
+     {
+        if (e_policy_client_is_home_screen(ev->ec))
+          {
+             ev->ec->lock_client_stacking = 0;
+             return ECORE_CALLBACK_PASS_ON;
+          }
+        else if (e_policy_client_is_lockscreen(ev->ec))
+          return ECORE_CALLBACK_PASS_ON;
+     }
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_policy_cb_client_vis_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
+{
+   e_policy_wl_win_scrmode_apply();
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+void
+e_policy_allow_user_geometry_set(E_Client *ec, Eina_Bool set)
+{
+   E_Policy_Client *pc;
+
+   if (EINA_UNLIKELY(!ec))
+     return;
+
+   pc = eina_hash_find(hash_policy_clients, &ec);
+   if (EINA_UNLIKELY(!pc))
+     return;
+
+   if (set) pc->user_geom_ref++;
+   else     pc->user_geom_ref--;
+
+   if (pc->user_geom_ref == 1 && !pc->allow_user_geom)
+     {
+        pc->allow_user_geom = EINA_TRUE;
+
+        if (!e_policy_client_is_noti(ec))
+          {
+             ec->netwm.type = E_WINDOW_TYPE_UTILITY;
+             ec->lock_client_location = EINA_FALSE;
+          }
+
+        ec->lock_client_size = EINA_FALSE;
+        ec->placed = 1;
+        EC_CHANGED(ec);
+     }
+   else if (pc->user_geom_ref == 0 && pc->allow_user_geom)
+     {
+        pc->allow_user_geom = EINA_FALSE;
+
+        ec->lock_client_location = EINA_TRUE;
+        ec->lock_client_size = EINA_TRUE;
+        ec->placed = 0;
+        ec->netwm.type = E_WINDOW_TYPE_NORMAL;
+        EC_CHANGED(ec);
+     }
+}
+
+void
+e_policy_desk_add(E_Desk *desk)
+{
+   E_Policy_Desk *pd;
+   E_Client *ec;
+   E_Policy_Softkey *softkey;
+   E_Policy_Client *pc;
+
+   pd = eina_hash_find(hash_policy_desks, &desk);
+   if (pd) return;
+
+   pd = E_NEW(E_Policy_Desk, 1);
+   pd->desk = desk;
+   pd->zone = desk->zone;
+
+   eina_hash_add(hash_policy_desks, &desk, pd);
+
+   /* add clients */
+   E_CLIENT_FOREACH(ec)
+     {
+       if (pd->desk == ec->desk)
+         {
+            pc = eina_hash_find(hash_policy_clients, &ec);
+            _e_policy_client_maximize_policy_apply(pc);
+         }
+     }
+
+   /* add and show softkey */
+   if (e_config->use_softkey)
+     {
+        softkey = e_policy_softkey_get(desk->zone);
+        if (!softkey)
+          softkey = e_policy_softkey_add(desk->zone);
+        if (e_desk_current_get(desk->zone) == desk)
+          e_policy_softkey_show(softkey);
+     }
+}
+
+void
+e_policy_desk_del(E_Policy_Desk *pd)
+{
+   Eina_Iterator *it;
+   E_Policy_Client *pc;
+   E_Client *ec;
+   Eina_List *clients_del = NULL;
+   E_Policy_Softkey *softkey;
+   Eina_Bool keep = EINA_FALSE;
+   int i, n;
+
+   /* hide and delete softkey */
+   if (e_config->use_softkey)
+     {
+        softkey = e_policy_softkey_get(pd->zone);
+        if (e_desk_current_get(pd->zone) == pd->desk)
+          e_policy_softkey_hide(softkey);
+
+        n = pd->zone->desk_y_count * pd->zone->desk_x_count;
+        for (i = 0; i < n; i++)
+          {
+             if (eina_hash_find(hash_policy_desks, &pd->zone->desks[i]))
+               {
+                  keep = EINA_TRUE;
+                  break;
+               }
+          }
+
+        if (!keep)
+          e_policy_softkey_del(softkey);
+     }
+
+   /* remove clients */
+   it = eina_hash_iterator_data_new(hash_policy_clients);
+   while (eina_iterator_next(it, (void **)&pc))
+     {
+        if (pc->ec->desk == pd->desk)
+          clients_del = eina_list_append(clients_del, pc->ec);
+     }
+   eina_iterator_free(it);
+
+   EINA_LIST_FREE(clients_del, ec)
+     {
+        pc = eina_hash_find(hash_policy_clients, &ec);
+        _e_policy_client_maximize_policy_cancel(pc);
+     }
+
+   eina_hash_del_by_key(hash_policy_desks, &pd->desk);
+}
+
+E_Policy_Client *
+e_policy_client_launcher_get(E_Zone *zone)
+{
+   E_Policy_Client *pc;
+   Eina_List *l;
+
+   EINA_LIST_FOREACH(e_policy->launchers, l, pc)
+     {
+        if (pc->ec->zone == zone)
+          return pc;
+     }
+   return NULL;
+}
+
+Eina_Bool
+e_policy_client_maximize(E_Client *ec)
+{
+   E_Policy_Desk *pd;
+   E_Policy_Client *pc;
+
+   E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
+   E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
+
+   if (EINA_UNLIKELY(!ec))  return EINA_FALSE;
+   if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
+
+   if ((e_policy_client_is_keyboard(ec)) ||
+       (e_policy_client_is_keyboard_sub(ec)) ||
+       (e_policy_client_is_floating(ec)) ||
+       (e_policy_client_is_quickpanel(ec)) ||
+       (e_policy_client_is_volume(ec)) ||
+       (!e_util_strcmp("wl_pointer-cursor", ec->icccm.window_role)) ||
+       (!e_util_strcmp("e_demo", ec->icccm.window_role)))
+     return EINA_FALSE;
+
+   if (e_policy_client_is_subsurface(ec)) return EINA_FALSE;
+
+   if ((ec->netwm.type != E_WINDOW_TYPE_NORMAL) &&
+       (ec->netwm.type != E_WINDOW_TYPE_UNKNOWN) &&
+       (ec->netwm.type != E_WINDOW_TYPE_NOTIFICATION))
+     return EINA_FALSE;
+
+   pd = eina_hash_find(hash_policy_desks, &ec->desk);
+   if (!pd) return EINA_FALSE;
+
+   pc = eina_hash_find(hash_policy_clients, &ec);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(pc, EINA_FALSE);
+
+   if (pc->flt_policy_state)
+     _e_policy_client_floating_policy_cancel(pc);
+
+   return _e_policy_client_maximize_policy_apply(pc);
+}
+
+Eina_Bool
+e_policy_client_is_lockscreen(E_Client *ec)
+{
+   E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
+   E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
+
+   if (ec->client_type == 2)
+     return EINA_TRUE;
+
+   if (!e_util_strcmp(ec->icccm.title, "LOCKSCREEN"))
+     return EINA_TRUE;
+
+   if (!e_util_strcmp(ec->icccm.window_role, "lockscreen"))
+     return EINA_TRUE;
+
+   return EINA_FALSE;
+}
+
+Eina_Bool
+e_policy_client_is_home_screen(E_Client *ec)
+{
+   E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
+   E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
+
+   if (ec->client_type == 1)
+     return EINA_TRUE;
+
+
+   return EINA_FALSE;
+}
+
+Eina_Bool
+e_policy_client_is_quickpanel(E_Client *ec)
+{
+   E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
+   E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
+
+   if (!e_util_strcmp(ec->icccm.window_role, "quickpanel"))
+     return EINA_TRUE;
+
+   return EINA_FALSE;
+}
+
+Eina_Bool
+e_policy_client_is_conformant(E_Client *ec)
+{
+   E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, EINA_FALSE);
+
+   E_Comp_Wl_Client_Data *cdata = (E_Comp_Wl_Client_Data *)ec->comp_data;
+   if (cdata->conformant == 1)
+     {
+        return EINA_TRUE;
+     }
+
+   return EINA_FALSE;
+}
+
+Eina_Bool
+e_policy_client_is_volume(E_Client *ec)
+{
+   E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
+   E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
+
+   if (!e_util_strcmp(ec->netwm.name, "volume"))
+     return EINA_TRUE;
+
+   if (!e_util_strcmp(ec->icccm.title, "volume"))
+     return EINA_TRUE;
+
+   return EINA_FALSE;
+}
+
+Eina_Bool
+e_policy_client_is_volume_tv(E_Client *ec)
+{
+   E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
+   E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
+
+   if (!e_util_strcmp(ec->icccm.window_role, "tv-volume-popup"))
+     return EINA_TRUE;
+
+   return EINA_FALSE;
+}
+
+Eina_Bool
+e_policy_client_is_noti(E_Client *ec)
+{
+   E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
+   E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
+
+   if (!e_util_strcmp(ec->icccm.title, "noti_win"))
+     return EINA_TRUE;
+
+   if (ec->netwm.type == E_WINDOW_TYPE_NOTIFICATION)
+     return EINA_TRUE;
+
+   return EINA_FALSE;
+}
+
+Eina_Bool
+e_policy_client_is_subsurface(E_Client *ec)
+{
+   E_Comp_Wl_Client_Data *cd;
+
+   E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
+   E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
+
+   cd = (E_Comp_Wl_Client_Data *)ec->comp_data;
+   if (cd && cd->sub.data)
+     return EINA_TRUE;
+
+   return EINA_FALSE;
+}
+
+Eina_Bool
+e_policy_client_is_floating(E_Client *ec)
+{
+   E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
+   E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
+
+   if (EINA_UNLIKELY(!ec))
+     return EINA_FALSE;
+
+   return ec->floating;
+}
+
+Eina_Bool
+e_policy_client_is_cursor(E_Client *ec)
+{
+   E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
+   E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
+
+   if (!e_util_strcmp("wl_pointer-cursor", ec->icccm.window_role))
+     return EINA_TRUE;
+
+   return EINA_FALSE;
+}
+
+E_API void
+e_policy_deferred_job(void)
+{
+   if (!e_policy) return;
+
+   e_policy_wl_defer_job();
+}
+
+
+#undef E_CLIENT_HOOK_APPEND
+#define E_CLIENT_HOOK_APPEND(l, t, cb, d) \
+  do                                      \
+    {                                     \
+       E_Client_Hook *_h;                 \
+       _h = e_client_hook_add(t, cb, d);  \
+       assert(_h);                        \
+       l = eina_list_append(l, _h);       \
+    }                                     \
+  while (0)
+
+#undef E_PIXMAP_HOOK_APPEND
+#define E_PIXMAP_HOOK_APPEND(l, t, cb, d) \
+  do                                      \
+    {                                     \
+       E_Pixmap_Hook *_h;                 \
+       _h = e_pixmap_hook_add(t, cb, d);  \
+       assert(_h);                        \
+       l = eina_list_append(l, _h);       \
+    }                                     \
+  while (0)
+
+E_API int
+e_policy_init(void)
+{
+   E_Policy *pol;
+   E_Zone *zone;
+   E_Config_Policy_Desk *d;
+   const Eina_List *l;
+   int i, n;
+
+   pol = E_NEW(E_Policy, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(pol, EINA_FALSE);
+
+   e_policy = pol;
+
+   hash_policy_clients = eina_hash_pointer_new(_e_policy_cb_client_data_free);
+   hash_policy_desks = eina_hash_pointer_new(_e_policy_cb_desk_data_free);
+
+   e_policy_stack_init();
+   e_policy_wl_init();
+   e_policy_wl_aux_hint_init();
+
+   EINA_LIST_FOREACH(e_comp->zones, l, zone)
+     {
+        n = zone->desk_y_count * zone->desk_x_count;
+        for (i = 0; i < n; i++)
+          {
+             d = _e_policy_desk_get_by_num(zone->num,
+                                           zone->desks[i]->x,
+                                           zone->desks[i]->y);
+             if (d)
+               e_policy_desk_add(zone->desks[i]);
+          }
+     }
+
+   E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_ADD,                  _e_policy_cb_zone_add,                        NULL);
+   E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_DEL,                  _e_policy_cb_zone_del,                        NULL);
+   E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_MOVE_RESIZE,          _e_policy_cb_zone_move_resize,                NULL);
+   E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_DESK_COUNT_SET,       _e_policy_cb_zone_desk_count_set,             NULL);
+   E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_DISPLAY_STATE_CHANGE, _e_policy_cb_zone_display_state_change,       NULL);
+   E_LIST_HANDLER_APPEND(handlers, E_EVENT_DESK_SHOW,                 _e_policy_cb_desk_show,                       NULL);
+   E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_ADD,                _e_policy_cb_client_add,                      NULL);
+   E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_MOVE,               _e_policy_cb_client_move,                     NULL);
+   E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_RESIZE,             _e_policy_cb_client_resize,                   NULL);
+   E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_STACK,              _e_policy_cb_client_stack,                    NULL);
+   E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_PROPERTY,           _e_policy_cb_client_property,                 NULL);
+   E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_VISIBILITY_CHANGE,  _e_policy_cb_client_vis_change,               NULL);
+
+   E_CLIENT_HOOK_APPEND(hooks_ec,  E_CLIENT_HOOK_NEW_CLIENT,          _e_policy_cb_hook_client_new,                 NULL);
+   E_CLIENT_HOOK_APPEND(hooks_ec,  E_CLIENT_HOOK_DEL,                 _e_policy_cb_hook_client_del,                 NULL);
+   E_CLIENT_HOOK_APPEND(hooks_ec,  E_CLIENT_HOOK_EVAL_PRE_NEW_CLIENT, _e_policy_cb_hook_client_eval_pre_new_client, NULL);
+   E_CLIENT_HOOK_APPEND(hooks_ec,  E_CLIENT_HOOK_EVAL_PRE_FETCH,      _e_policy_cb_hook_client_eval_pre_fetch,      NULL);
+   E_CLIENT_HOOK_APPEND(hooks_ec,  E_CLIENT_HOOK_EVAL_PRE_POST_FETCH, _e_policy_cb_hook_client_eval_pre_post_fetch, NULL);
+   E_CLIENT_HOOK_APPEND(hooks_ec,  E_CLIENT_HOOK_EVAL_POST_FETCH,     _e_policy_cb_hook_client_eval_post_fetch,     NULL);
+   E_CLIENT_HOOK_APPEND(hooks_ec,  E_CLIENT_HOOK_EVAL_POST_NEW_CLIENT,_e_policy_cb_hook_client_eval_post_new_client,NULL);
+   E_CLIENT_HOOK_APPEND(hooks_ec,  E_CLIENT_HOOK_DESK_SET,            _e_policy_cb_hook_client_desk_set,            NULL);
+   E_CLIENT_HOOK_APPEND(hooks_ec,  E_CLIENT_HOOK_FULLSCREEN_PRE,      _e_policy_cb_hook_client_fullscreen_pre,      NULL);
+   E_CLIENT_HOOK_APPEND(hooks_ec,  E_CLIENT_HOOK_EVAL_VISIBILITY,     _e_policy_cb_hook_client_visibility,          NULL);
+
+   E_PIXMAP_HOOK_APPEND(hooks_cp,  E_PIXMAP_HOOK_DEL,                 _e_policy_cb_hook_pixmap_del,                 NULL);
+   E_PIXMAP_HOOK_APPEND(hooks_cp,  E_PIXMAP_HOOK_UNUSABLE,            _e_policy_cb_hook_pixmap_unusable,            NULL);
+
+   e_policy_transform_mode_init();
+   e_policy_conformant_init();
+
+   return EINA_TRUE;
+}
+
+E_API int
+e_policy_shutdown(void)
+{
+   E_Policy *pol = e_policy;
+   Eina_Inlist *l;
+   E_Policy_Softkey *softkey;
+
+   eina_list_free(pol->launchers);
+   EINA_INLIST_FOREACH_SAFE(pol->softkeys, l, softkey)
+     e_policy_softkey_del(softkey);
+   E_FREE_LIST(hooks_cp, e_pixmap_hook_del);
+   E_FREE_LIST(hooks_ec, e_client_hook_del);
+   E_FREE_LIST(handlers, ecore_event_handler_del);
+
+   E_FREE_FUNC(hash_policy_desks, eina_hash_free);
+   E_FREE_FUNC(hash_policy_clients, eina_hash_free);
+
+   e_policy_stack_shutdonw();
+   e_policy_wl_shutdown();
+
+   e_policy_transform_mode_shutdown();
+   e_policy_conformant_shutdown();
+
+   E_FREE(pol);
+
+   e_policy = NULL;
+
+   return 1;
+}
diff --git a/src/bin/e_policy.h b/src/bin/e_policy.h
new file mode 100644 (file)
index 0000000..e1f202f
--- /dev/null
@@ -0,0 +1,148 @@
+# ifdef E_TYPEDEFS
+typedef struct _E_Policy_Desk     E_Policy_Desk;
+typedef struct _E_Policy_Client   E_Policy_Client;
+typedef struct _E_Policy_Softkey  E_Policy_Softkey;
+typedef struct _E_Policy_Config_Match E_Policy_Config_Match;
+typedef struct _E_Policy_Config_Desk  E_Policy_Config_Desk;
+typedef struct _E_Policy_Config_Rot   E_Policy_Config_Rot;
+typedef struct _E_Policy_Config       E_Policy_Config;
+typedef struct _E_Policy          E_Policy;
+typedef struct _E_Policy_System_Info E_Policy_System_Info;
+
+# else
+# ifndef E_POLICY_H
+# define E_POLICY_H
+#  ifndef _
+#    ifdef HAVE_GETTEXT
+#  define _(str) gettext(str)
+#    else
+#  define _(str) (str)
+#    endif
+#  endif
+
+struct _E_Policy_Desk
+{
+   E_Desk          *desk;
+   E_Zone          *zone;
+};
+
+struct _E_Policy_Client
+{
+   E_Client        *ec;
+   struct
+   {
+      E_Maximize    maximized;
+      unsigned int  fullscreen : 1;
+      unsigned char borderless : 1;
+      unsigned int  lock_user_location : 1;
+      unsigned int  lock_client_location : 1;
+      unsigned int  lock_user_size : 1;
+      unsigned int  lock_client_size : 1;
+      unsigned int  lock_client_stacking : 1;
+      unsigned int  lock_user_shade : 1;
+      unsigned int  lock_client_shade : 1;
+      unsigned int  lock_user_maximize : 1;
+      unsigned int  lock_client_maximize : 1;
+      unsigned int  lock_user_fullscreen : 1;
+      unsigned int  lock_client_fullscreen : 1;
+   } orig;
+
+   struct
+   {
+      unsigned int vkbd_state;
+      unsigned int already_hide;
+   } changes;
+
+   Eina_Bool max_policy_state;
+   Eina_Bool flt_policy_state;
+   Eina_Bool allow_user_geom;
+   int       user_geom_ref;
+};
+
+struct _E_Policy_Softkey
+{
+   EINA_INLIST;
+
+   E_Zone          *zone;
+   Evas_Object     *home;
+   Evas_Object     *back;
+};
+
+struct _E_Policy
+{
+   E_Module        *module;
+   Eina_List       *launchers; /* launcher window per zone */
+   Eina_Inlist     *softkeys; /* softkey ui object per zone */
+};
+
+struct _E_Policy_System_Info
+{
+   struct
+   {
+      E_Client  *ec;
+      Eina_Bool  show;
+   } lockscreen;
+
+   struct
+   {
+      int system;
+      int client;
+      Eina_Bool use_client;
+   } brightness;
+};
+
+extern E_Policy *e_policy;
+extern E_Policy_System_Info e_policy_system_info;
+
+EINTERN E_Policy_Config_Desk *e_policy_conf_desk_get_by_nums(E_Policy_Config *conf, unsigned int zone_num, int x, int y);
+EINTERN E_Policy_Client      *e_policy_client_get(E_Client *ec);
+EINTERN void                  e_policy_allow_user_geometry_set(E_Client *ec, Eina_Bool set);
+EINTERN void                  e_policy_desk_add(E_Desk *desk);
+EINTERN void                  e_policy_desk_del(E_Policy_Desk *pd);
+EINTERN E_Policy_Client      *e_policy_client_launcher_get(E_Zone *zone);
+
+EINTERN Eina_Bool        e_policy_client_is_lockscreen(E_Client *ec);
+EINTERN Eina_Bool        e_policy_client_is_home_screen(E_Client *ec);
+EINTERN Eina_Bool        e_policy_client_is_quickpanel(E_Client *ec);
+EINTERN Eina_Bool        e_policy_client_is_conformant(E_Client *ec);
+EINTERN Eina_Bool        e_policy_client_is_volume(E_Client *ec);
+EINTERN Eina_Bool        e_policy_client_is_volume_tv(E_Client *ec);
+EINTERN Eina_Bool        e_policy_client_is_noti(E_Client *ec);
+EINTERN Eina_Bool        e_policy_client_is_floating(E_Client *ec);
+EINTERN Eina_Bool        e_policy_client_is_cursor(E_Client *ec);
+EINTERN Eina_Bool        e_policy_client_is_subsurface(E_Client *ec);
+
+EINTERN E_Policy_Softkey *e_policy_softkey_add(E_Zone *zone);
+EINTERN void              e_policy_softkey_del(E_Policy_Softkey *softkey);
+EINTERN void              e_policy_softkey_show(E_Policy_Softkey *softkey);
+EINTERN void              e_policy_softkey_hide(E_Policy_Softkey *softkey);
+EINTERN void              e_policy_softkey_update(E_Policy_Softkey *softkey);
+EINTERN E_Policy_Softkey *e_policy_softkey_get(E_Zone *zone);
+
+EINTERN void             e_policy_client_visibility_send(E_Client *ec);
+EINTERN void             e_policy_client_iconify_by_visibility(E_Client *ec);
+EINTERN void             e_policy_client_uniconify_by_visibility(E_Client *ec);
+
+EINTERN Eina_Bool        e_policy_client_maximize(E_Client *ec);
+
+EINTERN void             e_policy_client_window_opaque_set(E_Client *ec);
+
+EINTERN void             e_policy_stack_init(void);
+EINTERN void             e_policy_stack_shutdonw(void);
+EINTERN void             e_policy_stack_transient_for_set(E_Client *child, E_Client *parent);
+EINTERN void             e_policy_stack_cb_client_remove(E_Client *ec);
+EINTERN void             e_policy_stack_hook_pre_fetch(E_Client *ec);
+EINTERN void             e_policy_stack_hook_pre_post_fetch(E_Client *ec);
+
+EINTERN void             e_policy_stack_below(E_Client *ec, E_Client *below_ec);
+
+EINTERN void             e_policy_stack_clients_restack_above_lockscreen(E_Client *ec_lock, Eina_Bool show);
+EINTERN Eina_Bool        e_policy_stack_check_above_lockscreen(E_Client *ec, E_Layer layer, E_Layer *new_layer, Eina_Bool set_layer);
+
+EINTERN Eina_Bool        e_policy_conf_rot_enable_get(int angle);
+
+E_API void e_policy_deferred_job(void);
+E_API int e_policy_init(void);
+E_API int e_policy_shutdown(void);
+#endif
+#endif
diff --git a/src/bin/e_policy_conformant.c b/src/bin/e_policy_conformant.c
new file mode 100644 (file)
index 0000000..6ab79dc
--- /dev/null
@@ -0,0 +1,511 @@
+#include "e.h"
+
+#include <wayland-server.h>
+#include <tizen-extension-server-protocol.h>
+
+#define CFDBG(f, x...)  DBG("Conformant|"f, ##x)
+#define CFINF(f, x...)  INF("Conformant|"f, ##x)
+#define CFERR(f, x...)  ERR("Conformant|"f, ##x)
+
+#define CONF_DATA_GET(ptr)             \
+   Conformant *ptr = _conf_data_get()
+#define CONF_DATA_GET_OR_RETURN(ptr)   \
+   CONF_DATA_GET(ptr);                 \
+   if (!ptr)                           \
+   {                                   \
+      CFERR("no conformant data");     \
+      return;                          \
+   }
+#define CONF_DATA_GET_OR_RETURN_VAL(ptr, val)   \
+   CONF_DATA_GET(ptr);                          \
+   if (!ptr)                                    \
+   {                                            \
+      CFERR("no conformant data");              \
+      return val;                               \
+   }
+
+typedef struct
+{
+   E_Client *vkbd;
+   E_Client *owner;
+   Eina_Hash *client_hash;
+   Eina_List *handlers;
+   E_Client_Hook *client_del_hook;
+   Ecore_Idle_Enterer *idle_enterer;
+
+   struct
+   {
+      Eina_Bool restore;
+      Eina_Bool visible;
+      int x, y, w, h;
+   } state;
+
+   Eina_Bool changed : 1;
+} Conformant;
+
+typedef struct
+{
+   E_Client *ec;
+   Eina_List *res_list;
+} Conformant_Client;
+
+typedef struct
+{
+   Conformant_Client *cfc;
+   struct wl_resource *res;
+   struct wl_listener destroy_listener;
+} Conformant_Wl_Res;
+
+Conformant *_conf = NULL;
+
+static Conformant *
+_conf_data_get()
+{
+   return _conf;
+}
+
+static void
+_conf_state_update(Conformant *conf, Eina_Bool visible, int x, int y, int w, int h)
+{
+   Conformant_Client *cfc;
+   Conformant_Wl_Res *cres;
+   Eina_List *l;
+
+   if ((conf->state.visible == visible) &&
+       (conf->state.x == x) && (conf->state.x == y) &&
+       (conf->state.x == w) && (conf->state.x == h))
+     return;
+
+   CFDBG("Update Conformant State\n");
+   CFDBG("\tprev: v %d geom %d %d %d %d\n",
+       conf->state.visible, conf->state.x, conf->state.y, conf->state.w, conf->state.h);
+   CFDBG("\tnew : v %d geom %d %d %d %d\n", visible, x, y, w, h);
+
+   conf->state.visible = visible;
+   conf->state.x = x;
+   conf->state.y = y;
+   conf->state.w = w;
+   conf->state.h = h;
+
+   if (!conf->owner)
+     return;
+
+   cfc = eina_hash_find(conf->client_hash, &conf->owner);
+   if (!cfc)
+     return;
+
+   CFDBG("\t=> '%s'(%p)", cfc->ec ? (cfc->ec->icccm.name ?:"") : "", cfc->ec);
+   EINA_LIST_FOREACH(cfc->res_list, l, cres)
+     {
+        tizen_policy_send_conformant_area
+           (cres->res,
+            cfc->ec->comp_data->surface,
+            TIZEN_POLICY_CONFORMANT_PART_KEYBOARD,
+            (unsigned int)visible, x, y, w, h);
+     }
+}
+
+static void
+_conf_cb_vkbd_obj_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Conformant *conf;
+
+   CFDBG("VKBD Deleted");
+   conf = data;
+   conf->vkbd = NULL;
+}
+
+static void
+_conf_cb_vkbd_obj_show(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Conformant *conf;
+
+   CFDBG("VKBD Show");
+   conf = data;
+   conf->owner = conf->vkbd->parent;
+   if (!conf->owner)
+     WRN("Not exist vkbd's parent even if it becomes visible");
+   conf->changed = 1;
+}
+
+static void
+_conf_cb_vkbd_obj_hide(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Conformant *conf;
+
+   CFDBG("VKBD Hide");
+   conf = data;
+   _conf_state_update(conf, EINA_FALSE, conf->state.x, conf->state.y, conf->state.w, conf->state.h);
+   conf->owner = NULL;
+}
+
+static void
+_conf_cb_vkbd_obj_move(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Conformant *conf;
+
+   CFDBG("VKBD Move");
+   conf = data;
+   conf->changed = 1;
+}
+
+static void
+_conf_cb_vkbd_obj_resize(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Conformant *conf;
+
+   CFDBG("VKBD Resize");
+   conf = data;
+   conf->changed = 1;
+}
+
+static void
+_conf_client_del(Conformant_Client *cfc)
+{
+   Conformant_Wl_Res *cres;
+
+   EINA_LIST_FREE(cfc->res_list, cres)
+     {
+        wl_list_remove(&cres->destroy_listener.link);
+        free(cres);
+     }
+
+   free(cfc);
+}
+
+static void
+_conf_client_resource_destroy(struct wl_listener *listener, void *data)
+{
+   Conformant_Wl_Res *cres;
+
+   cres = container_of(listener, Conformant_Wl_Res, destroy_listener);
+   if (!cres)
+     return;
+
+   CFDBG("Destroy Wl Resource res %p owner %s(%p)",
+         cres->res, cres->cfc->ec->icccm.name ? cres->cfc->ec->icccm.name : "", cres->cfc->ec);
+
+   cres->cfc->res_list = eina_list_remove(cres->cfc->res_list, cres);
+
+   free(cres);
+}
+
+static void
+_conf_client_resource_add(Conformant_Client *cfc, struct wl_resource *res)
+{
+   Conformant_Wl_Res *cres;
+   Eina_List *l;
+
+   if (cfc->res_list)
+     {
+        EINA_LIST_FOREACH(cfc->res_list, l, cres)
+          {
+             if (cres->res == res)
+               {
+                  CFERR("Already Added Resource, Nothing to do. res: %p", res);
+                  return;
+               }
+          }
+     }
+
+   cres = E_NEW(Conformant_Wl_Res, 1);
+   if (!cres)
+     return;
+
+   cres->cfc = cfc;
+   cres->res = res;
+   cres->destroy_listener.notify = _conf_client_resource_destroy;
+   wl_resource_add_destroy_listener(res, &cres->destroy_listener);
+
+   cfc->res_list = eina_list_append(cfc->res_list, cres);
+}
+
+static Conformant_Client *
+_conf_client_add(Conformant *conf, E_Client *ec, struct wl_resource *res)
+{
+   Conformant_Client *cfc;
+
+   cfc = E_NEW(Conformant_Client, 1);
+   if (!cfc)
+     return NULL;
+
+   cfc->ec = ec;
+
+   _conf_client_resource_add(cfc, res);
+
+   return cfc;
+}
+
+static void
+_conf_vkbd_register(Conformant *conf, E_Client *ec)
+{
+   CFINF("VKBD Registered");
+   if (conf->vkbd)
+     {
+        CFERR("Something strange error, VKBD Already Registered.");
+        return;
+     }
+   conf->vkbd = ec;
+
+   evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_DEL,      _conf_cb_vkbd_obj_del,     conf);
+   evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_SHOW,     _conf_cb_vkbd_obj_show,    conf);
+   evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_HIDE,     _conf_cb_vkbd_obj_hide,    conf);
+   evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_MOVE,     _conf_cb_vkbd_obj_move,    conf);
+   evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_RESIZE,   _conf_cb_vkbd_obj_resize,  conf);
+}
+
+static Eina_Bool
+_conf_cb_client_add(void *data, int type EINA_UNUSED, void *event)
+{
+   Conformant *conf;
+   E_Event_Client *ev;
+
+   conf = data;
+   ev = event;
+
+   if (ev->ec->vkbd.vkbd)
+     _conf_vkbd_register(conf, ev->ec);
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_conf_cb_client_rot_change_begin(void *data, int type EINA_UNUSED, void *event)
+{
+   Conformant *conf;
+   E_Event_Client *ev;
+
+   ev = event;
+   conf = data;
+
+   if (ev->ec != conf->vkbd)
+     goto end;
+
+   /* set conformant area to non-visible state before starting rotation.
+    * this is to prevent to apply wrong area of conformant area after rotation.
+    * Suppose conformant area will be set later according to changes of vkbd such as resize or move.
+    * if there is no being called rot_change_cancel and nothing changes vkbd,
+    * that is unexpected case.
+    */
+   if (conf->state.visible)
+     {
+        CFDBG("Rotation Begin");
+        _conf_state_update(conf, EINA_FALSE, conf->state.x, conf->state.y, conf->state.w, conf->state.h);
+        conf->state.restore = EINA_TRUE;
+     }
+
+end:
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_conf_cb_client_rot_change_cancel(void *data, int type EINA_UNUSED, void *event)
+{
+   Conformant *conf;
+   E_Event_Client *ev;
+
+   ev = event;
+   conf = data;
+
+   if (ev->ec != conf->vkbd)
+     goto end;
+
+   if (conf->state.restore)
+     {
+        CFDBG("Rotation Cancel");
+        _conf_state_update(conf, EINA_FALSE, conf->state.x, conf->state.y, conf->state.w, conf->state.h);
+        conf->state.restore = EINA_TRUE;
+     }
+
+end:
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_conf_cb_client_rot_change_end(void *data, int type EINA_UNUSED, void *event)
+{
+   Conformant *conf;
+   E_Event_Client *ev;
+
+   ev = event;
+   conf = data;
+
+   if (ev->ec != conf->vkbd)
+     goto end;
+
+   conf->state.restore = EINA_FALSE;
+
+end:
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static void
+_conf_cb_client_del(void *data, E_Client *ec)
+{
+   Conformant *conf;
+   Conformant_Client *cfc;
+
+   conf = data;
+   if (!conf->client_hash)
+     return;
+
+   cfc = eina_hash_find(conf->client_hash, &ec);
+   if (!cfc)
+     return;
+
+   eina_hash_del(conf->client_hash, &ec, cfc);
+   _conf_client_del(cfc);
+}
+
+static Eina_Bool
+_conf_idle_enter(void *data)
+{
+   Conformant *conf;
+   Eina_Bool visible;
+   int x, y, w, h;
+
+   conf = data;
+   if (!conf->vkbd)
+     goto end;
+
+   if (conf->changed)
+     {
+        visible = evas_object_visible_get(conf->vkbd->frame);
+        evas_object_geometry_get(conf->vkbd->frame, &x, &y, &w, &h);
+
+        _conf_state_update(conf, visible, x, y, w, h);
+
+        conf->changed = EINA_FALSE;
+     }
+
+end:
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static void
+_conf_event_init(Conformant *conf)
+{
+   E_LIST_HANDLER_APPEND(conf->handlers, E_EVENT_CLIENT_ADD,                     _conf_cb_client_add,                conf);
+   E_LIST_HANDLER_APPEND(conf->handlers, E_EVENT_CLIENT_ROTATION_CHANGE_BEGIN,   _conf_cb_client_rot_change_begin,   conf);
+   E_LIST_HANDLER_APPEND(conf->handlers, E_EVENT_CLIENT_ROTATION_CHANGE_CANCEL,  _conf_cb_client_rot_change_cancel,  conf);
+   E_LIST_HANDLER_APPEND(conf->handlers, E_EVENT_CLIENT_ROTATION_CHANGE_END,     _conf_cb_client_rot_change_end,     conf);
+
+   conf->client_del_hook = e_client_hook_add(E_CLIENT_HOOK_DEL, _conf_cb_client_del, conf);
+   conf->idle_enterer = ecore_idle_enterer_add(_conf_idle_enter, conf);
+}
+
+static void
+_conf_event_shutdown(Conformant *conf)
+{
+   E_FREE_LIST(conf->handlers, ecore_event_handler_del);
+   E_FREE_FUNC(conf->client_del_hook, e_client_hook_del);
+   E_FREE_FUNC(conf->idle_enterer, ecore_idle_enterer_del);
+}
+
+EINTERN void
+e_policy_conformant_client_add(E_Client *ec, struct wl_resource *res)
+{
+   Conformant_Client *cfc;
+
+   CONF_DATA_GET_OR_RETURN(conf);
+
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   CFDBG("Client Add '%s'(%p)", ec->icccm.name ? ec->icccm.name : "", ec);
+
+   if (conf->client_hash)
+     {
+        cfc = eina_hash_find(conf->client_hash, &ec);
+        if (cfc)
+          {
+             CFDBG("Already Added Client, Just Add Resource");
+             _conf_client_resource_add(cfc, res);
+             return;
+          }
+     }
+
+   cfc = _conf_client_add(conf, ec, res);
+
+   /* do we need to send conformant state if vkbd is visible ? */
+
+   if (!conf->client_hash)
+     conf->client_hash = eina_hash_pointer_new(NULL);
+
+   eina_hash_add(conf->client_hash, &ec, cfc);
+}
+
+EINTERN void
+e_policy_conformant_client_del(E_Client *ec)
+{
+   Conformant_Client *cfc;
+
+   CONF_DATA_GET_OR_RETURN(conf);
+
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   CFDBG("Client Del '%s'(%p)", ec->icccm.name ? ec->icccm.name : "", ec);
+
+   cfc = eina_hash_find(conf->client_hash, &ec);
+   if (cfc)
+     {
+        eina_hash_del(conf->client_hash, &ec, cfc);
+        _conf_client_del(cfc);
+     }
+}
+
+EINTERN Eina_Bool
+e_policy_conformant_client_check(E_Client *ec)
+{
+   CONF_DATA_GET_OR_RETURN_VAL(conf, EINA_FALSE);
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
+
+   if (!conf->client_hash)
+     return EINA_FALSE;
+
+   return !!eina_hash_find(conf->client_hash, &ec);
+}
+
+EINTERN Eina_Bool
+e_policy_conformant_init(void)
+{
+   Conformant *conf;
+
+   if (_conf)
+     return EINA_TRUE;
+
+   CFINF("Conformant Module Init");
+
+   conf = E_NEW(Conformant, 1);
+   if (!conf)
+     return EINA_FALSE;
+
+   _conf_event_init(conf);
+
+   _conf = conf;
+
+   return EINA_TRUE;
+}
+
+EINTERN void
+e_policy_conformant_shutdown(void)
+{
+   Conformant_Client *cfc;
+   Eina_Iterator *itr;
+
+   if (!_conf)
+     return;
+
+   CFINF("Conformant Module Shutdown");
+
+   _conf_event_shutdown(_conf);
+
+   itr = eina_hash_iterator_data_new(_conf->client_hash);
+   EINA_ITERATOR_FOREACH(itr, cfc)
+      _conf_client_del(cfc);
+   eina_iterator_free(itr);
+
+   E_FREE_FUNC(_conf->client_hash, eina_hash_free);
+
+   E_FREE(_conf);
+}
diff --git a/src/bin/e_policy_conformant.h b/src/bin/e_policy_conformant.h
new file mode 100644 (file)
index 0000000..d94a4e2
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef E_POLICY_CONFORMANT_H
+#define E_POLICY_CONFORMANT_H
+
+EINTERN Eina_Bool  e_policy_conformant_init(void);
+EINTERN void       e_policy_conformant_shutdown(void);
+EINTERN void       e_policy_conformant_client_add(E_Client *ec, struct wl_resource *res);
+EINTERN void       e_policy_conformant_client_del(E_Client *ec);
+EINTERN Eina_Bool  e_policy_conformant_client_check(E_Client *ec);
+
+#endif
diff --git a/src/bin/e_policy_keyboard.c b/src/bin/e_policy_keyboard.c
new file mode 100644 (file)
index 0000000..e7e9199
--- /dev/null
@@ -0,0 +1,98 @@
+#include "e_policy_keyboard.h"
+
+EINTERN Eina_Bool
+e_policy_client_is_keyboard(E_Client *ec)
+{
+   E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
+   E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
+
+   if (ec->vkbd.vkbd) return EINA_TRUE;
+
+   return EINA_FALSE;
+}
+
+EINTERN Eina_Bool
+e_policy_client_is_keyboard_sub(E_Client *ec)
+{
+   E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
+   E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
+
+   if (ec->vkbd.vkbd) return EINA_FALSE;
+
+   if ((ec->icccm.class) &&
+       (!strcmp(ec->icccm.class, "ISF")))
+     return EINA_TRUE;
+   if ((ec->icccm.title) &&
+       (!strcmp(ec->icccm.title, "ISF Popup")))
+     return EINA_TRUE;
+
+   return EINA_FALSE;
+}
+
+EINTERN void
+e_policy_keyboard_layout_apply(E_Client *ec EINA_UNUSED)
+{
+/* FIXME: do not resize and move client.
+ * ec->e.state.rot.geom[].w/h is always 0,
+ * then the geometry calculated here is not valid. */
+#if 0
+   int angle;
+   int angle_id = 0;
+   int kbd_x, kbd_y, kbd_w, kbd_h;
+
+   if (!e_policy_client_is_keyboard(ec) &&
+       !e_policy_client_is_keyboard_sub(ec))
+      return;
+
+   angle = e_client_rotation_curr_angle_get(ec);
+
+   switch (angle)
+     {
+      case 0: angle_id = 0; break;
+      case 90: angle_id = 1; break;
+      case 180: angle_id = 2; break;
+      case 270: angle_id = 3; break;
+      default: angle_id = 0; break;
+     }
+
+   kbd_w = ec->e.state.rot.geom[angle_id].w;
+   kbd_h = ec->e.state.rot.geom[angle_id].h;
+
+   switch (angle)
+     {
+      case 0:
+         kbd_x = ec->zone->w - kbd_w;
+         kbd_y = ec->zone->h - kbd_h;
+         break;
+
+      case 90:
+         kbd_x = ec->zone->w - kbd_w;
+         kbd_y = ec->zone->h - kbd_h;
+         break;
+
+      case 180:
+         kbd_x = 0;
+         kbd_y = 0;
+         break;
+
+      case 270:
+         kbd_x = 0;
+         kbd_y = 0;
+         break;
+
+      default:
+         kbd_x = ec->zone->w - kbd_w;
+         kbd_y = ec->zone->h - kbd_h;
+         break;
+     }
+
+   if ((ec->frame) &&
+       ((ec->w != kbd_w) || (ec->h != kbd_h)))
+     e_client_util_resize_without_frame(ec, kbd_w, kbd_h);
+
+   if ((e_policy_client_is_keyboard(ec)) &&
+       (ec->frame) &&
+       ((ec->x != kbd_x) || (ec->y != kbd_y)))
+     e_client_util_move_without_frame(ec, kbd_x, kbd_y);
+#endif
+}
diff --git a/src/bin/e_policy_keyboard.h b/src/bin/e_policy_keyboard.h
new file mode 100644 (file)
index 0000000..a17c441
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef E_POLICY_KEYBOARD_H
+#define E_POLICY_KEYBOARD_H
+#include <e.h>
+
+EINTERN Eina_Bool e_policy_client_is_keyboard(E_Client *ec);
+EINTERN Eina_Bool e_policy_client_is_keyboard_sub(E_Client *ec);
+EINTERN void      e_policy_keyboard_layout_apply(E_Client *ec);
+
+#endif
diff --git a/src/bin/e_policy_private_data.h b/src/bin/e_policy_private_data.h
new file mode 100644 (file)
index 0000000..83327d0
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef E_POLICY_PRIVATE_DATA_H
+#define E_POLICY_PRIVATE_DATA_H
+
+/* define layer values here */
+typedef enum {
+     E_POLICY_ANGLE_MAP_0 = 0,
+     E_POLICY_ANGLE_MAP_90,
+     E_POLICY_ANGLE_MAP_180,
+     E_POLICY_ANGLE_MAP_270,
+     E_POLICY_ANGLE_MAP_NUM,
+} E_Policy_Angle_Map;
+
+static inline Eina_Bool
+e_policy_angle_valid_check(int angle)
+{
+   return ((angle >= 0) && (angle <= 270) && !(angle % 90));
+}
+
+static inline E_Policy_Angle_Map
+e_policy_angle_map(int angle)
+{
+   if (!e_policy_angle_valid_check(angle))
+     return -1;
+
+   return angle / 90;
+}
+
+static inline int
+e_policy_angle_get(E_Policy_Angle_Map map)
+{
+   if ((map < E_POLICY_ANGLE_MAP_0 ) || (map > E_POLICY_ANGLE_MAP_NUM))
+     return -1;
+
+   return map * 90;
+}
+
+/* layer level - 999 */
+# define E_POLICY_QUICKPANEL_LAYER  E_LAYER_CLIENT_ALERT
+# define E_POLICY_TOAST_POPUP_LAYER E_LAYER_CLIENT_ALERT
+
+/* layer level - E_LAYER_CLIENT_NOTIFICATION_TOP (800) */
+# define E_POLICY_VOLUME_LAYER      E_LAYER_CLIENT_NOTIFICATION_TOP
+
+/* layer level - E_LAYER_CLIENT_NOTIFICATION_HIGH (750) */
+/* layer level - E_LAYER_CLIENT_NOTIFICATION_NORMAL (700) */
+/* layer level - E_LAYER_CLIENT_NOTIFICATION_LOW (650) */
+
+/* layer level - E_LAYER_CLIENT_PRIO (600) */
+# define E_POLICY_FLOATING_LAYER E_LAYER_CLIENT_PRIO
+
+/* layer level - E_LAYER_CLIENT_FULLSCREEN (350) */
+/* layer level - E_LAYER_CLIENT_ABOVE (250) */
+/* layer level - E_LAYER_CLIENT_NORMAL (200) */
+/* layer level - E_LAYER_CLIENT_BELOW (150) */
+
+#endif
diff --git a/src/bin/e_policy_softkey.c b/src/bin/e_policy_softkey.c
new file mode 100644 (file)
index 0000000..b33b5c1
--- /dev/null
@@ -0,0 +1,177 @@
+#include "e.h"
+
+static void         _e_policy_cb_softkey(void *data, Evas_Object *obj EINA_UNUSED, const char *emission, const char *source EINA_UNUSED);
+static void         _e_policy_softkey_iconify(E_Zone *zone, Eina_Bool all);
+static Evas_Object *_e_policy_softkey_icon_add(E_Zone *zone, const char *name);
+static void         _e_policy_softkey_icon_del(Evas_Object *comp_obj);
+
+static void
+_e_policy_cb_softkey(void *data, Evas_Object *obj EINA_UNUSED, const char *emission, const char *source EINA_UNUSED)
+{
+   E_Zone *zone;
+   Eina_Bool all;
+
+   zone = data;
+
+   if (!e_util_strcmp(emission, "e,action,softkey,home"))
+     all = EINA_TRUE;
+   else if (!e_util_strcmp(emission, "e,action,softkey,back"))
+     all = EINA_FALSE;
+   else
+     return;
+
+   _e_policy_softkey_iconify(zone, all);
+}
+
+static void
+_e_policy_softkey_iconify(E_Zone *zone, Eina_Bool all)
+{
+   E_Desk *desk;
+   E_Client *ec;
+   E_Policy_Client *launcher;
+
+   desk = e_desk_current_get(zone);
+   launcher = e_policy_client_launcher_get(zone);
+
+   E_CLIENT_REVERSE_FOREACH(ec)
+     {
+        if (e_client_util_ignored_get(ec)) continue;
+        if (!e_client_util_desk_visible(ec, desk)) continue;
+        if (!evas_object_visible_get(ec->frame)) continue;
+
+        if ((launcher) && (launcher->ec == ec))
+          return;
+
+        if (e_policy_client_is_home_screen(ec))
+          {
+             evas_object_raise(ec->frame);
+             return;
+          }
+        if (!all)
+          {
+             evas_object_lower(ec->frame);
+             return;
+          }
+     }
+}
+
+static Evas_Object *
+_e_policy_softkey_icon_add(E_Zone *zone, const char *name)
+{
+   Evas_Object *obj, *comp_obj;
+   char path[PATH_MAX], group[PATH_MAX];
+
+   obj = edje_object_add(e_comp->evas);
+
+   snprintf(group, sizeof(group), "e/modules/policy-mobile/softkey/%s", name);
+   e_prefix_data_snprintf(path, sizeof(path), "data/themes/%s", "e-policy.edj");
+
+   if (!e_theme_edje_object_set(obj, NULL, group))
+     edje_object_file_set(obj, path, group);
+
+   edje_object_signal_callback_add(obj, "e,action,softkey,*", "e",
+                                   _e_policy_cb_softkey, zone);
+
+   /* use TYPE_NONE to disable shadow for softkey object */
+   comp_obj = e_comp_object_util_add(obj, E_COMP_OBJECT_TYPE_NONE);
+   evas_object_layer_set(comp_obj, E_LAYER_POPUP);
+
+   evas_object_data_set(comp_obj, "policy_mobile_obj", obj);
+
+   return comp_obj;
+}
+
+static void
+_e_policy_softkey_icon_del(Evas_Object *comp_obj)
+{
+   Evas_Object *obj;
+
+   obj = evas_object_data_get(comp_obj, "policy_mobile_obj");
+
+   edje_object_signal_callback_del(obj, "e,action,softkey,*",
+                                   "e", _e_policy_cb_softkey);
+   evas_object_hide(comp_obj);
+   evas_object_del(comp_obj);
+}
+
+E_Policy_Softkey *
+e_policy_softkey_add(E_Zone *zone)
+{
+   E_Policy_Softkey *softkey;
+
+   softkey = E_NEW(E_Policy_Softkey, 1);
+
+   softkey->zone = zone;
+   softkey->home = _e_policy_softkey_icon_add(zone, "home");
+   softkey->back = _e_policy_softkey_icon_add(zone, "back");
+
+   e_policy->softkeys = eina_inlist_append(e_policy->softkeys, EINA_INLIST_GET(softkey));
+
+   return softkey;
+}
+
+void
+e_policy_softkey_del(E_Policy_Softkey *softkey)
+{
+   if (!softkey) return;
+
+   _e_policy_softkey_icon_del(softkey->home);
+   _e_policy_softkey_icon_del(softkey->back);
+
+   e_policy->softkeys = eina_inlist_remove(e_policy->softkeys, EINA_INLIST_GET(softkey));
+
+   free(softkey);
+}
+
+void
+e_policy_softkey_show(E_Policy_Softkey *softkey)
+{
+   if (!softkey) return;
+
+   e_policy_softkey_update(softkey);
+
+   evas_object_show(softkey->home);
+   evas_object_show(softkey->back);
+}
+
+void
+e_policy_softkey_hide(E_Policy_Softkey *softkey)
+{
+   if (!softkey) return;
+
+   evas_object_hide(softkey->home);
+   evas_object_hide(softkey->back);
+}
+
+void
+e_policy_softkey_update(E_Policy_Softkey *softkey)
+{
+   int x, y, w, h, ow, oh, space;
+
+   if (!softkey) return;
+
+   e_zone_useful_geometry_get(softkey->zone, &x, &y, &w, &h);
+
+   ow = oh = e_config->softkey_size;
+
+   x = x + (w - ow) / 2;
+   y = h - oh;
+   space = ow * 4;
+
+   evas_object_geometry_set(softkey->home, x - space, y, ow, oh);
+   evas_object_geometry_set(softkey->back, x + space, y, ow, oh);
+}
+
+E_Policy_Softkey *
+e_policy_softkey_get(E_Zone *zone)
+{
+   E_Policy_Softkey *softkey;
+
+   EINA_INLIST_FOREACH(e_policy->softkeys, softkey)
+     {
+        if (softkey->zone == zone)
+          return softkey;
+     }
+
+   return NULL;
+}
diff --git a/src/bin/e_policy_stack.c b/src/bin/e_policy_stack.c
new file mode 100644 (file)
index 0000000..6d2f56c
--- /dev/null
@@ -0,0 +1,485 @@
+#include "e.h"
+
+typedef struct _E_Policy_Stack E_Policy_Stack;
+
+struct _E_Policy_Stack
+{
+   E_Client *ec;
+
+   struct
+     {
+        Ecore_Window win;
+        Eina_Bool fetched;
+     } transient;
+};
+
+static Eina_Hash *hash_pol_stack = NULL;
+
+static void
+_e_policy_stack_cb_data_free(void *data)
+{
+   E_FREE(data);
+}
+
+E_Policy_Stack*
+_e_policy_stack_data_add(E_Client *ec)
+{
+   E_Policy_Stack *ps;
+
+   if ((ps = eina_hash_find(hash_pol_stack, &ec)))
+     return ps;
+
+   ps = E_NEW(E_Policy_Stack, 1);
+   if (!ps) return NULL;
+
+   ps->ec = ec;
+   eina_hash_add(hash_pol_stack, &ec, ps);
+
+   return ps;
+}
+
+void
+_e_policy_stack_data_del(E_Client *ec)
+{
+   E_Policy_Stack *ps;
+
+   if ((ps = eina_hash_find(hash_pol_stack, &ec)))
+     {
+        eina_hash_del_by_key(hash_pol_stack, &ec);
+     }
+}
+
+void
+_e_policy_stack_transient_for_apply(E_Client *ec)
+{
+   int raise;
+   E_Client *child, *top;
+   Eina_List *l;
+
+   if (ec->parent->layer != ec->layer)
+     {
+        raise = e_config->transient.raise;
+
+        ec->saved.layer = ec->layer;
+        ec->layer = ec->parent->layer;
+        if (e_config->transient.layer)
+          {
+             e_config->transient.raise = 1;
+             EINA_LIST_FOREACH(ec->transients, l, child)
+               {
+                  if (!child) continue;
+                  child->saved.layer = child->layer;
+                  child->layer = ec->parent->layer;
+               }
+          }
+
+        e_config->transient.raise = raise;
+     }
+
+   if (ec->transient_policy == E_TRANSIENT_ABOVE)
+     {
+        top = e_client_top_get();
+        while (top)
+          {
+             if ((!ec->parent->transients) || (top == ec->parent))
+               {
+                  top = NULL;
+                  break;
+               }
+             if ((top != ec) && (eina_list_data_find(ec->parent->transients, top)))
+               break;
+
+             top = e_client_below_get(top);
+          }
+
+        if (top)
+          evas_object_stack_above(ec->frame, top->frame);
+        else
+          evas_object_stack_above(ec->frame, ec->parent->frame);
+     }
+   else if (ec->transient_policy == E_TRANSIENT_BELOW)
+     {
+        evas_object_stack_below(ec->frame, ec->parent->frame);
+     }
+}
+
+Eina_Bool
+_e_policy_stack_transient_for_tree_check(E_Client *child, E_Client *parent)
+{
+   E_Client *p;
+
+   p = parent->parent;
+   while (p)
+     {
+        if (e_object_is_del(E_OBJECT(p))) return EINA_FALSE;
+        if (p == child) return EINA_TRUE;
+
+        p = p->parent;
+     }
+
+   return EINA_FALSE;
+}
+
+void
+e_policy_stack_hook_pre_post_fetch(E_Client *ec)
+{
+   E_Policy_Stack *ps;
+   ps = eina_hash_find(hash_pol_stack, &ec);
+
+   if (ps)
+     {
+        if ((ps->transient.win) && (ps->transient.fetched))
+          {
+             if ((ec->icccm.transient_for == ps->transient.win) &&
+                 (ec->parent))
+               _e_policy_stack_transient_for_apply(ec);
+             else
+               ps->transient.win = ec->icccm.transient_for;
+
+             ps->transient.fetched = 0;
+          }
+     }
+}
+
+void
+e_policy_stack_hook_pre_fetch(E_Client *ec)
+{
+   E_Policy_Stack *ps;
+   ps = eina_hash_find(hash_pol_stack, &ec);
+
+   if (ec->icccm.fetch.transient_for)
+     {
+        Ecore_Window transient_for_win = 0;
+        E_Client *parent = NULL;
+        Eina_Bool transient_each_other = EINA_FALSE;
+
+        parent = e_pixmap_find_client(E_PIXMAP_TYPE_WL, ec->icccm.transient_for);
+
+        if (parent)
+          {
+             if (!ps) ps = _e_policy_stack_data_add(ec);
+
+             ps->transient.win = e_client_util_win_get(parent);
+             ps->transient.fetched = 1;
+
+             /* clients transient for each other */
+             transient_each_other = _e_policy_stack_transient_for_tree_check(ec, parent);
+             if (transient_each_other)
+               {
+                  ec->icccm.transient_for = transient_for_win;
+                  ec->icccm.fetch.transient_for = 0;
+                  ps->transient.fetched = 0;
+                  parent = NULL;
+               }
+          }
+     }
+}
+
+void
+e_policy_stack_transient_for_set(E_Client *child, E_Client *parent)
+{
+   Ecore_Window pwin = 0;
+
+   EINA_SAFETY_ON_NULL_RETURN(child);
+
+   if (!parent)
+     {
+        child->icccm.fetch.transient_for = EINA_FALSE;
+        child->icccm.transient_for = 0;
+        if (child->parent)
+          {
+             child->parent->transients =
+                eina_list_remove(child->parent->transients, child);
+             if (child->parent->modal == child) child->parent->modal = NULL;
+             child->parent = NULL;
+          }
+        return;
+     }
+
+   pwin = e_client_util_win_get(parent);
+
+   /* If we already have a parent, remove it */
+   if (child->parent)
+     {
+        if (parent != child->parent)
+          {
+             child->parent->transients =
+                eina_list_remove(child->parent->transients, child);
+             if (child->parent->modal == child) child->parent->modal = NULL;
+             child->parent = NULL;
+          }
+        else
+          parent = NULL;
+     }
+
+   if ((parent) && (parent != child) &&
+       (eina_list_data_find(parent->transients, child) != child))
+     {
+        parent->transients = eina_list_append(parent->transients, child);
+        child->parent = parent;
+     }
+
+   child->icccm.fetch.transient_for = EINA_TRUE;
+   child->icccm.transient_for = pwin;
+}
+
+void
+e_policy_stack_cb_client_remove(E_Client *ec)
+{
+   _e_policy_stack_data_del(ec);
+}
+
+void
+e_policy_stack_shutdonw(void)
+{
+   eina_hash_free(hash_pol_stack);
+   hash_pol_stack = NULL;
+}
+
+void
+e_policy_stack_init(void)
+{
+   hash_pol_stack = eina_hash_pointer_new(_e_policy_stack_cb_data_free);
+}
+
+void
+e_policy_stack_below(E_Client *ec, E_Client *below_ec)
+{
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+   EINA_SAFETY_ON_NULL_RETURN(ec->frame);
+
+   EINA_SAFETY_ON_NULL_RETURN(below_ec);
+   EINA_SAFETY_ON_NULL_RETURN(below_ec->frame);
+
+   evas_object_stack_below(ec->frame, below_ec->frame);
+   if (e_config->transient.iconify)
+     {
+        E_Client *child;
+        Eina_List *list = eina_list_clone(ec->transients);
+
+        EINA_LIST_FREE(list, child)
+          {
+             e_policy_stack_below(child, below_ec);
+          }
+     }
+}
+
+static E_Client *
+_e_policy_stack_find_top_lockscreen(E_Client *ec_lock, E_Client *ec_except)
+{
+   E_Client *ec = NULL;
+   E_Client *ec_top_lock = NULL;
+   int x, y, w, h;
+
+   if (!ec_lock) return NULL;
+
+   E_CLIENT_REVERSE_FOREACH(ec)
+     {
+        if (e_object_is_del(E_OBJECT(ec))) continue;
+        if ((ec != ec_except) &&
+            (e_policy_client_is_lockscreen(ec)))
+          {
+             e_client_geometry_get(ec, &x, &y, &w, &h);
+             if (E_CONTAINS(ec->zone->x, ec->zone->y, ec->zone->w, ec->zone->h,
+                            x, y, w, h))
+               {
+                  ec_top_lock = ec;
+                  break;
+               }
+          }
+     }
+
+   return ec_top_lock;
+}
+
+void
+e_policy_stack_clients_restack_above_lockscreen(E_Client *ec_lock, Eina_Bool show)
+{
+   E_Client *ec = NULL;
+   E_Client *new_lock = NULL;
+   Eina_Bool restack_above = EINA_FALSE;
+
+   if (!ec_lock) return;
+
+   if (show)
+     {
+        new_lock = _e_policy_stack_find_top_lockscreen(ec_lock, NULL);
+        if (!new_lock)
+          new_lock = ec_lock;
+
+        e_policy_system_info.lockscreen.show = show;
+        e_policy_system_info.lockscreen.ec = new_lock;
+
+        restack_above = EINA_TRUE;
+     }
+   else
+     {
+        if (ec_lock != e_policy_system_info.lockscreen.ec)
+          return;
+
+        new_lock = _e_policy_stack_find_top_lockscreen(ec_lock, e_policy_system_info.lockscreen.ec);
+        if (new_lock)
+          {
+             e_policy_system_info.lockscreen.show = EINA_TRUE;
+             e_policy_system_info.lockscreen.ec = new_lock;
+             restack_above = EINA_TRUE;
+          }
+        else
+          {
+             E_Layer org_layer;
+             Eina_List *restore_list = NULL;
+             Eina_List *l = NULL;
+
+             e_policy_system_info.lockscreen.show = show;
+             e_policy_system_info.lockscreen.ec = NULL;
+
+             E_CLIENT_FOREACH(ec)
+               {
+                  if (e_object_is_del(E_OBJECT(ec))) continue;
+                  if (ec->changable_layer[E_CHANGABLE_LAYER_TYPE_ABOVE_NOTIFICATION].set &&
+                      ec->changable_layer[E_CHANGABLE_LAYER_TYPE_ABOVE_NOTIFICATION].saved)
+                    {
+                       restore_list = eina_list_append(restore_list, ec);
+                    }
+               }
+
+             if (restore_list)
+               {
+                  EINA_LIST_FOREACH(restore_list, l, ec)
+                    {
+                       org_layer = ec->changable_layer[E_CHANGABLE_LAYER_TYPE_ABOVE_NOTIFICATION].saved_layer;
+                       ELOGF("CHANGE to Original layer", "AboveLock|layer: %d -> %d", ec->pixmap, ec, ec->layer, org_layer);
+                       evas_object_layer_set(ec->frame, org_layer);
+                       ec->layer = org_layer;
+
+                       ec->changable_layer[E_CHANGABLE_LAYER_TYPE_ABOVE_NOTIFICATION].saved = EINA_FALSE;
+                       ec->changable_layer[E_CHANGABLE_LAYER_TYPE_ABOVE_NOTIFICATION].saved_layer = 0;
+                    }
+                  eina_list_free(restore_list);
+                  restore_list = NULL;
+               }
+          }
+     }
+
+   if (restack_above)
+     {
+        Eina_List *restack_list = NULL;
+        Eina_List *l = NULL;
+        E_Layer lock_layer = e_policy_system_info.lockscreen.ec->layer;
+        Eina_Bool passed_new_lock = EINA_FALSE;
+        int x, y, w, h;
+
+        E_CLIENT_REVERSE_FOREACH(ec)
+          {
+             if (e_object_is_del(E_OBJECT(ec))) continue;
+             if (ec == new_lock)
+               {
+                  passed_new_lock = EINA_TRUE;
+                  continue;
+               }
+             if (!passed_new_lock) continue;
+             if (e_policy_client_is_lockscreen(ec)) continue;
+             if (ec->exp_iconify.by_client) continue;
+
+             if (ec->changable_layer[E_CHANGABLE_LAYER_TYPE_ABOVE_NOTIFICATION].set)
+               {
+                  if (ec->layer <= lock_layer)
+                    {
+                       restack_list = eina_list_append(restack_list, ec);
+                    }
+               }
+
+             if ((!ec->argb) ||
+                 ((ec->argb) &&
+                  (ec->visibility.opaque == 1)))
+               {
+                  e_client_geometry_get(ec, &x, &y, &w, &h);
+                  if (E_CONTAINS(x, y, w, h, ec->zone->x, ec->zone->y, ec->zone->w, ec->zone->h))
+                    {
+                       break;
+                    }
+               }
+          }
+
+        if (restack_list)
+          {
+             EINA_LIST_REVERSE_FOREACH(restack_list, l, ec)
+               {
+                  if (ec->changable_layer[E_CHANGABLE_LAYER_TYPE_ABOVE_NOTIFICATION].saved == EINA_FALSE)
+                    {
+                       ec->changable_layer[E_CHANGABLE_LAYER_TYPE_ABOVE_NOTIFICATION].saved = EINA_TRUE;
+                       ec->changable_layer[E_CHANGABLE_LAYER_TYPE_ABOVE_NOTIFICATION].saved_layer = ec->layer;
+                    }
+
+                  ELOGF("CHANGE to Lockscreen layer", "AboveLock|layer: %d -> %d", ec->pixmap, ec, ec->layer, lock_layer);
+                  if (ec->layer == lock_layer)
+                    evas_object_raise(ec->frame);
+                  else
+                    evas_object_layer_set(ec->frame, lock_layer);
+
+                  ec->layer = lock_layer;
+               }
+             eina_list_free(restack_list);
+             restack_list = NULL;
+          }
+     }
+
+}
+
+Eina_Bool
+e_policy_stack_check_above_lockscreen(E_Client *ec, E_Layer layer, E_Layer *new_layer, Eina_Bool set_layer)
+{
+   E_Layer lock_layer;
+
+   if (!ec) return EINA_FALSE;
+   if (!ec->changable_layer[E_CHANGABLE_LAYER_TYPE_ABOVE_NOTIFICATION].set)
+     return EINA_FALSE;
+
+   if (e_policy_system_info.lockscreen.show &&
+       e_policy_system_info.lockscreen.ec)
+     {
+        lock_layer = e_policy_system_info.lockscreen.ec->layer;
+        if (layer <= lock_layer)
+          {
+             if (ec->changable_layer[E_CHANGABLE_LAYER_TYPE_ABOVE_NOTIFICATION].saved == EINA_FALSE)
+               {
+                  ec->changable_layer[E_CHANGABLE_LAYER_TYPE_ABOVE_NOTIFICATION].saved = EINA_TRUE;
+                  ec->changable_layer[E_CHANGABLE_LAYER_TYPE_ABOVE_NOTIFICATION].saved_layer = ec->layer;
+               }
+
+             if (set_layer)
+               {
+                  ELOGF("CHANGE to Lockscreen layer", "AboveLock|layer: %d -> %d", ec->pixmap, ec, ec->layer, lock_layer);
+                  if (ec->layer == lock_layer)
+                    evas_object_raise(ec->frame);
+                  else
+                    evas_object_layer_set(ec->frame, lock_layer);
+                  ec->layer = lock_layer;
+               }
+
+             if (new_layer)
+               *new_layer = lock_layer;
+          }
+        else
+          {
+             if (set_layer)
+               {
+                  if (ec->layer != layer)
+                    {
+                       ELOGF("CHANGE to Lockscreen layer", "AboveLock|layer: %d -> %d", ec->pixmap, ec, ec->layer, lock_layer);
+                       evas_object_layer_set(ec->frame, lock_layer);
+                       ec->layer = lock_layer;
+                    }
+               }
+
+             if (new_layer)
+               *new_layer = layer;
+          }
+
+        return EINA_TRUE;
+     }
+
+   return EINA_FALSE;
+
+}
+
diff --git a/src/bin/e_policy_transform_mode.c b/src/bin/e_policy_transform_mode.c
new file mode 100644 (file)
index 0000000..daaad58
--- /dev/null
@@ -0,0 +1,395 @@
+#include "e.h"
+#include "e_policy_transform_mode.h"
+
+#define E_TRANSFORM_MODE_NAME         "wm.policy.win.transform.mode"
+#define E_TRANSFORM_MODE_AUTOFIT      "autofit"
+#define E_TRANSFORM_MODE_RATIOFIT     "ratiofit"
+
+typedef struct _E_Mod_Transform_Client     E_Mod_Transform_Client;
+typedef struct _E_Mod_Transform_Manager    E_Mod_Transform_Manager;
+
+typedef enum
+{
+   E_Mod_Transform_Type_None = 0,
+   E_Mod_Transform_Type_AutoFit,
+   E_Mod_Transform_Type_RatioFit
+
+}E_Mod_Transform_Type;
+
+struct _E_Mod_Transform_Client
+{
+   E_Client             *ec;
+   E_Util_Transform     *transform;
+   Eina_Bool             user_geometry_by_me;
+   E_Mod_Transform_Type  transform_type;
+   int x, y, w, h;
+};
+
+struct _E_Mod_Transform_Manager
+{
+   Eina_List *transform_client_list;
+   Eina_List *hook_list;
+   Eina_List *event_list;
+};
+
+static E_Mod_Transform_Manager *_transform_mode = NULL;
+
+static E_Mod_Transform_Client    *_e_policy_transform_client_new(E_Client *ec, E_Mod_Transform_Manager *mng);
+static void                       _e_policy_transform_client_del(E_Mod_Transform_Client *transform_ec, E_Mod_Transform_Manager *mng);
+static E_Mod_Transform_Client    *_e_policy_transform_client_find(E_Client *ec, E_Mod_Transform_Manager *mng);
+static void                       _e_policy_transform_client_mode_change(E_Mod_Transform_Client *transform_ec, E_Mod_Transform_Type mode);
+static void                       _e_policy_transform_client_mode_cancel(E_Mod_Transform_Client *transform_ec);
+static void                       _e_policy_transform_client_mode_autofit_ratiofit_set(E_Mod_Transform_Client *transform_ec, E_Mod_Transform_Type mode);
+static void                       _e_policy_transform_client_mode_autofit_ratiofit_cancel(E_Mod_Transform_Client *transform_ec);
+
+static void                       _e_policy_transform_cb_aux_change(void *data, E_Client *ec);
+static void                       _e_policy_transform_cb_client_del(void *data, E_Client *ec);
+static void                       _e_policy_transform_cb_client_move_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
+
+
+static E_Mod_Transform_Type       _e_policy_transform_mode_string_to_enum(const char *str_mode);
+static void                       _e_policy_transform_screen_size_get(E_Mod_Transform_Client *transform_ec, int *w, int *h);
+static void                       _e_policy_transform_client_size_get(E_Mod_Transform_Client *transform_ec, int *w, int *h);
+static void                       _e_policy_transform_client_pos_get(E_Mod_Transform_Client *transform_ec, int *x, int *y);
+static Eina_Bool                  _e_policy_transform_client_geometry_change_check(E_Mod_Transform_Client *transform_ec);
+
+Eina_Bool
+e_policy_transform_mode_init(void)
+{
+   if (_transform_mode) return EINA_FALSE;
+
+   _transform_mode = (E_Mod_Transform_Manager*)malloc(sizeof(E_Mod_Transform_Manager));
+   memset(_transform_mode, 0, sizeof(E_Mod_Transform_Manager));
+
+   _transform_mode->hook_list = eina_list_append(_transform_mode->hook_list,
+                                                 e_client_hook_add(E_CLIENT_HOOK_AUX_HINT_CHANGE ,
+                                                                   _e_policy_transform_cb_aux_change,
+                                                                   _transform_mode));
+
+   _transform_mode->hook_list = eina_list_append(_transform_mode->hook_list,
+                                                 e_client_hook_add(E_CLIENT_HOOK_DEL ,
+                                                                   _e_policy_transform_cb_client_del,
+                                                                   _transform_mode));
+
+   e_hints_aux_hint_supported_add(E_TRANSFORM_MODE_NAME);
+   return EINA_TRUE;
+}
+
+void
+e_policy_transform_mode_shutdown(void)
+{
+   if (!_transform_mode) return;
+
+   while(_transform_mode->transform_client_list)
+     {
+        _e_policy_transform_client_del(eina_list_nth(_transform_mode->transform_client_list, 0), _transform_mode);
+     }
+
+   if (_transform_mode->hook_list)
+     {
+        E_Client_Hook *hook;
+
+        EINA_LIST_FREE(_transform_mode->hook_list, hook)
+          {
+             e_client_hook_del(hook);
+          }
+     }
+
+   free(_transform_mode);
+   _transform_mode = NULL;
+
+   e_hints_aux_hint_supported_del(E_TRANSFORM_MODE_NAME);
+}
+
+static E_Mod_Transform_Client*
+_e_policy_transform_client_new(E_Client *ec, E_Mod_Transform_Manager *mng)
+{
+   E_Mod_Transform_Client *result = NULL;
+
+   if (!mng) return NULL;
+   if (!ec) return NULL;
+   if (_e_policy_transform_client_find(ec, mng)) return NULL;
+
+   result = (E_Mod_Transform_Client*)malloc(sizeof(E_Mod_Transform_Client));
+   memset(result, 0, sizeof(E_Mod_Transform_Client));
+   result->ec = ec;
+   result->transform = e_util_transform_new();
+
+   mng->transform_client_list = eina_list_append(mng->transform_client_list, result);
+   return result;
+}
+
+static void
+_e_policy_transform_client_del(E_Mod_Transform_Client *transform_ec, E_Mod_Transform_Manager *mng)
+{
+   if (!mng) return;
+   if (!transform_ec) return;
+
+   if (transform_ec->transform)
+     {
+        _e_policy_transform_client_mode_cancel(transform_ec);
+        e_util_transform_del(transform_ec->transform);
+        transform_ec->transform = NULL;
+     }
+
+   mng->transform_client_list = eina_list_remove(mng->transform_client_list, transform_ec);
+   free(transform_ec);
+}
+
+static E_Mod_Transform_Client*
+_e_policy_transform_client_find(E_Client *ec, E_Mod_Transform_Manager *mng)
+{
+   E_Mod_Transform_Client *temp = NULL;
+   E_Mod_Transform_Client *result = NULL;
+   Eina_List *l = NULL;
+
+   if (!mng) return NULL;
+   if (!ec) return NULL;
+
+   EINA_LIST_FOREACH(mng->transform_client_list, l, temp)
+     {
+        if (temp->ec == ec)
+          {
+             result = temp;
+             break;
+          }
+     }
+   return result;
+}
+
+static void
+_e_policy_transform_client_mode_change(E_Mod_Transform_Client *transform_ec, E_Mod_Transform_Type mode)
+{
+   if (!transform_ec) return;
+   if (mode == E_Mod_Transform_Type_None) return;
+
+   if (transform_ec->transform_type != mode)
+     {
+        _e_policy_transform_client_mode_cancel(transform_ec);
+
+        if (mode == E_Mod_Transform_Type_AutoFit ||
+            mode == E_Mod_Transform_Type_RatioFit)
+          {
+             _e_policy_transform_client_mode_autofit_ratiofit_set(transform_ec, mode);
+          }
+     }
+}
+
+static void
+_e_policy_transform_client_mode_cancel(E_Mod_Transform_Client *transform_ec)
+{
+   if (!transform_ec) return;
+   if (transform_ec->transform_type == E_Mod_Transform_Type_None) return;
+
+   if (transform_ec->transform_type == E_Mod_Transform_Type_AutoFit ||
+       transform_ec->transform_type == E_Mod_Transform_Type_RatioFit)
+     {
+        _e_policy_transform_client_mode_autofit_ratiofit_cancel(transform_ec);
+     }
+
+   transform_ec->transform_type = E_Mod_Transform_Type_None;
+}
+
+static void
+_e_policy_transform_client_mode_autofit_ratiofit_set(E_Mod_Transform_Client *transform_ec,  E_Mod_Transform_Type mode)
+{
+   if (!transform_ec) return;
+   if (transform_ec->transform_type != E_Mod_Transform_Type_None) return;
+
+   if (transform_ec->transform)
+     {
+        if (mode == E_Mod_Transform_Type_RatioFit)
+           e_util_transform_keep_ratio_set(transform_ec->transform, EINA_TRUE);
+        e_client_transform_core_add(transform_ec->ec, transform_ec->transform);
+     }
+   _e_policy_transform_cb_client_move_resize(transform_ec, 0, 0, 0);
+
+   if (transform_ec->ec->frame)
+     {
+        evas_object_event_callback_add(transform_ec->ec->frame, EVAS_CALLBACK_RESIZE, _e_policy_transform_cb_client_move_resize, transform_ec);
+        evas_object_event_callback_add(transform_ec->ec->frame, EVAS_CALLBACK_MOVE, _e_policy_transform_cb_client_move_resize, transform_ec);
+     }
+
+   e_policy_allow_user_geometry_set(transform_ec->ec, EINA_TRUE);
+   transform_ec->transform_type = mode;
+}
+
+static void
+_e_policy_transform_client_mode_autofit_ratiofit_cancel(E_Mod_Transform_Client *transform_ec)
+{
+   if (!transform_ec) return;
+   if (transform_ec->transform_type != E_Mod_Transform_Type_AutoFit &&
+       transform_ec->transform_type != E_Mod_Transform_Type_RatioFit) return;
+
+   if (transform_ec->transform)
+     {
+        e_util_transform_keep_ratio_set(transform_ec->transform, EINA_FALSE);
+        e_client_transform_core_remove(transform_ec->ec, transform_ec->transform);
+     }
+
+   if (transform_ec->ec->frame)
+     {
+        evas_object_event_callback_del(transform_ec->ec->frame, EVAS_CALLBACK_RESIZE, _e_policy_transform_cb_client_move_resize);
+        evas_object_event_callback_del(transform_ec->ec->frame, EVAS_CALLBACK_MOVE, _e_policy_transform_cb_client_move_resize);
+     }
+
+   e_policy_allow_user_geometry_set(transform_ec->ec, EINA_FALSE);
+   transform_ec->transform_type = E_Mod_Transform_Type_None;
+}
+
+static void
+_e_policy_transform_cb_aux_change(void *data, E_Client *ec)
+{
+   E_Mod_Transform_Manager *mng = (E_Mod_Transform_Manager*)data;
+   E_Mod_Transform_Client  *t_ec = NULL;
+   E_Mod_Transform_Type     t_mode = E_Mod_Transform_Type_None;
+   const char              *t_str = NULL;
+
+   if (!ec) return;
+   if (!mng) return;
+
+   t_ec = _e_policy_transform_client_find(ec, mng);
+   t_str = e_hints_aux_hint_value_get(ec, E_TRANSFORM_MODE_NAME);
+   t_mode = _e_policy_transform_mode_string_to_enum(t_str);
+
+   if (t_ec)
+     {
+        if (t_mode == E_Mod_Transform_Type_None)
+           _e_policy_transform_client_del(t_ec, mng);
+        else
+           _e_policy_transform_client_mode_change(t_ec, t_mode);
+     }
+   else
+     {
+        if (t_mode != E_Mod_Transform_Type_None)
+          {
+             t_ec = _e_policy_transform_client_new(ec, mng);
+             _e_policy_transform_client_mode_change(t_ec, t_mode);
+          }
+     }
+}
+
+static void
+_e_policy_transform_cb_client_del(void *data, E_Client *ec)
+{
+   E_Mod_Transform_Manager *mng = (E_Mod_Transform_Manager*)data;
+   E_Mod_Transform_Client *transform_ec = NULL;
+
+   if (!mng) return;
+   if (!ec) return;
+
+   transform_ec = _e_policy_transform_client_find(ec, mng);
+
+   if (transform_ec)
+      _e_policy_transform_client_del(transform_ec, mng);
+}
+
+static void
+_e_policy_transform_cb_client_move_resize(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   E_Mod_Transform_Client *transform_ec = (E_Mod_Transform_Client*)data;
+   int zone_w = 1, zone_h = 1;
+   double sx = 1.0, sy = 1.0;
+   int w = 1, h = 1;
+   int x, y;
+
+   if (!transform_ec) return;
+   if (!_e_policy_transform_client_geometry_change_check(transform_ec)) return;
+
+   _e_policy_transform_screen_size_get(transform_ec, &zone_w, &zone_h);
+   _e_policy_transform_client_size_get(transform_ec, &w, &h);
+   _e_policy_transform_client_pos_get(transform_ec, &x, &y);
+
+   sx = (double) zone_w / (double) w;
+   sy = (double) zone_h / (double) h;
+
+   e_util_transform_init(transform_ec->transform);
+   if (transform_ec->transform_type == E_Mod_Transform_Type_RatioFit)
+      e_util_transform_keep_ratio_set(transform_ec->transform, EINA_TRUE);
+   e_util_transform_move(transform_ec->transform, -x, -y, 0.0);
+   e_util_transform_scale(transform_ec->transform, sx, sy, 1.0);
+}
+
+static E_Mod_Transform_Type
+_e_policy_transform_mode_string_to_enum(const char *str_mode)
+{
+   if (!str_mode)                                                   return E_Mod_Transform_Type_None;
+   else if (!e_util_strcmp(str_mode, E_TRANSFORM_MODE_AUTOFIT))     return E_Mod_Transform_Type_AutoFit;
+   else if (!e_util_strcmp(str_mode, E_TRANSFORM_MODE_RATIOFIT))    return E_Mod_Transform_Type_RatioFit;
+
+   return E_Mod_Transform_Type_None;
+}
+
+static void
+_e_policy_transform_screen_size_get(E_Mod_Transform_Client *transform_ec, int *w, int *h)
+{
+   int zone_w = 1;
+   int zone_h = 1;
+
+   if (!transform_ec) return;
+
+   if (transform_ec->ec->zone)
+     {
+        zone_w = transform_ec->ec->zone->w;
+        zone_h = transform_ec->ec->zone->h;
+     }
+   else
+     {
+        zone_w = 1920;
+        zone_h = 1080;
+     }
+
+   if (zone_w < 1) zone_w = 1;
+   if (zone_h < 1) zone_h = 1;
+
+   if (w) *w = zone_w;
+   if (h) *h = zone_h;
+}
+
+static void
+_e_policy_transform_client_size_get(E_Mod_Transform_Client *transform_ec, int *w, int *h)
+{
+   int ec_w = 1;
+   int ec_h = 1;
+
+   if (!transform_ec) return;
+
+   ec_w = transform_ec->ec->w;
+   ec_h = transform_ec->ec->h;
+
+   if (ec_w < 1) ec_w = 1;
+   if (ec_h < 1) ec_h = 1;
+
+   if (w) *w = ec_w;
+   if (h) *h = ec_h;
+}
+
+static void
+_e_policy_transform_client_pos_get(E_Mod_Transform_Client *transform_ec, int *x, int *y)
+{
+   if (!transform_ec) return;
+
+   if (x) *x = transform_ec->ec->x;
+   if (y) *y = transform_ec->ec->y;
+
+}
+
+static Eina_Bool
+_e_policy_transform_client_geometry_change_check(E_Mod_Transform_Client *transform_ec)
+{
+   if (!transform_ec) return EINA_FALSE;
+   if (transform_ec->ec->x != transform_ec->x ||
+       transform_ec->ec->y != transform_ec->y ||
+       transform_ec->ec->w != transform_ec->w ||
+       transform_ec->ec->h != transform_ec->h)
+     {
+        transform_ec->x = transform_ec->ec->x;
+        transform_ec->y = transform_ec->ec->y;
+        transform_ec->w = transform_ec->ec->w;
+        transform_ec->h = transform_ec->ec->h;
+
+        return EINA_TRUE;
+     }
+
+   return EINA_FALSE;
+}
diff --git a/src/bin/e_policy_transform_mode.h b/src/bin/e_policy_transform_mode.h
new file mode 100644 (file)
index 0000000..45e82a5
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef E_POLICY_TRANSFORM_MODE_H
+#define E_POLICY_TRANSFORM_MODE_H
+
+#include "e.h"
+
+Eina_Bool e_policy_transform_mode_init(void);
+void      e_policy_transform_mode_shutdown(void);
+
+#endif /* end of E_POLICY_TRANSFORM_MODE_H */
diff --git a/src/bin/e_policy_visibility.c b/src/bin/e_policy_visibility.c
new file mode 100644 (file)
index 0000000..25ec0d4
--- /dev/null
@@ -0,0 +1,284 @@
+#include "e.h"
+#include "e_comp_wl.h"
+#include "e_policy_wl.h"
+
+#ifdef ENABLE_TTRACE
+# include <ttrace.h>
+# undef TRACE_DS_BEGIN
+# undef TRACE_DS_END
+
+# define TRACE_DS_BEGIN(NAME) traceBegin(TTRACE_TAG_WINDOW_MANAGER, "DS:POL:"#NAME)
+# define TRACE_DS_END() traceEnd(TTRACE_TAG_WINDOW_MANAGER)
+#else
+# define TRACE_DS_BEGIN(NAME)
+# define TRACE_DS_END()
+#endif
+
+static Eina_Bool _e_policy_check_transient_child_visible(E_Client *ancestor_ec, E_Client *ec);
+static Eina_Bool _e_policy_check_above_alpha_opaque(E_Client *ec);
+static void      _e_policy_client_iconify_by_visibility(E_Client *ec);
+static void      _e_policy_client_ancestor_uniconify(E_Client *ec);
+static void      _e_policy_client_below_uniconify(E_Client *ec);
+static void      _e_policy_client_uniconify_by_visibility(E_Client *ec);
+
+static Eina_Bool
+_e_policy_check_transient_child_visible(E_Client *ancestor_ec, E_Client *ec)
+{
+   Eina_Bool visible = EINA_FALSE;
+   Eina_List *list = NULL;
+   E_Client *child_ec = NULL;
+   int anc_x, anc_y, anc_w, anc_h;
+   int child_x, child_y, child_w, child_h;
+
+   if (!ancestor_ec) return EINA_FALSE;
+
+   e_client_geometry_get(ancestor_ec, &anc_x, &anc_y, &anc_w, &anc_h);
+
+   list = eina_list_clone(ec->transients);
+   EINA_LIST_FREE(list, child_ec)
+     {
+        if (visible == EINA_TRUE) continue;
+
+        if (child_ec->exp_iconify.skip_iconify == EINA_TRUE)
+          {
+             if (child_ec->visibility.obscured == E_VISIBILITY_UNOBSCURED)
+               {
+                  return EINA_TRUE;
+               }
+             else
+               {
+                  if (!child_ec->iconic)
+                    {
+                       e_client_geometry_get(child_ec, &child_x, &child_y, &child_w, &child_h);
+                       if (E_CONTAINS(child_x, child_y, child_w, child_h, anc_x, anc_y, anc_w, anc_h))
+                         {
+                            return EINA_TRUE;
+                         }
+                    }
+               }
+          }
+        else
+          {
+             if ((!child_ec->iconic) ||
+                 (child_ec->visibility.obscured == E_VISIBILITY_UNOBSCURED))
+               {
+                  return EINA_TRUE;
+               }
+          }
+
+        visible = _e_policy_check_transient_child_visible(ancestor_ec, child_ec);
+     }
+
+   return visible;
+}
+
+static Eina_Bool
+_e_policy_check_above_alpha_opaque(E_Client *ec)
+{
+   E_Client *above_ec;
+   Evas_Object *o;
+   Eina_Bool alpha_opaque = EINA_FALSE;
+
+   for (o = evas_object_above_get(ec->frame); o; o = evas_object_above_get(o))
+     {
+        above_ec = evas_object_data_get(o, "E_Client");
+        if (!above_ec) continue;
+        if (e_client_util_ignored_get(above_ec)) continue;
+        if (!E_CONTAINS(above_ec->x, above_ec->y, above_ec->w, above_ec->h, ec->x, ec->y, ec->w, ec->h)) continue;
+
+        if ((above_ec->visibility.opaque > 0) && (above_ec->argb))
+          {
+             if (above_ec->visibility.obscured == E_VISIBILITY_UNOBSCURED)
+               {
+                  alpha_opaque = EINA_TRUE;
+               }
+             else
+               {
+                  if (!above_ec->iconic)
+                    {
+                       alpha_opaque = EINA_TRUE;
+                    }
+               }
+          }
+        break;
+     }
+
+   return alpha_opaque;
+}
+
+static void
+_e_policy_client_iconify_by_visibility(E_Client *ec)
+{
+   Eina_Bool do_iconify = EINA_TRUE;
+
+   if (!ec) return;
+   if (ec->iconic) return;
+   if (ec->exp_iconify.by_client) return;
+   if (ec->exp_iconify.skip_iconify) return;
+
+   E_Comp_Wl_Client_Data *cdata = (E_Comp_Wl_Client_Data *)ec->comp_data;
+   if (cdata && !cdata->mapped) return;
+
+   if (e_config->transient.iconify)
+     {
+        if (_e_policy_check_transient_child_visible(ec, ec))
+          {
+             do_iconify = EINA_FALSE;
+          }
+     }
+
+   if (ec->zone->display_state != E_ZONE_DISPLAY_STATE_OFF)
+     {
+        // check above window is alpha opaque or not
+        if (_e_policy_check_above_alpha_opaque(ec))
+          {
+             do_iconify = EINA_FALSE;
+          }
+     }
+
+   if (!do_iconify)
+     {
+        ELOGF("SKIP.. ICONIFY_BY_WM", "win:0x%08x", ec->pixmap, ec, e_client_util_win_get(ec));
+        return;
+     }
+
+   ELOGF("ICONIFY_BY_WM", "win:0x%08x", ec->pixmap, ec, e_client_util_win_get(ec));
+   e_policy_wl_iconify_state_change_send(ec, 1);
+   e_client_iconify(ec);
+
+   /* if client has obscured parent, try to iconify the parent also */
+   if (ec->parent)
+     {
+        if (ec->parent->visibility.obscured == E_VISIBILITY_FULLY_OBSCURED)
+          _e_policy_client_iconify_by_visibility(ec->parent);
+     }
+}
+
+static void
+_e_policy_client_ancestor_uniconify(E_Client *ec)
+{
+   Eina_List *list = NULL;
+   Eina_List *l = NULL;
+   E_Client *parent = NULL;
+   int transient_iconify = 0;
+   int count = 0;
+
+   if (!ec) return;
+   if (e_object_is_del(E_OBJECT(ec))) return;
+   if (!ec->iconic) return;
+   if (ec->exp_iconify.by_client) return;
+   if (ec->exp_iconify.skip_iconify) return;
+
+   parent = ec->parent;
+   while (parent)
+     {
+        if (count > 10)
+          {
+             // something strange state.
+             ELOGF("CHECK transient_for tree", "win:0x%08x, parent:0x%08x", NULL, NULL, e_client_util_win_get(ec), e_client_util_win_get(parent));
+             break;
+          }
+
+        if (e_object_is_del(E_OBJECT(parent))) break;
+        if (!parent->iconic) break;
+        if (parent->exp_iconify.by_client) break;
+        if (parent->exp_iconify.skip_iconify) break;
+
+        if (eina_list_data_find(list, parent))
+          {
+             // very bad. there are loop for parenting
+             ELOGF("Very BAD. Circling transient_for window", "win:0x%08x, parent:0x%08x", NULL, NULL, e_client_util_win_get(ec), e_client_util_win_get(parent));
+             break;
+          }
+
+        list = eina_list_prepend(list, parent);
+        parent = parent->parent;
+
+        // for preventing infiniting loop
+        count++;
+     }
+
+   transient_iconify = e_config->transient.iconify;
+   e_config->transient.iconify = 0;
+
+   parent = NULL;
+   EINA_LIST_FOREACH(list, l, parent)
+     {
+        ELOGF("UNICONIFY_BY_WM", "parent_win:0x%08x", parent->pixmap, parent, e_client_util_win_get(parent));
+        parent->exp_iconify.not_raise = 1;
+        e_client_uniconify(parent);
+        e_policy_wl_iconify_state_change_send(parent, 0);
+     }
+   eina_list_free(list);
+
+   e_config->transient.iconify = transient_iconify;
+}
+
+static void
+_e_policy_client_below_uniconify(E_Client *ec)
+{
+   E_Client *below_ec;
+   Evas_Object *o;
+
+   for (o = evas_object_below_get(ec->frame); o; o = evas_object_below_get(o))
+     {
+        below_ec = evas_object_data_get(o, "E_Client");
+        if (!below_ec) continue;
+        if (e_client_util_ignored_get(below_ec)) continue;
+
+        if (ec->parent == below_ec) break;
+        if (!below_ec->iconic) break;
+
+        if (below_ec->visibility.obscured == E_VISIBILITY_FULLY_OBSCURED)
+          {
+             _e_policy_client_uniconify_by_visibility(below_ec);
+          }
+
+        break;
+     }
+}
+
+static void
+_e_policy_client_uniconify_by_visibility(E_Client *ec)
+{
+   if (!ec) return;
+   if (e_object_is_del(E_OBJECT(ec))) return;
+   if (!ec->iconic) return;
+   if (ec->exp_iconify.by_client) return;
+   if (ec->exp_iconify.skip_iconify) return;
+
+   E_Comp_Wl_Client_Data *cdata = (E_Comp_Wl_Client_Data *)ec->comp_data;
+   if (cdata && !cdata->mapped) return;
+
+   _e_policy_client_ancestor_uniconify(ec);
+
+   ELOGF("UNICONIFY_BY_WM", "win:0x%08x", ec->pixmap, ec, e_client_util_win_get(ec));
+   ec->exp_iconify.not_raise = 1;
+   e_client_uniconify(ec);
+   e_policy_wl_iconify_state_change_send(ec, 0);
+
+   if ((ec->visibility.opaque > 0) && (ec->argb))
+     {
+        _e_policy_client_below_uniconify(ec);
+     }
+}
+
+void
+e_policy_client_visibility_send(E_Client *ec)
+{
+   e_policy_wl_visibility_send(ec, ec->visibility.obscured);
+}
+
+void
+e_policy_client_iconify_by_visibility(E_Client *ec)
+{
+   if (!ec) return;
+   _e_policy_client_iconify_by_visibility(ec);
+}
+
+void
+e_policy_client_uniconify_by_visibility(E_Client *ec)
+{
+   if (!ec) return;
+   _e_policy_client_uniconify_by_visibility(ec);
+}
diff --git a/src/bin/e_policy_wl.c b/src/bin/e_policy_wl.c
new file mode 100644 (file)
index 0000000..1bfa0e7
--- /dev/null
@@ -0,0 +1,4448 @@
+#include "e_policy_wl.h"
+#include "e.h"
+#include "services/e_service_quickpanel.h"
+#include "services/e_service_volume.h"
+#include "services/e_service_lockscreen.h"
+#include "e_policy_wl_display.h"
+#include "e_policy_conformant.h"
+
+#include <device/display.h>
+#include <wayland-server.h>
+#include <tizen-extension-server-protocol.h>
+#include <tzsh_server.h>
+
+#ifdef HAVE_CYNARA
+# include <cynara-session.h>
+# include <cynara-client.h>
+# include <cynara-creds-socket.h>
+#endif
+
+#define PRIVILEGE_NOTIFICATION_LEVEL_SET "http://tizen.org/privilege/window.priority.set"
+#define PRIVILEGE_SCREEN_MODE_SET "http://tizen.org/privilege/display"
+#define PRIVILEGE_BRIGHTNESS_SET "http://tizen.org/privilege/display"
+
+#define APP_DEFINE_GROUP_NAME "effect"
+
+typedef enum _Tzsh_Srv_Role
+{
+   TZSH_SRV_ROLE_UNKNOWN = -1,
+   TZSH_SRV_ROLE_CALL,
+   TZSH_SRV_ROLE_VOLUME,
+   TZSH_SRV_ROLE_QUICKPANEL,
+   TZSH_SRV_ROLE_LOCKSCREEN,
+   TZSH_SRV_ROLE_INDICATOR,
+   TZSH_SRV_ROLE_TVSERVICE,
+   TZSH_SRV_ROLE_SCREENSAVER_MNG,
+   TZSH_SRV_ROLE_SCREENSAVER,
+   TZSH_SRV_ROLE_MAX
+} Tzsh_Srv_Role;
+
+typedef enum _Tzsh_Type
+{
+   TZSH_TYPE_UNKNOWN = 0,
+   TZSH_TYPE_SRV,
+   TZSH_TYPE_CLIENT
+} Tzsh_Type;
+
+typedef struct _E_Policy_Wl_Tzpol
+{
+   struct wl_resource *res_tzpol; /* tizen_policy_interface */
+   Eina_List          *psurfs;    /* list of E_Policy_Wl_Surface */
+   Eina_List          *pending_bg;
+} E_Policy_Wl_Tzpol;
+
+typedef struct _E_Policy_Wl_Tz_Dpy_Pol
+{
+   struct wl_resource *res_tz_dpy_pol;
+   Eina_List          *dpy_surfs;  // list of E_Policy_Wl_Dpy_Surface
+} E_Policy_Wl_Tz_Dpy_Pol;
+
+typedef struct _E_Policy_Wl_Tzsh
+{
+   struct wl_resource *res_tzsh; /* tizen_ws_shell_interface */
+   Tzsh_Type           type;
+   E_Pixmap           *cp;
+   E_Client           *ec;
+} E_Policy_Wl_Tzsh;
+
+typedef struct _E_Policy_Wl_Tzsh_Srv
+{
+   E_Policy_Wl_Tzsh        *tzsh;
+   struct wl_resource *res_tzsh_srv;
+   Tzsh_Srv_Role       role;
+   const char         *name;
+} E_Policy_Wl_Tzsh_Srv;
+
+typedef struct _E_Policy_Wl_Tzsh_Client
+{
+   E_Policy_Wl_Tzsh        *tzsh;
+   struct wl_resource *res_tzsh_client;
+   Eina_Bool           qp_client;
+} E_Policy_Wl_Tzsh_Client;
+
+typedef struct _E_Policy_Wl_Tzsh_Region
+{
+   E_Policy_Wl_Tzsh        *tzsh;
+   struct wl_resource *res_tzsh_reg;
+   Eina_Tiler         *tiler;
+   struct wl_listener  destroy_listener;
+} E_Policy_Wl_Tzsh_Region;
+
+typedef struct _E_Policy_Wl_Surface
+{
+   struct wl_resource *surf;
+   E_Policy_Wl_Tzpol       *tzpol;
+   E_Pixmap           *cp;
+   E_Client           *ec;
+   pid_t               pid;
+   Eina_Bool           pending_notilv;
+   int32_t             notilv;
+   Eina_List          *vislist; /* list of tizen_visibility_interface resources */
+   Eina_List          *poslist; /* list of tizen_position_inteface resources */
+   Eina_Bool           is_background;
+} E_Policy_Wl_Surface;
+
+typedef struct _E_Policy_Wl_Dpy_Surface
+{
+   E_Policy_Wl_Tz_Dpy_Pol  *tz_dpy_pol;
+   struct wl_resource *surf;
+   E_Client           *ec;
+   Eina_Bool           set;
+   int32_t             brightness;
+} E_Policy_Wl_Dpy_Surface;
+
+typedef struct _E_Policy_Wl_Tzlaunch
+{
+   struct wl_resource *res_tzlaunch;     /* tizen_launchscreen */
+   Eina_List          *imglist;          /* list of E_Policy_Wl_Tzlaunch_Img */
+} E_Policy_Wl_Tzlaunch;
+
+typedef struct _E_Policy_Wl_Tzlaunch_Img
+{
+   struct wl_resource  *res_tzlaunch_img; /* tizen_launch_image */
+   E_Policy_Wl_Tzlaunch     *tzlaunch;         /* launcher */
+
+   const char          *path;             /* image resource path */
+   uint32_t            type;              /* 0: image, 1: edc */
+   uint32_t            indicator;         /* 0: off, 1: on */
+   uint32_t            angle;             /* 0, 90, 180, 270 : rotation angle */
+   uint32_t            pid;
+
+   Evas_Object         *obj;              /* launch screen image */
+   E_Pixmap            *ep;               /* pixmap for launch screen client */
+   E_Client            *ec;               /* client for launch screen image */
+   Ecore_Timer         *timeout;          /* launch screen image hide timer */
+
+   Eina_Bool           valid;
+} E_Policy_Wl_Tzlaunch_Img;
+
+typedef enum _E_Launch_Img_File_type
+{
+   E_LAUNCH_FILE_TYPE_ERROR = -1,
+   E_LAUNCH_FILE_TYPE_IMAGE = 0,
+   E_LAUNCH_FILE_TYPE_EDJ
+} E_Launch_Img_File_type;
+
+typedef struct _E_Policy_Wl
+{
+   Eina_List       *globals;                 /* list of wl_global */
+   Eina_Hash       *tzpols;                  /* list of E_Policy_Wl_Tzpol */
+
+   Eina_List       *tz_dpy_pols;             /* list of E_Policy_Wl_Tz_Dpy_Pol */
+   Eina_List       *pending_vis;             /* list of clients that have pending visibility change*/
+
+   /* tizen_ws_shell_interface */
+   Eina_List       *tzshs;                   /* list of E_Policy_Wl_Tzsh */
+   Eina_List       *tzsh_srvs;               /* list of E_Policy_Wl_Tzsh_Srv */
+   Eina_List       *tzsh_clients;            /* list of E_Policy_Wl_Tzsh_Client */
+   E_Policy_Wl_Tzsh_Srv *srvs[TZSH_SRV_ROLE_MAX]; /* list of registered E_Policy_Wl_Tzsh_Srv */
+   Eina_List       *tvsrv_bind_list;         /* list of activated E_Policy_Wl_Tzsh_Client */
+
+   /* tizen_launchscreen_interface */
+   Eina_List       *tzlaunchs;                   /* list of E_Policy_Wl_Tzlaunch */
+#ifdef HAVE_CYNARA
+   cynara          *p_cynara;
+#endif
+} E_Policy_Wl;
+
+typedef struct _E_Tzsh_QP_Event
+{
+   int type;
+   int val;
+} E_Tzsh_QP_Event;
+
+static E_Policy_Wl *polwl = NULL;
+
+static Eina_List *handlers = NULL;
+static Eina_List *hooks_cw = NULL;
+static struct wl_resource *_scrsaver_mng_res = NULL; // TODO
+
+enum _E_Policy_Hint_Type
+{
+   E_POLICY_HINT_USER_GEOMETRY = 0,
+   E_POLICY_HINT_FIXED_RESIZE = 1,
+   E_POLICY_HINT_DEICONIFY_APPROVE_DISABLE = 2,
+   E_POLICY_HINT_ICONIFY = 3,
+   E_POLICY_HINT_ABOVE_LOCKSCREEN = 4,
+   E_POLICY_HINT_GESTURE_DISABLE = 5,
+   E_POLICY_HINT_EFFECT_DISABLE = 6,
+};
+
+static const char *hint_names[] =
+{
+   "wm.policy.win.user.geometry",
+   "wm.policy.win.fixed.resize",
+   "wm.policy.win.deiconify.approve.disable",
+   "wm.policy.win.iconify",
+   "wm.policy.win.above.lock",
+   "wm.policy.win.gesture.disable",
+   "wm.policy.win.effect.disable",
+};
+
+static void                _e_policy_wl_surf_del(E_Policy_Wl_Surface *psurf);
+static void                _e_policy_wl_tzsh_srv_register_handle(E_Policy_Wl_Tzsh_Srv *tzsh_srv);
+static void                _e_policy_wl_tzsh_srv_unregister_handle(E_Policy_Wl_Tzsh_Srv *tzsh_srv);
+static void                _e_policy_wl_tzsh_srv_state_broadcast(E_Policy_Wl_Tzsh_Srv *tzsh_srv, Eina_Bool reg);
+static void                _e_policy_wl_tzsh_srv_tvsrv_bind_update(void);
+static Eina_Bool           _e_policy_wl_e_client_is_valid(E_Client *ec);
+static E_Policy_Wl_Tzsh_Srv    *_e_policy_wl_tzsh_srv_add(E_Policy_Wl_Tzsh *tzsh, Tzsh_Srv_Role role, struct wl_resource *res_tzsh_srv, const char *name);
+static void                _e_policy_wl_tzsh_srv_del(E_Policy_Wl_Tzsh_Srv *tzsh_srv);
+static E_Policy_Wl_Tzsh_Client *_e_policy_wl_tzsh_client_add(E_Policy_Wl_Tzsh *tzsh, struct wl_resource *res_tzsh_client);
+static void                _e_policy_wl_tzsh_client_del(E_Policy_Wl_Tzsh_Client *tzsh_client);
+static void                _launchscreen_hide(uint32_t pid);
+static void                _launch_img_off(E_Policy_Wl_Tzlaunch_Img *tzlaunchimg);
+static void                _e_policy_wl_background_state_set(E_Policy_Wl_Surface *psurf, Eina_Bool state);
+
+// --------------------------------------------------------
+// E_Policy_Wl_Tzpol
+// --------------------------------------------------------
+static E_Policy_Wl_Tzpol *
+_e_policy_wl_tzpol_add(struct wl_resource *res_tzpol)
+{
+   E_Policy_Wl_Tzpol *tzpol;
+
+   tzpol = E_NEW(E_Policy_Wl_Tzpol, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(tzpol, NULL);
+
+   eina_hash_add(polwl->tzpols, &res_tzpol, tzpol);
+
+   tzpol->res_tzpol = res_tzpol;
+
+   return tzpol;
+}
+
+static void
+_e_policy_wl_tzpol_del(void *data)
+{
+   E_Policy_Wl_Tzpol *tzpol;
+   E_Policy_Wl_Surface *psurf;
+
+   tzpol = (E_Policy_Wl_Tzpol *)data;
+
+   EINA_LIST_FREE(tzpol->psurfs, psurf)
+     {
+        _e_policy_wl_surf_del(psurf);
+     }
+
+   tzpol->pending_bg = eina_list_free(tzpol->pending_bg);
+
+   memset(tzpol, 0x0, sizeof(E_Policy_Wl_Tzpol));
+   E_FREE(tzpol);
+}
+
+static E_Policy_Wl_Tzpol *
+_e_policy_wl_tzpol_get(struct wl_resource *res_tzpol)
+{
+   return (E_Policy_Wl_Tzpol *)eina_hash_find(polwl->tzpols, &res_tzpol);
+}
+
+static E_Policy_Wl_Surface *
+_e_policy_wl_tzpol_surf_find(E_Policy_Wl_Tzpol *tzpol, E_Client *ec)
+{
+   Eina_List *l;
+   E_Policy_Wl_Surface *psurf;
+
+   EINA_LIST_FOREACH(tzpol->psurfs, l, psurf)
+     {
+        if (psurf->ec == ec)
+          return psurf;
+     }
+
+   return NULL;
+}
+
+static Eina_List *
+_e_policy_wl_tzpol_surf_find_by_pid(E_Policy_Wl_Tzpol *tzpol, pid_t pid)
+{
+   Eina_List *surfs = NULL, *l;
+   E_Policy_Wl_Surface *psurf;
+
+   EINA_LIST_FOREACH(tzpol->psurfs, l, psurf)
+     {
+        if (psurf->pid == pid)
+          {
+             surfs = eina_list_append(surfs, psurf);
+          }
+     }
+
+   return surfs;
+}
+
+static Eina_Bool
+_e_policy_wl_surf_is_valid(E_Policy_Wl_Surface *psurf)
+{
+   E_Policy_Wl_Tzpol *tzpol;
+   E_Policy_Wl_Surface *psurf2;
+   Eina_Iterator *it;
+   Eina_List *l;
+
+   it = eina_hash_iterator_data_new(polwl->tzpols);
+   EINA_ITERATOR_FOREACH(it, tzpol)
+     EINA_LIST_FOREACH(tzpol->psurfs, l, psurf2)
+       {
+          if (psurf2 == psurf)
+            {
+               eina_iterator_free(it);
+               return EINA_TRUE;
+            }
+       }
+   eina_iterator_free(it);
+
+   return EINA_FALSE;
+}
+
+// --------------------------------------------------------
+// E_Policy_Wl_Tzsh
+// --------------------------------------------------------
+static E_Policy_Wl_Tzsh *
+_e_policy_wl_tzsh_add(struct wl_resource *res_tzsh)
+{
+   E_Policy_Wl_Tzsh *tzsh;
+
+   tzsh = E_NEW(E_Policy_Wl_Tzsh, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(tzsh, NULL);
+
+   tzsh->res_tzsh = res_tzsh;
+   tzsh->type = TZSH_TYPE_UNKNOWN;
+
+   polwl->tzshs = eina_list_append(polwl->tzshs, tzsh);
+
+   return tzsh;
+}
+
+static void
+_e_policy_wl_tzsh_del(E_Policy_Wl_Tzsh *tzsh)
+{
+   E_Policy_Wl_Tzsh_Srv *tzsh_srv;
+   E_Policy_Wl_Tzsh_Client *tzsh_client;
+   Eina_List *l, *ll;
+
+   polwl->tzshs = eina_list_remove(polwl->tzshs, tzsh);
+
+   if (tzsh->type == TZSH_TYPE_SRV)
+     {
+        EINA_LIST_FOREACH_SAFE(polwl->tzsh_srvs, l, ll, tzsh_srv)
+          {
+             if (tzsh_srv->tzsh != tzsh) continue;
+             _e_policy_wl_tzsh_srv_del(tzsh_srv);
+             break;
+          }
+     }
+   else
+     {
+        EINA_LIST_FOREACH_SAFE(polwl->tzsh_clients, l, ll, tzsh_client)
+          {
+             if (tzsh_client->tzsh != tzsh) continue;
+             _e_policy_wl_tzsh_client_del(tzsh_client);
+             break;
+          }
+     }
+
+   memset(tzsh, 0x0, sizeof(E_Policy_Wl_Tzsh));
+   E_FREE(tzsh);
+}
+
+static void
+_e_policy_wl_tzsh_data_set(E_Policy_Wl_Tzsh *tzsh, Tzsh_Type type, E_Pixmap *cp, E_Client *ec)
+{
+   tzsh->type = type;
+   tzsh->cp = cp;
+   tzsh->ec = ec;
+}
+
+/* notify current registered services to the client */
+static void
+_e_policy_wl_tzsh_registered_srv_send(E_Policy_Wl_Tzsh *tzsh)
+{
+   int i;
+
+   for (i = 0; i < TZSH_SRV_ROLE_MAX; i++)
+     {
+        if (!polwl->srvs[i]) continue;
+
+        tizen_ws_shell_send_service_register
+          (tzsh->res_tzsh, polwl->srvs[i]->name);
+     }
+}
+
+static E_Policy_Wl_Tzsh *
+_e_policy_wl_tzsh_get_from_client(E_Client *ec)
+{
+   E_Policy_Wl_Tzsh *tzsh = NULL;
+   Eina_List *l;
+
+   EINA_LIST_FOREACH(polwl->tzshs, l, tzsh)
+     {
+        if (tzsh->cp == ec->pixmap)
+          {
+             if ((tzsh->ec) &&
+                 (tzsh->ec != ec))
+               {
+                  ELOGF("TZSH",
+                        "CRI ERR!!|tzsh_cp:0x%08x|tzsh_ec:0x%08x|tzsh:0x%08x",
+                        ec->pixmap, ec,
+                        (unsigned int)tzsh->cp,
+                        (unsigned int)tzsh->ec,
+                        (unsigned int)tzsh);
+               }
+
+             return tzsh;
+          }
+     }
+
+   return NULL;
+}
+
+static E_Policy_Wl_Tzsh_Client *
+_e_policy_wl_tzsh_client_get_from_client(E_Client *ec)
+{
+   E_Policy_Wl_Tzsh_Client *tzsh_client = NULL;
+   Eina_List *l;
+
+   if (!ec) return NULL;
+   if (e_object_is_del(E_OBJECT(ec))) return NULL;
+
+   EINA_LIST_FOREACH(polwl->tzsh_clients, l, tzsh_client)
+     {
+        if (!tzsh_client->tzsh) continue;
+        if (!tzsh_client->tzsh->ec) continue;
+
+        if (tzsh_client->tzsh->cp == ec->pixmap)
+          {
+             if (tzsh_client->tzsh->ec != ec)
+               {
+                  ELOGF("TZSH",
+                        "CRI ERR!!|tzsh_cp:0x%08x|tzsh_ec:0x%08x|tzsh:0x%08x",
+                        ec->pixmap, ec,
+                        (unsigned int)tzsh_client->tzsh->cp,
+                        (unsigned int)tzsh_client->tzsh->ec,
+                        (unsigned int)tzsh_client->tzsh);
+               }
+             return tzsh_client;
+          }
+     }
+
+   return NULL;
+}
+
+static E_Policy_Wl_Tzsh_Client *
+_e_policy_wl_tzsh_client_get_from_tzsh(E_Policy_Wl_Tzsh *tzsh)
+{
+   E_Policy_Wl_Tzsh_Client *tzsh_client;
+   Eina_List *l;
+
+   EINA_LIST_FOREACH(polwl->tvsrv_bind_list, l, tzsh_client)
+     {
+        if (tzsh_client->tzsh == tzsh)
+          return tzsh_client;
+     }
+
+   return NULL;
+}
+
+static void
+_e_policy_wl_tzsh_client_set(E_Client *ec)
+{
+   E_Policy_Wl_Tzsh *tzsh, *tzsh2;
+   E_Policy_Wl_Tzsh_Srv *tzsh_srv;
+
+   tzsh = _e_policy_wl_tzsh_get_from_client(ec);
+   if (!tzsh) return;
+
+   tzsh->ec = ec;
+
+   if (tzsh->type == TZSH_TYPE_SRV)
+     {
+        tzsh_srv = polwl->srvs[TZSH_SRV_ROLE_TVSERVICE];
+        if (tzsh_srv)
+          {
+             tzsh2 = tzsh_srv->tzsh;
+             if (tzsh2 == tzsh)
+               _e_policy_wl_tzsh_srv_register_handle(tzsh_srv);
+          }
+     }
+   else
+     {
+        if (_e_policy_wl_tzsh_client_get_from_tzsh(tzsh))
+          _e_policy_wl_tzsh_srv_tvsrv_bind_update();
+     }
+}
+
+static void
+_e_policy_wl_tzsh_client_unset(E_Client *ec)
+{
+   E_Policy_Wl_Tzsh *tzsh, *tzsh2;
+   E_Policy_Wl_Tzsh_Srv *tzsh_srv;
+
+   tzsh = _e_policy_wl_tzsh_get_from_client(ec);
+   if (!tzsh) return;
+
+   tzsh->ec = NULL;
+
+   if (tzsh->type == TZSH_TYPE_SRV)
+     {
+        tzsh_srv = polwl->srvs[TZSH_SRV_ROLE_TVSERVICE];
+        if (tzsh_srv)
+          {
+             tzsh2 = tzsh_srv->tzsh;
+             if (tzsh2 == tzsh)
+               _e_policy_wl_tzsh_srv_unregister_handle(tzsh_srv);
+          }
+     }
+   else
+     {
+        if (_e_policy_wl_tzsh_client_get_from_tzsh(tzsh))
+          _e_policy_wl_tzsh_srv_tvsrv_bind_update();
+     }
+}
+
+// --------------------------------------------------------
+// E_Policy_Wl_Tzsh_Srv
+// --------------------------------------------------------
+static E_Policy_Wl_Tzsh_Srv *
+_e_policy_wl_tzsh_srv_add(E_Policy_Wl_Tzsh *tzsh, Tzsh_Srv_Role role, struct wl_resource *res_tzsh_srv, const char *name)
+{
+   E_Policy_Wl_Tzsh_Srv *tzsh_srv;
+
+   tzsh_srv = E_NEW(E_Policy_Wl_Tzsh_Srv, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(tzsh_srv, NULL);
+
+   tzsh_srv->tzsh = tzsh;
+   tzsh_srv->res_tzsh_srv = res_tzsh_srv;
+   tzsh_srv->role = role;
+   tzsh_srv->name = eina_stringshare_add(name);
+
+   polwl->srvs[role] = tzsh_srv;
+   polwl->tzsh_srvs = eina_list_append(polwl->tzsh_srvs, tzsh_srv);
+
+   _e_policy_wl_tzsh_srv_register_handle(tzsh_srv);
+   _e_policy_wl_tzsh_srv_state_broadcast(tzsh_srv, EINA_TRUE);
+
+   return tzsh_srv;
+}
+
+static void
+_e_policy_wl_tzsh_srv_del(E_Policy_Wl_Tzsh_Srv *tzsh_srv)
+{
+   polwl->tzsh_srvs = eina_list_remove(polwl->tzsh_srvs, tzsh_srv);
+
+   if (polwl->srvs[tzsh_srv->role] == tzsh_srv)
+     polwl->srvs[tzsh_srv->role] = NULL;
+
+   _e_policy_wl_tzsh_srv_state_broadcast(tzsh_srv, EINA_TRUE);
+   _e_policy_wl_tzsh_srv_unregister_handle(tzsh_srv);
+
+   if (tzsh_srv->name)
+     eina_stringshare_del(tzsh_srv->name);
+
+   memset(tzsh_srv, 0x0, sizeof(E_Policy_Wl_Tzsh_Srv));
+   E_FREE(tzsh_srv);
+}
+
+static int
+_e_policy_wl_tzsh_srv_role_get(const char *name)
+{
+   Tzsh_Srv_Role role = TZSH_SRV_ROLE_UNKNOWN;
+
+   if      (!e_util_strcmp(name, "call"               )) role = TZSH_SRV_ROLE_CALL;
+   else if (!e_util_strcmp(name, "volume"             )) role = TZSH_SRV_ROLE_VOLUME;
+   else if (!e_util_strcmp(name, "quickpanel"         )) role = TZSH_SRV_ROLE_QUICKPANEL;
+   else if (!e_util_strcmp(name, "lockscreen"         )) role = TZSH_SRV_ROLE_LOCKSCREEN;
+   else if (!e_util_strcmp(name, "indicator"          )) role = TZSH_SRV_ROLE_INDICATOR;
+   else if (!e_util_strcmp(name, "tvsrv"              )) role = TZSH_SRV_ROLE_TVSERVICE;
+   else if (!e_util_strcmp(name, "screensaver_manager")) role = TZSH_SRV_ROLE_SCREENSAVER_MNG;
+   else if (!e_util_strcmp(name, "screensaver"        )) role = TZSH_SRV_ROLE_SCREENSAVER;
+
+   return role;
+}
+
+static E_Client *
+_e_policy_wl_tzsh_srv_parent_client_pick(void)
+{
+   E_Policy_Wl_Tzsh *tzsh = NULL;
+   E_Policy_Wl_Tzsh_Client *tzsh_client;
+   E_Client *ec = NULL, *ec2;
+   Eina_List *l;
+
+   EINA_LIST_REVERSE_FOREACH(polwl->tvsrv_bind_list, l, tzsh_client)
+     {
+        tzsh = tzsh_client->tzsh;
+        if (!tzsh) continue;
+
+        ec2 = tzsh->ec;
+        if (!ec2) continue;
+        if (!_e_policy_wl_e_client_is_valid(ec2)) continue;
+
+        ec = ec2;
+        break;
+     }
+
+   return ec;
+}
+
+static void
+_e_policy_wl_tzsh_srv_tvsrv_bind_update(void)
+{
+   E_Policy_Wl_Tzsh_Srv *tzsh_srv;
+   E_Client *tzsh_client_ec = NULL;
+   E_Client *tzsh_srv_ec = NULL;
+
+   tzsh_srv = polwl->srvs[TZSH_SRV_ROLE_TVSERVICE];
+   if ((tzsh_srv) && (tzsh_srv->tzsh))
+     tzsh_srv_ec = tzsh_srv->tzsh->ec;
+
+   tzsh_client_ec = _e_policy_wl_tzsh_srv_parent_client_pick();
+
+   if ((tzsh_srv_ec) &&
+       (tzsh_srv_ec->parent == tzsh_client_ec))
+     return;
+
+   if ((tzsh_client_ec) && (tzsh_srv_ec))
+     {
+        ELOGF("TZSH",
+              "TR_SET   |parent_ec:0x%08x|child_ec:0x%08x",
+              NULL, NULL,
+              (unsigned int)e_client_util_win_get(tzsh_client_ec),
+              (unsigned int)e_client_util_win_get(tzsh_srv_ec));
+
+        e_policy_stack_transient_for_set(tzsh_srv_ec, tzsh_client_ec);
+        evas_object_stack_below(tzsh_srv_ec->frame, tzsh_client_ec->frame);
+     }
+   else
+     {
+        if (tzsh_srv_ec)
+          {
+             ELOGF("TZSH",
+                   "TR_UNSET |                    |child_ec:0x%08x",
+                   NULL, NULL,
+                   (unsigned int)e_client_util_win_get(tzsh_srv_ec));
+
+             e_policy_stack_transient_for_set(tzsh_srv_ec, NULL);
+          }
+     }
+}
+
+static void
+_e_policy_wl_tzsh_srv_register_handle(E_Policy_Wl_Tzsh_Srv *tzsh_srv)
+{
+   E_Policy_Wl_Tzsh *tzsh;
+
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_srv);
+
+   tzsh = tzsh_srv->tzsh;
+   EINA_SAFETY_ON_NULL_RETURN(tzsh);
+
+   switch (tzsh_srv->role)
+     {
+      case TZSH_SRV_ROLE_TVSERVICE:
+         if (tzsh->ec) tzsh->ec->transient_policy = E_TRANSIENT_BELOW;
+         _e_policy_wl_tzsh_srv_tvsrv_bind_update();
+         break;
+
+      default:
+         break;
+     }
+}
+
+static void
+_e_policy_wl_tzsh_srv_unregister_handle(E_Policy_Wl_Tzsh_Srv *tzsh_srv)
+{
+   E_Policy_Wl_Tzsh *tzsh;
+
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_srv);
+
+   tzsh = tzsh_srv->tzsh;
+   EINA_SAFETY_ON_NULL_RETURN(tzsh);
+
+   switch (tzsh_srv->role)
+     {
+      case TZSH_SRV_ROLE_TVSERVICE:
+         _e_policy_wl_tzsh_srv_tvsrv_bind_update();
+         break;
+
+      default:
+         break;
+     }
+}
+
+/* broadcast state of registered service to all subscribers */
+static void
+_e_policy_wl_tzsh_srv_state_broadcast(E_Policy_Wl_Tzsh_Srv *tzsh_srv, Eina_Bool reg)
+{
+   E_Policy_Wl_Tzsh *tzsh;
+   Eina_List *l;
+
+   EINA_LIST_FOREACH(polwl->tzshs, l, tzsh)
+     {
+        if (tzsh->type == TZSH_TYPE_SRV) continue;
+
+        if (reg)
+          tizen_ws_shell_send_service_register
+            (tzsh->res_tzsh, tzsh_srv->name);
+        else
+          tizen_ws_shell_send_service_unregister
+            (tzsh->res_tzsh, tzsh_srv->name);
+     }
+}
+
+// --------------------------------------------------------
+// E_Policy_Wl_Tzsh_Client
+// --------------------------------------------------------
+static E_Policy_Wl_Tzsh_Client *
+_e_policy_wl_tzsh_client_add(E_Policy_Wl_Tzsh *tzsh, struct wl_resource *res_tzsh_client)
+{
+   E_Policy_Wl_Tzsh_Client *tzsh_client;
+
+   tzsh_client = E_NEW(E_Policy_Wl_Tzsh_Client, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(tzsh_client, NULL);
+
+   tzsh_client->tzsh = tzsh;
+   tzsh_client->res_tzsh_client = res_tzsh_client;
+
+   /* TODO: add tzsh_client to list or hash */
+
+   polwl->tzsh_clients = eina_list_append(polwl->tzsh_clients, tzsh_client);
+
+   return tzsh_client;
+}
+
+static void
+_e_policy_wl_tzsh_client_del(E_Policy_Wl_Tzsh_Client *tzsh_client)
+{
+   if (!tzsh_client) return;
+
+   if (!eina_list_data_find(polwl->tzsh_clients, tzsh_client))
+     return;
+
+   polwl->tzsh_clients = eina_list_remove(polwl->tzsh_clients, tzsh_client);
+   polwl->tvsrv_bind_list = eina_list_remove(polwl->tvsrv_bind_list, tzsh_client);
+
+   if ((tzsh_client->qp_client) &&
+       (tzsh_client->tzsh) &&
+       (tzsh_client->tzsh->ec))
+     e_qp_client_del(tzsh_client->tzsh->ec);
+
+   memset(tzsh_client, 0x0, sizeof(E_Policy_Wl_Tzsh_Client));
+   E_FREE(tzsh_client);
+}
+
+// --------------------------------------------------------
+// E_Policy_Wl_Surface
+// --------------------------------------------------------
+static E_Policy_Wl_Surface *
+_e_policy_wl_surf_add(E_Client *ec, struct wl_resource *res_tzpol)
+{
+   E_Policy_Wl_Surface *psurf = NULL;
+
+   E_Policy_Wl_Tzpol *tzpol;
+
+   tzpol = _e_policy_wl_tzpol_get(res_tzpol);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(tzpol, NULL);
+
+   psurf = _e_policy_wl_tzpol_surf_find(tzpol, ec);
+   if (psurf) return psurf;
+
+   psurf = E_NEW(E_Policy_Wl_Surface, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(psurf, NULL);
+
+   psurf->surf = ec->comp_data->surface;
+   psurf->tzpol = tzpol;
+   psurf->cp = ec->pixmap;
+   psurf->ec = ec;
+   psurf->pid = ec->netwm.pid;
+
+   tzpol->psurfs = eina_list_append(tzpol->psurfs, psurf);
+
+   return psurf;
+}
+
+static void
+_e_policy_wl_surf_del(E_Policy_Wl_Surface *psurf)
+{
+   eina_list_free(psurf->vislist);
+   eina_list_free(psurf->poslist);
+
+   memset(psurf, 0x0, sizeof(E_Policy_Wl_Surface));
+   E_FREE(psurf);
+}
+
+static void
+_e_policy_wl_surf_client_set(E_Client *ec)
+{
+   E_Policy_Wl_Tzpol *tzpol;
+   E_Policy_Wl_Surface *psurf;
+   Eina_Iterator *it;
+
+   it = eina_hash_iterator_data_new(polwl->tzpols);
+   EINA_ITERATOR_FOREACH(it, tzpol)
+     {
+        psurf = _e_policy_wl_tzpol_surf_find(tzpol, ec);
+        if (psurf)
+          {
+             if ((psurf->ec) && (psurf->ec != ec))
+               {
+                  ELOGF("POLSURF",
+                        "CRI ERR!!|s:0x%08x|tzpol:0x%08x|ps:0x%08x|new_ec:0x%08x|new_cp:0x%08x",
+                        psurf->cp,
+                        psurf->ec,
+                        (unsigned int)psurf->surf,
+                        (unsigned int)psurf->tzpol,
+                        (unsigned int)psurf,
+                        (unsigned int)ec,
+                        (unsigned int)ec->pixmap);
+               }
+
+             psurf->ec = ec;
+          }
+     }
+   eina_iterator_free(it);
+
+   return;
+}
+
+static void
+_e_policy_wl_pending_bg_client_set(E_Client *ec)
+{
+   E_Policy_Wl_Tzpol *tzpol;
+   E_Policy_Wl_Surface *psurf;
+   Eina_Iterator *it;
+
+   if (ec->netwm.pid == 0) return;
+
+   it = eina_hash_iterator_data_new(polwl->tzpols);
+   EINA_ITERATOR_FOREACH(it, tzpol)
+     {
+        Eina_List *psurfs;
+
+        if (!tzpol->pending_bg) continue;
+
+        if ((psurfs = _e_policy_wl_tzpol_surf_find_by_pid(tzpol, ec->netwm.pid)))
+          {
+             EINA_LIST_FREE(psurfs, psurf)
+               {
+                  psurf->ec = ec;
+
+                  if (eina_list_data_find(tzpol->pending_bg, psurf))
+                    {
+                       _e_policy_wl_background_state_set(psurf, EINA_TRUE);
+                       tzpol->pending_bg = eina_list_remove(tzpol->pending_bg, psurf);
+                    }
+               }
+          }
+     }
+   eina_iterator_free(it);
+}
+
+static E_Pixmap *
+_e_policy_wl_e_pixmap_get_from_id(struct wl_client *client, uint32_t id)
+{
+   E_Pixmap *cp;
+   E_Client *ec;
+   struct wl_resource *res_surf;
+
+   res_surf = wl_client_get_object(client, id);
+   if (!res_surf)
+     {
+        ERR("Could not get surface resource");
+        return NULL;
+     }
+
+   ec = wl_resource_get_user_data(res_surf);
+   if (!ec)
+     {
+        ERR("Could not get surface's user data");
+        return NULL;
+     }
+
+   /* check E_Pixmap */
+   cp = e_pixmap_find(E_PIXMAP_TYPE_WL, (uintptr_t)res_surf);
+   if (cp != ec->pixmap)
+     {
+        ELOGF("POLWL",
+              "CRI ERR!!|cp2:0x%08x|ec2:0x%08x|res_surf:0x%08x",
+              ec->pixmap, ec,
+              (unsigned int)cp,
+              (unsigned int)e_pixmap_client_get(cp),
+              (unsigned int)res_surf);
+        return NULL;
+     }
+
+   return cp;
+}
+
+static Eina_Bool
+_e_policy_wl_e_client_is_valid(E_Client *ec)
+{
+   E_Client *ec2;
+   Eina_List *l;
+   Eina_Bool del = EINA_FALSE;
+   Eina_Bool found = EINA_FALSE;
+
+   EINA_LIST_FOREACH(e_comp->clients, l, ec2)
+     {
+        if (ec2 == ec)
+          {
+             if (e_object_is_del(E_OBJECT(ec2)))
+               del = EINA_TRUE;
+             found = EINA_TRUE;
+             break;
+          }
+     }
+
+   return ((!del) && (found));
+}
+
+static Eina_List *
+_e_policy_wl_e_clients_find_by_pid(pid_t pid)
+{
+   E_Client *ec;
+   Eina_List *clients = NULL, *l;
+
+   EINA_LIST_FOREACH(e_comp->clients, l, ec)
+     {
+        if (e_object_is_del(E_OBJECT(ec))) continue;
+        if (ec->netwm.pid != pid) continue;
+        clients = eina_list_append(clients, ec);
+     }
+
+   return clients;
+}
+
+// --------------------------------------------------------
+// visibility
+// --------------------------------------------------------
+static void
+_tzvis_iface_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzvis)
+{
+   wl_resource_destroy(res_tzvis);
+}
+
+static const struct tizen_visibility_interface _tzvis_iface =
+{
+   _tzvis_iface_cb_destroy
+};
+
+static void
+_tzvis_iface_cb_vis_destroy(struct wl_resource *res_tzvis)
+{
+   E_Policy_Wl_Surface *psurf;
+   Eina_Bool r;
+
+   psurf = wl_resource_get_user_data(res_tzvis);
+   EINA_SAFETY_ON_NULL_RETURN(psurf);
+
+   r = _e_policy_wl_surf_is_valid(psurf);
+   if (!r) return;
+
+   psurf->vislist = eina_list_remove(psurf->vislist, res_tzvis);
+}
+
+static void
+_tzpol_iface_cb_vis_get(struct wl_client *client, struct wl_resource *res_tzpol, uint32_t id, struct wl_resource *surf)
+{
+   E_Client *ec;
+   E_Policy_Wl_Surface *psurf;
+   struct wl_resource *res_tzvis;
+
+   ec = wl_resource_get_user_data(surf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   psurf = _e_policy_wl_surf_add(ec, res_tzpol);
+   EINA_SAFETY_ON_NULL_RETURN(psurf);
+
+   res_tzvis = wl_resource_create(client,
+                                  &tizen_visibility_interface,
+                                  wl_resource_get_version(res_tzpol),
+                                  id);
+   if (!res_tzvis)
+     {
+        wl_client_post_no_memory(client);
+        return;
+     }
+
+   wl_resource_set_implementation(res_tzvis,
+                                  &_tzvis_iface,
+                                  psurf,
+                                  _tzvis_iface_cb_vis_destroy);
+
+   psurf->vislist = eina_list_append(psurf->vislist, res_tzvis);
+
+   if (eina_list_data_find(polwl->pending_vis, ec))
+     {
+        e_policy_wl_visibility_send(ec, ec->visibility.obscured);
+     }
+}
+
+void
+e_policy_wl_visibility_send(E_Client *ec, int vis)
+{
+   E_Policy_Wl_Tzpol *tzpol;
+   E_Policy_Wl_Surface *psurf;
+   struct wl_resource *res_tzvis;
+   Eina_List *l, *ll;
+   Eina_Iterator *it;
+   E_Client *ec2;
+   Ecore_Window win;
+   Eina_Bool sent = EINA_FALSE;
+
+   win = e_client_util_win_get(ec);
+
+   it = eina_hash_iterator_data_new(polwl->tzpols);
+   EINA_ITERATOR_FOREACH(it, tzpol)
+     EINA_LIST_FOREACH(tzpol->psurfs, l, psurf)
+       {
+          ec2 = e_pixmap_client_get(psurf->cp);
+          if (ec2 != ec) continue;
+
+          EINA_LIST_FOREACH(psurf->vislist, ll, res_tzvis)
+            {
+               tizen_visibility_send_notify(res_tzvis, vis);
+               ELOGF("TZVIS",
+                     "SEND     |win:0x%08x|res_tzvis:0x%08x|v:%d",
+                     ec->pixmap, ec,
+                     (unsigned int)win,
+                     (unsigned int)res_tzvis,
+                     vis);
+               sent = EINA_TRUE;
+               _launchscreen_hide(ec->netwm.pid);
+            }
+       }
+   eina_iterator_free(it);
+
+   polwl->pending_vis = eina_list_remove(polwl->pending_vis, ec);
+   if (!sent)
+     polwl->pending_vis = eina_list_append(polwl->pending_vis, ec);
+}
+
+void
+e_policy_wl_iconify_state_change_send(E_Client *ec, int iconic)
+{
+   E_Policy_Wl_Tzpol *tzpol;
+   E_Policy_Wl_Surface *psurf;
+   E_Client *ec2;
+   Eina_List *l;
+   Eina_Iterator *it;
+   Ecore_Window win;
+
+   if (ec->exp_iconify.skip_iconify) return;
+
+   if (e_config->transient.iconify)
+     {
+        E_Client *child;
+        Eina_List *list = eina_list_clone(ec->transients);
+
+        EINA_LIST_FREE(list, child)
+          {
+             if ((child->iconic == ec->iconic) &&
+                 (child->exp_iconify.by_client == ec->exp_iconify.by_client))
+               e_policy_wl_iconify_state_change_send(child, iconic);
+
+          }
+     }
+
+   win = e_client_util_win_get(ec);
+
+   it = eina_hash_iterator_data_new(polwl->tzpols);
+   EINA_ITERATOR_FOREACH(it, tzpol)
+     EINA_LIST_FOREACH(tzpol->psurfs, l, psurf)
+       {
+          ec2 = e_pixmap_client_get(psurf->cp);
+          if (ec2 != ec) continue;
+
+          tizen_policy_send_iconify_state_changed(tzpol->res_tzpol, psurf->surf, iconic, 1);
+          ELOGF("ICONIFY",
+                "SEND     |win:0x%08x|iconic:%d |sur:%p",
+                ec->pixmap, ec,
+                (unsigned int)win,
+                iconic, psurf->surf);
+          break;
+       }
+   eina_iterator_free(it);
+}
+
+// --------------------------------------------------------
+// position
+// --------------------------------------------------------
+static void
+_tzpos_iface_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpos)
+{
+   wl_resource_destroy(res_tzpos);
+}
+
+static void
+_tzpos_iface_cb_set(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpos, int32_t x, int32_t y)
+{
+   E_Client *ec;
+   E_Policy_Wl_Surface *psurf;
+
+   psurf = wl_resource_get_user_data(res_tzpos);
+   EINA_SAFETY_ON_NULL_RETURN(psurf);
+
+   ec = e_pixmap_client_get(psurf->cp);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+   EINA_SAFETY_ON_NULL_RETURN(ec->frame);
+
+   if(!E_INTERSECTS(ec->zone->x, ec->zone->y,
+                    ec->zone->w, ec->zone->h,
+                    x, y,
+                    ec->w, ec->h))
+     {
+        e_policy_wl_position_send(ec);
+        return;
+     }
+
+   if (!ec->lock_client_location)
+     {
+        ec->x = ec->client.x = x;
+        ec->y = ec->client.y = y;
+        ec->placed = 1;
+     }
+}
+
+static const struct tizen_position_interface _tzpos_iface =
+{
+   _tzpos_iface_cb_destroy,
+   _tzpos_iface_cb_set,
+};
+
+static void
+_tzpol_iface_cb_pos_destroy(struct wl_resource *res_tzpos)
+{
+   E_Policy_Wl_Surface *psurf;
+   Eina_Bool r;
+
+   psurf = wl_resource_get_user_data(res_tzpos);
+   EINA_SAFETY_ON_NULL_RETURN(psurf);
+
+   r = _e_policy_wl_surf_is_valid(psurf);
+   if (!r) return;
+
+   psurf->poslist = eina_list_remove(psurf->poslist, res_tzpos);
+}
+
+static void
+_tzpol_iface_cb_pos_get(struct wl_client *client, struct wl_resource *res_tzpol, uint32_t id, struct wl_resource *surf)
+{
+   E_Client *ec;
+   E_Policy_Wl_Surface *psurf;
+   struct wl_resource *res_tzpos;
+
+   ec = wl_resource_get_user_data(surf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   psurf = _e_policy_wl_surf_add(ec, res_tzpol);
+   EINA_SAFETY_ON_NULL_RETURN(psurf);
+
+   res_tzpos = wl_resource_create(client,
+                                  &tizen_position_interface,
+                                  wl_resource_get_version(res_tzpol),
+                                  id);
+   if (!res_tzpos)
+     {
+        wl_client_post_no_memory(client);
+        return;
+     }
+
+   wl_resource_set_implementation(res_tzpos,
+                                  &_tzpos_iface,
+                                  psurf,
+                                  _tzpol_iface_cb_pos_destroy);
+
+   psurf->poslist = eina_list_append(psurf->poslist, res_tzpos);
+}
+
+void
+e_policy_wl_position_send(E_Client *ec)
+{
+   E_Policy_Wl_Tzpol *tzpol;
+   E_Policy_Wl_Surface *psurf;
+   struct wl_resource *res_tzpos;
+   Eina_List *l, *ll;
+   Eina_Iterator *it;
+   Ecore_Window win;
+
+   win = e_client_util_win_get(ec);
+
+   it = eina_hash_iterator_data_new(polwl->tzpols);
+   EINA_ITERATOR_FOREACH(it, tzpol)
+     EINA_LIST_FOREACH(tzpol->psurfs, l, psurf)
+       {
+          if (e_pixmap_client_get(psurf->cp) != ec) continue;
+
+          EINA_LIST_FOREACH(psurf->poslist, ll, res_tzpos)
+            {
+               tizen_position_send_changed(res_tzpos, ec->client.x, ec->client.y);
+               ELOGF("TZPOS",
+                     "SEND     |win:0x%08x|res_tzpos:0x%08x|ec->x:%d, ec->y:%d, ec->client.x:%d, ec->client.y:%d",
+                     ec->pixmap, ec,
+                     (unsigned int)win,
+                     (unsigned int)res_tzpos,
+                     ec->x, ec->y,
+                     ec->client.x, ec->client.y);
+            }
+       }
+   eina_iterator_free(it);
+}
+
+// --------------------------------------------------------
+// stack: activate, raise, lower
+// --------------------------------------------------------
+static void
+_tzpol_iface_cb_activate(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol EINA_UNUSED, struct wl_resource *surf)
+{
+   E_Client *ec;
+
+   ec = wl_resource_get_user_data(surf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+   EINA_SAFETY_ON_NULL_RETURN(ec->frame);
+
+   ELOGF("TZPOL", "ACTIVATE", ec->pixmap, ec);
+
+   if ((!starting) && (!ec->focused))
+     {
+        if ((ec->iconic) && (!ec->exp_iconify.by_client))
+          e_policy_wl_iconify_state_change_send(ec, 0);
+        e_client_activate(ec, EINA_TRUE);
+     }
+   else
+     evas_object_raise(ec->frame);
+
+   if (e_policy_client_is_lockscreen(ec))
+     e_policy_stack_clients_restack_above_lockscreen(ec, EINA_TRUE);
+   else
+     e_policy_stack_check_above_lockscreen(ec, ec->layer, NULL, EINA_TRUE);
+}
+
+static void
+_tzpol_iface_cb_activate_below_by_res_id(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol,  uint32_t res_id, uint32_t below_res_id)
+{
+   E_Client *ec = NULL;
+   E_Client *below_ec = NULL;
+   E_Client *parent_ec = NULL;
+   Eina_Bool check_ancestor = EINA_FALSE;
+
+   ec = e_pixmap_find_client_by_res_id(res_id);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+   EINA_SAFETY_ON_NULL_RETURN(ec->frame);
+
+   below_ec = e_pixmap_find_client_by_res_id(below_res_id);
+   EINA_SAFETY_ON_NULL_RETURN(below_ec);
+   EINA_SAFETY_ON_NULL_RETURN(below_ec->frame);
+
+   if (ec->layer > below_ec->layer) return;
+
+   parent_ec = ec->parent;
+   while (parent_ec)
+     {
+        if (parent_ec == below_ec)
+          {
+             check_ancestor = EINA_TRUE;
+             break;
+          }
+        parent_ec = parent_ec->parent;
+     }
+   if (check_ancestor) return;
+
+   if ((!starting) && (!ec->focused))
+     {
+        if ((ec->iconic) && (!ec->exp_iconify.by_client))
+          e_policy_wl_iconify_state_change_send(ec, 0);
+
+        e_client_activate(ec, EINA_TRUE);
+     }
+
+   e_policy_stack_below(ec, below_ec);
+
+   if (!e_client_first_mapped_get(ec))
+     e_client_post_raise_lower_set(ec, EINA_FALSE, EINA_FALSE);
+}
+
+static void
+_tzpol_iface_cb_raise(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol EINA_UNUSED, struct wl_resource *surf)
+{
+   E_Client *ec;
+
+   ec = wl_resource_get_user_data(surf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+   EINA_SAFETY_ON_NULL_RETURN(ec->frame);
+
+   ELOGF("TZPOL", "RAISE", ec->pixmap, ec);
+
+   evas_object_raise(ec->frame);
+
+   if (!e_client_first_mapped_get(ec))
+     e_client_post_raise_lower_set(ec, EINA_TRUE, EINA_FALSE);
+}
+
+static void
+_tzpol_iface_cb_lower(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol EINA_UNUSED, struct wl_resource *surf)
+{
+   E_Client *ec, *below = NULL;
+
+   ec = wl_resource_get_user_data(surf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+   EINA_SAFETY_ON_NULL_RETURN(ec->frame);
+
+   ELOGF("TZPOL", "LOWER", ec->pixmap, ec);
+
+   below = ec;
+   while ((below = e_client_below_get(below)))
+     {
+        if ((e_client_util_ignored_get(below)) ||
+            (below->iconic))
+          continue;
+
+        break;
+     }
+
+   evas_object_lower(ec->frame);
+
+   if (!e_client_first_mapped_get(ec))
+     e_client_post_raise_lower_set(ec, EINA_FALSE, EINA_TRUE);
+
+   if ((!below) || (!ec->focused)) return;
+
+   evas_object_focus_set(below->frame, 1);
+}
+
+static void
+_tzpol_iface_cb_lower_by_res_id(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol,  uint32_t res_id)
+{
+   E_Client *ec, *below = NULL;
+
+   ELOGF("TZPOL",
+         "LOWER_RES|res_tzpol:0x%08x|res_id:%d",
+         NULL, NULL, (unsigned int)res_tzpol, res_id);
+
+   ec = e_pixmap_find_client_by_res_id(res_id);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+   EINA_SAFETY_ON_NULL_RETURN(ec->frame);
+
+   below = ec;
+   while ((below = e_client_below_get(below)))
+     {
+        if ((e_client_util_ignored_get(below)) ||
+            (below->iconic))
+          continue;
+
+        break;
+     }
+
+   evas_object_lower(ec->frame);
+
+   if (!e_client_first_mapped_get(ec))
+     e_client_post_raise_lower_set(ec, EINA_FALSE, EINA_TRUE);
+
+   if ((!below) || (!ec->focused)) return;
+
+   if ((below->icccm.accepts_focus) ||(below->icccm.take_focus))
+     evas_object_focus_set(below->frame, 1);
+}
+
+// --------------------------------------------------------
+// focus
+// --------------------------------------------------------
+static void
+_tzpol_iface_cb_focus_skip_set(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol EINA_UNUSED, struct wl_resource *surf)
+{
+   E_Client *ec;
+
+   ec = wl_resource_get_user_data(surf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   if (ec->icccm.accepts_focus)
+     {
+        ec->icccm.accepts_focus = ec->icccm.take_focus = 0;
+        EC_CHANGED(ec);
+     }
+}
+
+static void
+_tzpol_iface_cb_focus_skip_unset(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol EINA_UNUSED, struct wl_resource *surf)
+{
+   E_Client *ec;
+
+   ec = wl_resource_get_user_data(surf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   if (!ec->icccm.accepts_focus)
+     {
+        ec->icccm.accepts_focus = ec->icccm.take_focus = 1;
+        EC_CHANGED(ec);
+     }
+}
+
+// --------------------------------------------------------
+// role
+// --------------------------------------------------------
+static void
+_tzpol_iface_cb_role_set(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol EINA_UNUSED, struct wl_resource *surf, const char *role)
+{
+   E_Client *ec;
+
+   EINA_SAFETY_ON_NULL_RETURN(role);
+
+   ec = wl_resource_get_user_data(surf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+   EINA_SAFETY_ON_NULL_RETURN(ec->frame);
+
+   eina_stringshare_replace(&ec->icccm.window_role, role);
+
+   /* TODO: support multiple roles */
+   if (!e_util_strcmp("notification-low", role))
+     {
+        evas_object_layer_set(ec->frame, E_LAYER_CLIENT_NOTIFICATION_LOW);
+     }
+   else if (!e_util_strcmp("notification-normal", role))
+     {
+        evas_object_layer_set(ec->frame, E_LAYER_CLIENT_NOTIFICATION_NORMAL);
+     }
+   else if (!e_util_strcmp("notification-high", role))
+     {
+        evas_object_layer_set(ec->frame, E_LAYER_CLIENT_NOTIFICATION_HIGH);
+     }
+   else if (!e_util_strcmp("alert", role))
+     {
+        evas_object_layer_set(ec->frame, E_LAYER_CLIENT_ALERT);
+     }
+   else if (!e_util_strcmp("tv-volume-popup", role))
+     {
+        evas_object_layer_set(ec->frame, E_LAYER_CLIENT_NOTIFICATION_LOW);
+        ec->lock_client_location = 1;
+     }
+   else if (!e_util_strcmp("e_demo", role))
+     {
+        evas_object_layer_set(ec->frame, E_LAYER_CLIENT_NOTIFICATION_HIGH);
+        ec->lock_client_location = 1;
+     }
+   else if (!e_util_strcmp("cbhm", role))
+     {
+        if (!ec->comp_data) return;
+        e_comp_wl->selection.cbhm = ec->comp_data->surface;
+     }
+}
+
+static void
+_tzpol_iface_cb_type_set(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol, struct wl_resource *surf, uint32_t type)
+{
+   E_Client *ec;
+   E_Window_Type win_type;
+
+   ec = wl_resource_get_user_data(surf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   switch (type)
+     {
+      /* TODO: support other types */
+      case TIZEN_POLICY_WIN_TYPE_NOTIFICATION:
+         win_type = E_WINDOW_TYPE_NOTIFICATION;
+         break;
+
+      case TIZEN_POLICY_WIN_TYPE_UTILITY:
+         win_type = E_WINDOW_TYPE_UTILITY;
+         break;
+
+      default: return;
+     }
+
+   ELOGF("TZPOL",
+         "TYPE_SET |win:0x%08x|s:0x%08x|res_tzpol:0x%08x|tizen_win_type:%d, e_win_type:%d",
+         ec->pixmap, ec,
+         (unsigned int)e_client_util_win_get(ec),
+         (unsigned int)surf,
+         (unsigned int)res_tzpol,
+         type, win_type);
+
+   ec->netwm.type = win_type;
+
+   EC_CHANGED(ec);
+}
+// --------------------------------------------------------
+// conformant
+// --------------------------------------------------------
+static void
+_tzpol_iface_cb_conformant_set(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol, struct wl_resource *surf)
+{
+   E_Client *ec;
+
+   ec = wl_resource_get_user_data(surf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   e_policy_conformant_client_add(ec, res_tzpol);
+}
+
+static void
+_tzpol_iface_cb_conformant_unset(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol EINA_UNUSED, struct wl_resource *surf)
+{
+   E_Client *ec;
+
+   ec = wl_resource_get_user_data(surf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   e_policy_conformant_client_del(ec);
+}
+
+static void
+_tzpol_iface_cb_conformant_get(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol, struct wl_resource *surf)
+{
+   E_Client *ec;
+
+   ec = wl_resource_get_user_data(surf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   tizen_policy_send_conformant(res_tzpol, surf, e_policy_conformant_client_check(ec));
+}
+
+// --------------------------------------------------------
+// notification level
+// --------------------------------------------------------
+#define SMACK_LABEL_LEN 255
+#define PATH_MAX_LEN 64
+
+#ifdef HAVE_CYNARA
+static void
+_e_policy_wl_smack_label_direct_read(int pid, char **client)
+{
+   int ret;
+   int fd = -1;
+   char smack_label[SMACK_LABEL_LEN +1];
+   char path[PATH_MAX_LEN + 1];
+
+   bzero(smack_label, SMACK_LABEL_LEN + 1);
+   bzero(path, PATH_MAX_LEN + 1);
+   snprintf(path, PATH_MAX_LEN, "/proc/%d/attr/current", pid);
+   fd = open(path, O_RDONLY);
+   if (fd == -1) return;
+
+   ret = read(fd, smack_label, SMACK_LABEL_LEN);
+   close(fd);
+   if (ret < 0) return;
+
+   *client = calloc(SMACK_LABEL_LEN + 1, sizeof(char));
+   strncpy(*client, smack_label, SMACK_LABEL_LEN + 1);
+}
+#endif
+
+static Eina_Bool
+_e_policy_wl_privilege_check(int fd, const char *privilege)
+{
+#ifdef HAVE_CYNARA
+   char *client = NULL, *user = NULL, *client_session = NULL;
+   pid_t pid = 0;
+   int ret = -1;
+   Eina_Bool res = EINA_FALSE;
+
+   if ((!polwl->p_cynara))
+     {
+        ELOGF("TZPOL",
+              "Cynara is not initialized. DENY all requests", NULL, NULL);
+        return EINA_FALSE;
+     }
+
+   ret = cynara_creds_socket_get_user(fd, USER_METHOD_DEFAULT, &user);
+   if (ret != CYNARA_API_SUCCESS) goto cynara_finished;
+
+   ret = cynara_creds_socket_get_pid(fd, &pid);
+   if (ret != CYNARA_API_SUCCESS) goto cynara_finished;
+
+   client_session = cynara_session_from_pid(pid);
+   if (!client_session) goto cynara_finished;
+
+   /* Temporary fix for mis matching socket smack label
+    * ret = cynara_creds_socket_get_client(fd, CLIENT_METHOD_DEFAULT, &client);
+    * if (ret != CYNARA_API_SUCCESS) goto cynara_finished; 
+    */
+   _e_policy_wl_smack_label_direct_read(pid, &client);
+   if (!client) goto cynara_finished;
+
+   ret = cynara_check(polwl->p_cynara,
+                      client,
+                      client_session,
+                      user,
+                      privilege);
+
+   if (ret == CYNARA_API_ACCESS_ALLOWED)
+     res = EINA_TRUE;
+
+cynara_finished:
+   ELOGF("TZPOL",
+         "Privilege Check For %s %s fd:%d client:%s user:%s pid:%u client_session:%s ret:%d",
+         NULL, NULL,
+         privilege, res?"SUCCESS":"FAIL",
+         fd, client?:"N/A", user?:"N/A", pid, client_session?:"N/A", ret);
+
+   if (client_session) free(client_session);
+   if (user) free(user);
+   if (client) free(client);
+
+   return res;
+#else
+   return EINA_TRUE;
+#endif
+}
+
+static void
+_tzpol_notilv_set(E_Client *ec, int lv)
+{
+   short ly;
+
+   switch (lv)
+     {
+      case  0: ly = E_LAYER_CLIENT_NOTIFICATION_LOW;    break;
+      case  1: ly = E_LAYER_CLIENT_NOTIFICATION_NORMAL; break;
+      case  2: ly = E_LAYER_CLIENT_NOTIFICATION_TOP;    break;
+      case -1: ly = E_LAYER_CLIENT_NORMAL;              break;
+      case 10: ly = E_LAYER_CLIENT_NOTIFICATION_LOW;    break;
+      case 20: ly = E_LAYER_CLIENT_NOTIFICATION_NORMAL; break;
+      case 30: ly = E_LAYER_CLIENT_NOTIFICATION_HIGH;   break;
+      case 40: ly = E_LAYER_CLIENT_NOTIFICATION_TOP;    break;
+      default: ly = E_LAYER_CLIENT_NOTIFICATION_LOW;    break;
+     }
+
+   if (ly != evas_object_layer_get(ec->frame))
+     {
+        evas_object_layer_set(ec->frame, ly);
+     }
+
+   ec->layer = ly;
+}
+
+static void
+_tzpol_iface_cb_notilv_set(struct wl_client *client, struct wl_resource *res_tzpol, struct wl_resource *surf, int32_t lv)
+{
+   E_Client *ec;
+   E_Policy_Wl_Surface *psurf;
+   int fd;
+
+   ec = wl_resource_get_user_data(surf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   psurf = _e_policy_wl_surf_add(ec, res_tzpol);
+   EINA_SAFETY_ON_NULL_RETURN(psurf);
+
+   fd = wl_client_get_fd(client);
+   if (!_e_policy_wl_privilege_check(fd, PRIVILEGE_NOTIFICATION_LEVEL_SET))
+     {
+        ELOGF("TZPOL",
+              "Privilege Check Failed! DENY set_notification_level",
+              ec->pixmap, ec);
+
+        tizen_policy_send_notification_done
+           (res_tzpol,
+            surf,
+            -1,
+            TIZEN_POLICY_ERROR_STATE_PERMISSION_DENIED);
+        return;
+     }
+
+   ELOGF("TZPOL", "NOTI_LEVEL|level:%d", ec->pixmap, ec, lv);
+   _tzpol_notilv_set(ec, lv);
+
+   psurf->notilv = lv;
+
+   tizen_policy_send_notification_done
+     (res_tzpol, surf, lv, TIZEN_POLICY_ERROR_STATE_NONE);
+
+   if (e_policy_client_is_lockscreen(ec))
+     e_policy_stack_clients_restack_above_lockscreen(ec, EINA_TRUE);
+}
+
+void
+e_policy_wl_notification_level_fetch(E_Client *ec)
+{
+   E_Pixmap *cp;
+   E_Policy_Wl_Surface *psurf;
+   E_Policy_Wl_Tzpol *tzpol;
+   Eina_Iterator *it;
+   Eina_List *l;
+   Eina_Bool changed_stack = EINA_FALSE;
+
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   cp = ec->pixmap;
+   EINA_SAFETY_ON_NULL_RETURN(cp);
+
+   // TODO: use pending_notilv_list instead of loop
+   it = eina_hash_iterator_data_new(polwl->tzpols);
+   EINA_ITERATOR_FOREACH(it, tzpol)
+     EINA_LIST_FOREACH(tzpol->psurfs, l, psurf)
+       {
+          if (psurf->cp != cp) continue;
+          if (!psurf->pending_notilv) continue;
+
+          psurf->pending_notilv = EINA_FALSE;
+          _tzpol_notilv_set(ec, psurf->notilv);
+          changed_stack = EINA_TRUE;
+       }
+   eina_iterator_free(it);
+
+   if (changed_stack &&
+       e_policy_client_is_lockscreen(ec))
+     {
+        e_policy_stack_clients_restack_above_lockscreen(ec, EINA_TRUE);
+     }
+}
+
+// --------------------------------------------------------
+// transient for
+// --------------------------------------------------------
+static void
+_e_policy_wl_parent_surf_set(E_Client *ec, struct wl_resource *parent_surf)
+{
+   E_Client *pc = NULL;
+
+   if (parent_surf)
+     {
+        if (!(pc = wl_resource_get_user_data(parent_surf)))
+          {
+             ERR("Could not get parent res e_client");
+             return;
+          }
+     }
+
+   e_policy_stack_transient_for_set(ec, pc);
+}
+
+static void
+_tzpol_iface_cb_transient_for_set(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol, uint32_t child_id, uint32_t parent_id)
+{
+   E_Client *ec, *pc;
+   struct wl_resource *parent_surf;
+
+   ELOGF("TZPOL",
+         "TF_SET   |res_tzpol:0x%08x|parent:%d|child:%d",
+         NULL, NULL, (unsigned int)res_tzpol, parent_id, child_id);
+
+   ec = e_pixmap_find_client_by_res_id(child_id);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   pc = e_pixmap_find_client_by_res_id(parent_id);
+   EINA_SAFETY_ON_NULL_RETURN(pc);
+   EINA_SAFETY_ON_NULL_RETURN(pc->comp_data);
+
+   parent_surf = pc->comp_data->surface;
+
+   _e_policy_wl_parent_surf_set(ec, parent_surf);
+
+   ELOGF("TZPOL",
+         "         |win:0x%08x|parent|s:0x%08x",
+         pc->pixmap, pc,
+         (unsigned int)e_client_util_win_get(pc),
+         (unsigned int)parent_surf);
+
+   ELOGF("TZPOL",
+         "         |win:0x%08x|child |s:0x%08x",
+         ec->pixmap, ec,
+         (unsigned int)e_client_util_win_get(ec),
+         (unsigned int)(ec->comp_data ? ec->comp_data->surface : NULL));
+
+   tizen_policy_send_transient_for_done(res_tzpol, child_id);
+
+   EC_CHANGED(ec);
+}
+
+static void
+_tzpol_iface_cb_transient_for_unset(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol, uint32_t child_id)
+{
+   E_Client *ec;
+
+   ELOGF("TZPOL",
+         "TF_UNSET |res_tzpol:0x%08x|child:%d",
+         NULL, NULL, (unsigned int)res_tzpol, child_id);
+
+   ec = e_pixmap_find_client_by_res_id(child_id);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   _e_policy_wl_parent_surf_set(ec, NULL);
+
+   tizen_policy_send_transient_for_done(res_tzpol, child_id);
+
+   EC_CHANGED(ec);
+}
+
+// --------------------------------------------------------
+// window screen mode
+// --------------------------------------------------------
+static void
+_tzpol_iface_cb_win_scrmode_set(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol, struct wl_resource *surf, uint32_t mode)
+{
+   E_Client *ec;
+   int fd;
+
+   ec = wl_resource_get_user_data(surf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   fd = wl_client_get_fd(client);
+   if (!_e_policy_wl_privilege_check(fd, PRIVILEGE_SCREEN_MODE_SET))
+     {
+        ELOGF("TZPOL",
+              "Privilege Check Failed! DENY set_screen_mode",
+              ec->pixmap, ec);
+
+        tizen_policy_send_window_screen_mode_done
+           (res_tzpol,
+            surf,
+            -1,
+            TIZEN_POLICY_ERROR_STATE_PERMISSION_DENIED);
+        return;
+     }
+
+   ELOGF("TZPOL", "SCR_MODE |mode:%d", ec->pixmap, ec, mode);
+
+   e_policy_display_screen_mode_set(ec, mode);
+   e_policy_wl_win_scrmode_apply();
+
+   tizen_policy_send_window_screen_mode_done
+     (res_tzpol, surf, mode, TIZEN_POLICY_ERROR_STATE_NONE);
+}
+
+void
+e_policy_wl_win_scrmode_apply(void)
+{
+   e_policy_display_screen_mode_apply();
+}
+
+// --------------------------------------------------------
+// subsurface
+// --------------------------------------------------------
+static void
+_tzpol_iface_cb_subsurf_place_below_parent(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol EINA_UNUSED, struct wl_resource *subsurf)
+{
+   E_Client *ec;
+   E_Client *epc;
+   E_Comp_Wl_Subsurf_Data *sdata;
+
+   ec = wl_resource_get_user_data(subsurf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+   EINA_SAFETY_ON_NULL_RETURN(ec->comp_data);
+
+   sdata = ec->comp_data->sub.data;
+   EINA_SAFETY_ON_NULL_RETURN(sdata);
+
+   epc = sdata->parent;
+   EINA_SAFETY_ON_NULL_RETURN(epc);
+
+   /* check if a subsurface has already placed below a parent */
+   if (eina_list_data_find(epc->comp_data->sub.below_list, ec)) return;
+
+   epc->comp_data->sub.list = eina_list_remove(epc->comp_data->sub.list, ec);
+   epc->comp_data->sub.list_pending = eina_list_remove(epc->comp_data->sub.list_pending, ec);
+   epc->comp_data->sub.below_list = eina_list_append(epc->comp_data->sub.below_list, ec);
+   epc->comp_data->sub.list_changed = EINA_TRUE;
+}
+
+static void
+_tzpol_iface_cb_subsurf_stand_alone_set(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol EINA_UNUSED, struct wl_resource *subsurf)
+{
+   E_Client *ec;
+   E_Comp_Wl_Subsurf_Data *sdata;
+
+   ec = wl_resource_get_user_data(subsurf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+   EINA_SAFETY_ON_NULL_RETURN(ec->comp_data);
+
+   sdata = ec->comp_data->sub.data;
+   EINA_SAFETY_ON_NULL_RETURN(sdata);
+
+   sdata->stand_alone = EINA_TRUE;
+}
+
+static void
+_tzpol_iface_cb_subsurface_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface, uint32_t parent_id)
+{
+   E_Client *ec, *epc;
+
+   ELOGF("TZPOL",
+         "SUBSURF   |wl_surface@%d|parent_id:%d",
+         NULL, NULL, wl_resource_get_id(surface), parent_id);
+
+   ec = wl_resource_get_user_data(surface);
+   if (!ec)
+     {
+        wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
+                               "tizen_policy failed: wrong wl_surface@%d resource",
+                               wl_resource_get_id(surface));
+        return;
+     }
+
+   if (e_object_is_del(E_OBJECT(ec))) return;
+
+   epc = e_pixmap_find_client_by_res_id(parent_id);
+   if (!epc)
+     {
+        wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
+                               "tizen_policy failed: wrong parent_id(%d)", parent_id);
+        return;
+     }
+
+   if (e_object_is_del(E_OBJECT(epc))) return;
+
+   /* check if this surface is already a sub-surface */
+   if ((ec->comp_data) && (ec->comp_data->sub.data))
+     {
+        wl_resource_post_error(resource,
+                               WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
+                               "wl_surface@%d is already a sub-surface",
+                               wl_resource_get_id(surface));
+        return;
+     }
+
+   /* try to create a new subsurface */
+   if (!e_comp_wl_subsurface_create(ec, epc, id, surface))
+     ERR("Failed to create subsurface for surface@%d",
+         wl_resource_get_id(surface));
+
+   /* ec's parent comes from another process */
+   if (ec->comp_data)
+     ec->comp_data->has_extern_parent = EINA_TRUE;
+}
+
+static void
+_tzpol_iface_cb_opaque_state_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, int32_t state)
+{
+   E_Client *ec;
+
+   ec = wl_resource_get_user_data(surface);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   ELOGF("TZPOL", "OPAQUE   |opaque_state:%d", ec->pixmap, ec, state);
+   ec->visibility.opaque = state;
+}
+
+// --------------------------------------------------------
+// iconify
+// --------------------------------------------------------
+static void
+_tzpol_iface_cb_iconify(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol EINA_UNUSED, struct wl_resource *surf)
+{
+   E_Client *ec;
+
+   ec = wl_resource_get_user_data(surf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+   EINA_SAFETY_ON_NULL_RETURN(ec->frame);
+
+   ELOG("Set ICONIFY BY CLIENT", ec->pixmap, ec);
+   ec->exp_iconify.by_client = 1;
+   e_client_iconify(ec);
+
+   EC_CHANGED(ec);
+}
+
+static void
+_tzpol_iface_cb_uniconify(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol EINA_UNUSED, struct wl_resource *surf)
+{
+   E_Client *ec;
+
+   ec = wl_resource_get_user_data(surf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+   EINA_SAFETY_ON_NULL_RETURN(ec->frame);
+
+   if ((ec->iconic) && (!ec->exp_iconify.by_client))
+     e_policy_wl_iconify_state_change_send(ec, 0);
+
+   ELOG("Un-Set ICONIFY BY CLIENT", ec->pixmap, ec);
+   ec->exp_iconify.by_client = 0;
+   e_client_uniconify(ec);
+
+   EC_CHANGED(ec);
+}
+
+static void
+_e_policy_wl_allowed_aux_hint_send(E_Client *ec, int id)
+{
+   E_Policy_Wl_Tzpol *tzpol;
+   E_Policy_Wl_Surface *psurf;
+   Eina_List *l;
+   Eina_Iterator *it;
+
+   it = eina_hash_iterator_data_new(polwl->tzpols);
+   EINA_ITERATOR_FOREACH(it, tzpol)
+     EINA_LIST_FOREACH(tzpol->psurfs, l, psurf)
+       {
+          if (e_pixmap_client_get(psurf->cp) != ec) continue;
+          tizen_policy_send_allowed_aux_hint
+            (tzpol->res_tzpol,
+             psurf->surf,
+             id);
+          ELOGF("TZPOL",
+                "SEND     |res_tzpol:0x%08x|allowed hint->id:%d",
+                ec->pixmap, ec,
+                (unsigned int)tzpol->res_tzpol,
+                id);
+       }
+   eina_iterator_free(it);
+}
+
+static void
+_e_policy_wl_aux_hint_apply(E_Client *ec)
+{
+   E_Comp_Wl_Aux_Hint *hint;
+   Eina_List *l;
+   Eina_Bool send;
+
+   if (!ec->comp_data) return;
+   if (!ec->comp_data->aux_hint.changed) return;
+
+   EINA_LIST_FOREACH(ec->comp_data->aux_hint.hints, l, hint)
+     {
+        if (!hint->changed) continue;
+
+        send = EINA_FALSE;
+        if (!strcmp(hint->hint, hint_names[E_POLICY_HINT_USER_GEOMETRY]))
+          {
+             if (hint->deleted)
+               {
+                  e_policy_allow_user_geometry_set(ec, EINA_FALSE);
+                  continue;
+               }
+
+             if (!strcmp(hint->val, "1"))
+               {
+                  send = EINA_TRUE;
+                  e_policy_allow_user_geometry_set(ec, EINA_TRUE);
+               }
+             else if (strcmp(hint->val, "1"))
+               {
+                  send = EINA_TRUE;
+                  e_policy_allow_user_geometry_set(ec, EINA_FALSE);
+               }
+          }
+        else if (!strcmp(hint->hint, hint_names[E_POLICY_HINT_FIXED_RESIZE]))
+          {
+             /* TODO: support other aux_hints */
+          }
+        else if (!strcmp(hint->hint, hint_names[E_POLICY_HINT_DEICONIFY_APPROVE_DISABLE]))
+          {
+             /* TODO: would implement after deiconify approve protocol provided */
+          }
+        else if (!strcmp(hint->hint, hint_names[E_POLICY_HINT_GESTURE_DISABLE]))
+          {
+             if (hint->deleted)
+               {
+                  ec->gesture_disable = EINA_FALSE;
+                  continue;
+               }
+
+             if (atoi(hint->val) == 1)
+               {
+                  ec->gesture_disable = EINA_TRUE;
+               }
+             else
+               {
+                  ec->gesture_disable = EINA_FALSE;
+               }
+          }
+        else if (!strcmp(hint->hint, hint_names[E_POLICY_HINT_ICONIFY]))
+          {
+             if (hint->deleted)
+               {
+                  ec->exp_iconify.skip_iconify = 0;
+                  EC_CHANGED(ec);
+                  continue;
+               }
+
+             if (!strcmp(hint->val, "disable"))
+               {
+                  ec->exp_iconify.skip_iconify = 1;
+                  EC_CHANGED(ec);
+               }
+             else if (!strcmp(hint->val, "enable"))
+               {
+                  ec->exp_iconify.skip_iconify = 0;
+                  EC_CHANGED(ec);
+               }
+          }
+        else if (!strcmp(hint->hint, hint_names[E_POLICY_HINT_ABOVE_LOCKSCREEN]))
+          {
+             if ((hint->deleted) ||
+                 (!strcmp(hint->val, "0")))
+               {
+                  E_Layer original_layer = ec->changable_layer[E_CHANGABLE_LAYER_TYPE_ABOVE_NOTIFICATION].saved_layer;
+                  if (ec->changable_layer[E_CHANGABLE_LAYER_TYPE_ABOVE_NOTIFICATION].set &&
+                      ec->changable_layer[E_CHANGABLE_LAYER_TYPE_ABOVE_NOTIFICATION].saved)
+                    {
+                       // restore original layer
+                       if (original_layer != evas_object_layer_get(ec->frame))
+                         {
+                            evas_object_layer_set(ec->frame, original_layer);
+                            ec->layer = original_layer;
+                         }
+                    }
+                  ec->changable_layer[E_CHANGABLE_LAYER_TYPE_ABOVE_NOTIFICATION].set = 0;
+                  ec->changable_layer[E_CHANGABLE_LAYER_TYPE_ABOVE_NOTIFICATION].saved = 0;
+                  ec->changable_layer[E_CHANGABLE_LAYER_TYPE_ABOVE_NOTIFICATION].saved_layer = 0;
+                  EC_CHANGED(ec);
+               }
+             else if (!strcmp(hint->val, "1"))
+               {
+                  if (!ec->changable_layer[E_CHANGABLE_LAYER_TYPE_ABOVE_NOTIFICATION].saved)
+                    {
+                       ec->changable_layer[E_CHANGABLE_LAYER_TYPE_ABOVE_NOTIFICATION].set = 1;
+                       ec->changable_layer[E_CHANGABLE_LAYER_TYPE_ABOVE_NOTIFICATION].saved = 0;
+                       ec->changable_layer[E_CHANGABLE_LAYER_TYPE_ABOVE_NOTIFICATION].saved_layer = ec->layer;
+                       EC_CHANGED(ec);
+                    }
+               }
+          }
+        else if (!strcmp(hint->hint, hint_names[E_POLICY_HINT_EFFECT_DISABLE]))
+          {
+             if ((hint->deleted) ||
+                 (!strcmp(hint->val, "0")))
+               {
+                  ec->animatable = 1;
+               }
+             else if (!strcmp(hint->val, "1"))
+               {
+                  ec->animatable = 0;
+               }
+          }
+
+        if (send)
+          _e_policy_wl_allowed_aux_hint_send(ec, hint->id);
+     }
+}
+
+void
+e_policy_wl_eval_pre_post_fetch(E_Client *ec)
+{
+   if (!ec) return;
+
+   _e_policy_wl_aux_hint_apply(ec);
+}
+
+static void
+_tzpol_iface_cb_aux_hint_add(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol, struct wl_resource *surf, int32_t id, const char *name, const char *value)
+{
+   E_Client *ec;
+   Eina_Bool res = EINA_FALSE;
+
+
+   ec = wl_resource_get_user_data(surf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   res = e_hints_aux_hint_add(ec, id, name, value);
+
+   ELOGF("TZPOL", "HINT_ADD |res_tzpol:0x%08x|id:%d, name:%s, val:%s, res:%d", ec->pixmap, ec, (unsigned int)res_tzpol, id, name, value, res);
+
+   if (res)
+     {
+        _e_policy_wl_aux_hint_apply(ec);
+        tizen_policy_send_allowed_aux_hint(res_tzpol, surf, id);
+        EC_CHANGED(ec);
+     }
+}
+
+static void
+_tzpol_iface_cb_aux_hint_change(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol, struct wl_resource *surf, int32_t id, const char *value)
+{
+   E_Client *ec;
+   Eina_Bool res = EINA_FALSE;
+
+   ec = wl_resource_get_user_data(surf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   res = e_hints_aux_hint_change(ec, id, value);
+
+   ELOGF("TZPOL", "HINT_CHD |res_tzpol:0x%08x|id:%d, val:%s, result:%d", ec->pixmap, ec, (unsigned int)res_tzpol, id, value, res);
+
+   if (res)
+     {
+        _e_policy_wl_aux_hint_apply(ec);
+        tizen_policy_send_allowed_aux_hint(res_tzpol, surf, id);
+        EC_CHANGED(ec);
+     }
+}
+
+static void
+_tzpol_iface_cb_aux_hint_del(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol, struct wl_resource *surf, int32_t id)
+{
+   E_Client *ec;
+   unsigned int res = -1;
+
+   ec = wl_resource_get_user_data(surf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   res = e_hints_aux_hint_del(ec, id);
+   ELOGF("TZPOL", "HINT_DEL |res_tzpol:0x%08x|id:%d, result:%d", ec->pixmap, ec, (unsigned int)res_tzpol, id, res);
+
+   if (res)
+     {
+        _e_policy_wl_aux_hint_apply(ec);
+        EC_CHANGED(ec);
+     }
+}
+
+static void
+_tzpol_iface_cb_supported_aux_hints_get(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol, struct wl_resource *surf)
+{
+   E_Client *ec;
+   const Eina_List *hints_list;
+   const Eina_List *l;
+   struct wl_array hints;
+   const char *hint_name;
+   int len;
+   char *p;
+
+   ec = wl_resource_get_user_data(surf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   hints_list = e_hints_aux_hint_supported_get();
+
+   wl_array_init(&hints);
+   EINA_LIST_FOREACH(hints_list, l, hint_name)
+     {
+        len = strlen(hint_name) + 1;
+        p = wl_array_add(&hints, len);
+
+        if (p == NULL)
+          break;
+        strncpy(p, hint_name, len);
+     }
+
+   tizen_policy_send_supported_aux_hints(res_tzpol, surf, &hints, eina_list_count(hints_list));
+   ELOGF("TZPOL",
+         "SEND     |res_tzpol:0x%08x|supported_hints size:%d",
+         ec->pixmap, ec,
+         (unsigned int)res_tzpol,
+         eina_list_count(hints_list));
+   wl_array_release(&hints);
+}
+
+static void
+e_client_background_state_set(E_Client *ec, Eina_Bool state)
+{
+   if (!ec) return;
+
+   ELOGF("TZPOL",
+         "BACKGROUND STATE %s for PID(%u)",
+         ec->pixmap, ec,
+         state?"SET":"UNSET", ec->netwm.pid);
+
+   if (state)
+     {
+        ec->comp_data->mapped = EINA_TRUE;
+        evas_object_hide(ec->frame);
+        EC_CHANGED(ec);
+     }
+   else
+     {
+        ec->comp_data->mapped = EINA_FALSE;
+         if ((ec->comp_data->shell.surface) && (ec->comp_data->shell.map))
+               ec->comp_data->shell.map(ec->comp_data->shell.surface);
+        evas_object_show(ec->frame);
+        e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
+     }
+}
+
+static void
+_e_policy_wl_background_state_set(E_Policy_Wl_Surface *psurf, Eina_Bool state)
+{
+   if (state)
+     {
+        if (psurf->ec)
+          e_client_background_state_set(psurf->ec, EINA_TRUE);
+        else
+          {
+             ELOGF("TZPOL",
+                   "PENDING BACKGROUND STATE SET for PID(%u) psurf:%p tzpol:%p",
+                   NULL, NULL, psurf->pid, psurf, psurf->tzpol);
+
+             if (!eina_list_data_find(psurf->tzpol->pending_bg, psurf))
+               psurf->tzpol->pending_bg =
+                  eina_list_append(psurf->tzpol->pending_bg, psurf);
+          }
+     }
+   else
+     {
+        if (psurf->ec)
+          e_client_background_state_set(psurf->ec, EINA_FALSE);
+        else
+          {
+             ELOGF("TZPOL",
+                   "UNSET PENDING BACKGROUND STATE for PID(%u) psurf:%p tzpol:%p",
+                   NULL, NULL, psurf->pid, psurf, psurf->tzpol);
+
+             if (eina_list_data_find(psurf->tzpol->pending_bg, psurf))
+               psurf->tzpol->pending_bg =
+                  eina_list_remove(psurf->tzpol->pending_bg, psurf);
+          }
+     }
+}
+
+static void
+_tzpol_iface_cb_background_state_set(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol, uint32_t pid)
+{
+   E_Policy_Wl_Tzpol *tzpol;
+   E_Policy_Wl_Surface *psurf;
+   Eina_List *psurfs = NULL, *clients = NULL;
+   E_Client *ec;
+
+   tzpol = _e_policy_wl_tzpol_get(res_tzpol);
+   EINA_SAFETY_ON_NULL_RETURN(tzpol);
+
+   if ((psurfs = _e_policy_wl_tzpol_surf_find_by_pid(tzpol, pid)))
+     {
+        EINA_LIST_FREE(psurfs, psurf)
+          {
+             if (psurf->is_background) continue;
+
+             _e_policy_wl_background_state_set(psurf, EINA_TRUE);
+          }
+
+        return;
+     }
+
+   clients = _e_policy_wl_e_clients_find_by_pid(pid);
+
+   if (clients)
+     {
+        EINA_LIST_FREE(clients, ec)
+          {
+             psurf = _e_policy_wl_surf_add(ec, res_tzpol);
+
+             ELOGF("TZPOL",
+                   "Register PID(%u) for BACKGROUND STATE psurf:%p tzpol:%p",
+                   ec->pixmap, ec, pid, psurf, psurf ? psurf->tzpol : NULL);
+          }
+     }
+   else
+     {
+        psurf = E_NEW(E_Policy_Wl_Surface, 1);
+        EINA_SAFETY_ON_NULL_RETURN(psurf);
+
+        psurf->tzpol = tzpol;
+        psurf->pid = pid;
+        psurf->ec = NULL;
+
+        tzpol->psurfs = eina_list_append(tzpol->psurfs, psurf);
+
+        ELOGF("TZPOL",
+              "Register PID(%u) for BACKGROUND STATE psurf:%p tzpol:%p",
+              NULL, NULL, pid, psurf, psurf->tzpol);
+     }
+
+   psurf->is_background = EINA_TRUE;
+   _e_policy_wl_background_state_set(psurf, EINA_TRUE);
+}
+
+static void
+_tzpol_iface_cb_background_state_unset(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol, uint32_t pid)
+{
+   E_Policy_Wl_Surface *psurf = NULL;
+   E_Policy_Wl_Tzpol *tzpol;
+   Eina_List *psurfs = NULL;
+
+   tzpol = _e_policy_wl_tzpol_get(res_tzpol);
+   EINA_SAFETY_ON_NULL_RETURN(tzpol);
+
+   if ((psurfs = _e_policy_wl_tzpol_surf_find_by_pid(tzpol, pid)))
+     {
+        EINA_LIST_FREE(psurfs, psurf)
+          {
+             if (!psurf->is_background) continue;
+             psurf->is_background = EINA_FALSE;
+             _e_policy_wl_background_state_set(psurf, EINA_FALSE);
+          }
+        return;
+     }
+}
+
+static void
+_e_policy_wl_floating_mode_apply(E_Client *ec, Eina_Bool floating)
+{
+   if (ec->floating == floating) return;
+
+   ec->floating = floating;
+
+   if (ec->frame)
+     {
+        if (floating)
+          evas_object_layer_set(ec->frame, E_LAYER_CLIENT_ABOVE);
+        else
+          evas_object_layer_set(ec->frame, E_LAYER_CLIENT_NORMAL);
+     }
+
+   EC_CHANGED(ec);
+}
+
+static void
+_tzpol_iface_cb_floating_mode_set(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol, struct wl_resource *surf)
+{
+   E_Client *ec;
+
+   ec = wl_resource_get_user_data(surf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   ELOGF("TZPOL", "FLOATING Set", ec->pixmap, ec);
+
+   _e_policy_wl_floating_mode_apply(ec, EINA_TRUE);
+}
+
+static void
+_tzpol_iface_cb_floating_mode_unset(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol, struct wl_resource *surf)
+{
+   E_Client *ec;
+
+   ec = wl_resource_get_user_data(surf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   ELOGF("TZPOL", "FLOATING Unset", ec->pixmap, ec);
+
+   _e_policy_wl_floating_mode_apply(ec, EINA_FALSE);
+}
+
+static void
+_tzpol_iface_cb_stack_mode_set(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol, struct wl_resource *surf, uint32_t mode)
+{
+   E_Client *ec;
+
+   ec = wl_resource_get_user_data(surf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   ELOGF("TZPOL", "STACK Mode Set. mode:%d", ec->pixmap, ec, mode);
+
+   if (ec->frame)
+     {
+        if (mode == TIZEN_POLICY_STACK_MODE_ABOVE)
+          {
+             evas_object_layer_set(ec->frame, E_LAYER_CLIENT_ABOVE);
+          }
+        else if (mode == TIZEN_POLICY_STACK_MODE_BELOW)
+          {
+             evas_object_layer_set(ec->frame, E_LAYER_CLIENT_BELOW);
+          }
+        else
+          {
+             evas_object_layer_set(ec->frame, E_LAYER_CLIENT_NORMAL);
+          }
+        EC_CHANGED(ec);
+     }
+}
+
+// --------------------------------------------------------
+// E_Policy_Wl_Tz_Dpy_Pol
+// --------------------------------------------------------
+static E_Policy_Wl_Tz_Dpy_Pol *
+_e_policy_wl_tz_dpy_pol_add(struct wl_resource *res_tz_dpy_pol)
+{
+   E_Policy_Wl_Tz_Dpy_Pol *tz_dpy_pol;
+
+   tz_dpy_pol = E_NEW(E_Policy_Wl_Tz_Dpy_Pol, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(tz_dpy_pol, NULL);
+
+   tz_dpy_pol->res_tz_dpy_pol = res_tz_dpy_pol;
+
+   polwl->tz_dpy_pols = eina_list_append(polwl->tz_dpy_pols, tz_dpy_pol);
+
+   return tz_dpy_pol;
+}
+
+static void
+_e_policy_wl_tz_dpy_pol_del(E_Policy_Wl_Tz_Dpy_Pol *tz_dpy_pol)
+{
+   E_Policy_Wl_Dpy_Surface *dpy_surf;
+
+   EINA_SAFETY_ON_NULL_RETURN(tz_dpy_pol);
+
+   polwl->tz_dpy_pols = eina_list_remove(polwl->tz_dpy_pols, tz_dpy_pol);
+
+   EINA_LIST_FREE(tz_dpy_pol->dpy_surfs, dpy_surf)
+     {
+        E_FREE(dpy_surf);
+     }
+
+   E_FREE(tz_dpy_pol);
+}
+
+static E_Policy_Wl_Tz_Dpy_Pol *
+_e_policy_wl_tz_dpy_pol_get(struct wl_resource *res_tz_dpy_pol)
+{
+   Eina_List *l;
+   E_Policy_Wl_Tz_Dpy_Pol *tz_dpy_pol;
+
+   EINA_LIST_FOREACH(polwl->tz_dpy_pols, l, tz_dpy_pol)
+     {
+        if (tz_dpy_pol->res_tz_dpy_pol == res_tz_dpy_pol)
+          return tz_dpy_pol;
+     }
+
+   return NULL;
+}
+
+// --------------------------------------------------------
+// E_Policy_Wl_Dpy_Surface
+// --------------------------------------------------------
+static E_Policy_Wl_Dpy_Surface *
+_e_policy_wl_dpy_surf_find(E_Policy_Wl_Tz_Dpy_Pol *tz_dpy_pol, E_Client *ec)
+{
+   Eina_List *l;
+   E_Policy_Wl_Dpy_Surface *dpy_surf;
+
+   EINA_LIST_FOREACH(tz_dpy_pol->dpy_surfs, l, dpy_surf)
+     {
+        if (dpy_surf->ec == ec)
+          return dpy_surf;
+     }
+
+   return NULL;
+}
+
+static E_Policy_Wl_Dpy_Surface *
+_e_policy_wl_dpy_surf_add(E_Client *ec, struct wl_resource *res_tz_dpy_pol)
+{
+   E_Policy_Wl_Tz_Dpy_Pol  *tz_dpy_pol = NULL;
+   E_Policy_Wl_Dpy_Surface *dpy_surf   = NULL;
+
+   tz_dpy_pol = _e_policy_wl_tz_dpy_pol_get(res_tz_dpy_pol);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(tz_dpy_pol, NULL);
+
+   dpy_surf = _e_policy_wl_dpy_surf_find(tz_dpy_pol, ec);
+   if (dpy_surf)
+     return dpy_surf;
+
+   dpy_surf = E_NEW(E_Policy_Wl_Dpy_Surface, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(dpy_surf, NULL);
+
+   dpy_surf->surf = ec->comp_data->surface;
+   dpy_surf->tz_dpy_pol = tz_dpy_pol;
+   dpy_surf->ec = ec;
+   dpy_surf->brightness = -1;
+
+   tz_dpy_pol->dpy_surfs = eina_list_append(tz_dpy_pol->dpy_surfs, dpy_surf);
+   return dpy_surf;
+}
+
+static void
+_e_policy_wl_dpy_surf_del(E_Client *ec)
+{
+   Eina_List *l;
+   E_Policy_Wl_Tz_Dpy_Pol *tz_dpy_pol;
+   E_Policy_Wl_Dpy_Surface *dpy_surf;
+
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   EINA_LIST_FOREACH(polwl->tz_dpy_pols, l, tz_dpy_pol)
+     {
+        dpy_surf = _e_policy_wl_dpy_surf_find(tz_dpy_pol, ec);
+        if (dpy_surf)
+          {
+             tz_dpy_pol->dpy_surfs = eina_list_remove(tz_dpy_pol->dpy_surfs, dpy_surf);
+             E_FREE(dpy_surf);
+          }
+     }
+}
+
+// --------------------------------------------------------
+// brightness
+// --------------------------------------------------------
+static Eina_Bool
+_e_policy_system_brightness_get(int *brightness)
+{
+   int error;
+   int sys_brightness = -1;
+
+   if (!brightness) return EINA_FALSE;
+
+   error = device_display_get_brightness(0, &sys_brightness);
+   if (error != DEVICE_ERROR_NONE)
+     {
+        // error
+        return EINA_FALSE;
+     }
+
+   *brightness = sys_brightness;
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_policy_system_brightness_set(int brightness)
+{
+   Eina_Bool ret;
+   int error;
+   int num_of_dpy;
+   int id;
+
+   ret = EINA_TRUE;
+
+   error = device_display_get_numbers(&num_of_dpy);
+   if (error != DEVICE_ERROR_NONE)
+     {
+        // error
+        return EINA_FALSE;
+     }
+
+   for (id = 0; id < num_of_dpy; id++)
+     {
+        error = device_display_set_brightness(id, brightness);
+        if (error != DEVICE_ERROR_NONE)
+          {
+             // error
+             ret = EINA_FALSE;
+             break;
+          }
+     }
+
+   return ret;
+}
+
+static Eina_Bool
+_e_policy_change_system_brightness(int new_brightness)
+{
+   Eina_Bool ret;
+   int sys_brightness;
+
+   if (!e_policy_system_info.brightness.use_client)
+     {
+        // save system brightness
+        ret = _e_policy_system_brightness_get(&sys_brightness);
+        if (!ret)
+          {
+             return EINA_FALSE;
+          }
+        e_policy_system_info.brightness.system = sys_brightness;
+     }
+
+   ret = _e_policy_system_brightness_set(new_brightness);
+   if (!ret)
+     {
+        return EINA_FALSE;
+     }
+   e_policy_system_info.brightness.client = new_brightness;
+   e_policy_system_info.brightness.use_client = EINA_TRUE;
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_policy_restore_system_brightness(void)
+{
+   Eina_Bool ret;
+
+   if (!e_policy_system_info.brightness.use_client) return EINA_TRUE;
+
+   // restore system brightness
+   ret = _e_policy_system_brightness_set(e_policy_system_info.brightness.system);
+   if (!ret)
+     {
+        return EINA_FALSE;
+     }
+   e_policy_system_info.brightness.use_client = EINA_FALSE;
+
+   // Todo:
+   // if there are another window which set brighteness, then we change brighteness of it
+   // if no, then we rollback system brightness
+
+   return EINA_TRUE;
+}
+
+Eina_Bool
+e_policy_wl_win_brightness_apply(E_Client *ec)
+{
+   Eina_Bool ret;
+   Eina_List *l;
+   E_Policy_Wl_Tz_Dpy_Pol *tz_dpy_pol;
+   E_Policy_Wl_Dpy_Surface *dpy_surf = NULL;
+   int ec_visibility;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
+   if (e_object_is_del(E_OBJECT(ec)))
+     ec_visibility = E_VISIBILITY_FULLY_OBSCURED;
+   else
+     ec_visibility = ec->visibility.obscured;
+
+   EINA_LIST_FOREACH(polwl->tz_dpy_pols, l, tz_dpy_pol)
+     {
+        dpy_surf = _e_policy_wl_dpy_surf_find(tz_dpy_pol, ec);
+        if (dpy_surf)
+          break;
+     }
+
+   if (!dpy_surf) return EINA_FALSE;
+   if (!dpy_surf->set) return EINA_FALSE;
+
+   // use system brightness
+   if (dpy_surf->brightness < 0)
+     {
+        ELOGF("TZ_DPY_POL", "Restore system brightness. Win(0x%08x)'s brightness:%d", ec->pixmap, ec, e_client_util_win_get(ec), dpy_surf->brightness);
+        ret = _e_policy_restore_system_brightness();
+        return ret;
+     }
+
+   if (ec_visibility == E_VISIBILITY_UNOBSCURED)
+     {
+        ELOGF("TZ_DPY_POL", "Change system brightness(%d). Win(0x%08x) is un-obscured", ec->pixmap, ec, dpy_surf->brightness, e_client_util_win_get(ec));
+        ret = _e_policy_change_system_brightness(dpy_surf->brightness);
+        if (!ret) return EINA_FALSE;
+     }
+   else
+     {
+        ELOGF("TZ_DPY_POL", "Restore system brightness. Win(0x%08x) is obscured", ec->pixmap, ec, e_client_util_win_get(ec));
+        ret = _e_policy_restore_system_brightness();
+        if (!ret) return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+}
+
+static void
+_tz_dpy_pol_iface_cb_brightness_set(struct wl_client *client, struct wl_resource *res_tz_dpy_pol, struct wl_resource *surf, int32_t brightness)
+{
+   E_Client *ec;
+   E_Policy_Wl_Dpy_Surface *dpy_surf;
+   int fd;
+
+   ec = wl_resource_get_user_data(surf);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   dpy_surf = _e_policy_wl_dpy_surf_add(ec, res_tz_dpy_pol);
+   EINA_SAFETY_ON_NULL_RETURN(dpy_surf);
+
+   fd = wl_client_get_fd(client);
+   if (!_e_policy_wl_privilege_check(fd, PRIVILEGE_BRIGHTNESS_SET))
+     {
+        ELOGF("TZ_DPY_POL",
+              "Privilege Check Failed! DENY set_brightness",
+              ec->pixmap, ec);
+
+        tizen_display_policy_send_window_brightness_done
+           (res_tz_dpy_pol,
+            surf,
+            -1,
+            TIZEN_DISPLAY_POLICY_ERROR_STATE_PERMISSION_DENIED);
+        return;
+     }
+   ELOGF("TZ_DPY_POL", "Set Win(0x%08x)'s brightness:%d", ec->pixmap, ec, e_client_util_win_get(ec), brightness);
+   dpy_surf->set = EINA_TRUE;
+   dpy_surf->brightness = brightness;
+
+   e_policy_wl_win_brightness_apply(ec);
+
+   tizen_display_policy_send_window_brightness_done
+      (res_tz_dpy_pol, surf, brightness, TIZEN_DISPLAY_POLICY_ERROR_STATE_NONE);
+}
+
+// --------------------------------------------------------
+// tizen_policy_interface
+// --------------------------------------------------------
+static const struct tizen_policy_interface _tzpol_iface =
+{
+   _tzpol_iface_cb_vis_get,
+   _tzpol_iface_cb_pos_get,
+   _tzpol_iface_cb_activate,
+   _tzpol_iface_cb_activate_below_by_res_id,
+   _tzpol_iface_cb_raise,
+   _tzpol_iface_cb_lower,
+   _tzpol_iface_cb_lower_by_res_id,
+   _tzpol_iface_cb_focus_skip_set,
+   _tzpol_iface_cb_focus_skip_unset,
+   _tzpol_iface_cb_role_set,
+   _tzpol_iface_cb_type_set,
+   _tzpol_iface_cb_conformant_set,
+   _tzpol_iface_cb_conformant_unset,
+   _tzpol_iface_cb_conformant_get,
+   _tzpol_iface_cb_notilv_set,
+   _tzpol_iface_cb_transient_for_set,
+   _tzpol_iface_cb_transient_for_unset,
+   _tzpol_iface_cb_win_scrmode_set,
+   _tzpol_iface_cb_subsurf_place_below_parent,
+   _tzpol_iface_cb_subsurf_stand_alone_set,
+   _tzpol_iface_cb_subsurface_get,
+   _tzpol_iface_cb_opaque_state_set,
+   _tzpol_iface_cb_iconify,
+   _tzpol_iface_cb_uniconify,
+   _tzpol_iface_cb_aux_hint_add,
+   _tzpol_iface_cb_aux_hint_change,
+   _tzpol_iface_cb_aux_hint_del,
+   _tzpol_iface_cb_supported_aux_hints_get,
+   _tzpol_iface_cb_background_state_set,
+   _tzpol_iface_cb_background_state_unset,
+   _tzpol_iface_cb_floating_mode_set,
+   _tzpol_iface_cb_floating_mode_unset,
+   _tzpol_iface_cb_stack_mode_set,
+};
+
+static void
+_tzpol_cb_unbind(struct wl_resource *res_tzpol)
+{
+   E_Policy_Wl_Tzpol *tzpol;
+
+   tzpol = _e_policy_wl_tzpol_get(res_tzpol);
+   EINA_SAFETY_ON_NULL_RETURN(tzpol);
+
+   eina_hash_del_by_key(polwl->tzpols, &res_tzpol);
+}
+
+static void
+_tzpol_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t ver, uint32_t id)
+{
+   E_Policy_Wl_Tzpol *tzpol;
+   struct wl_resource *res_tzpol;
+
+   EINA_SAFETY_ON_NULL_GOTO(polwl, err);
+
+   res_tzpol = wl_resource_create(client,
+                                  &tizen_policy_interface,
+                                  ver,
+                                  id);
+   EINA_SAFETY_ON_NULL_GOTO(res_tzpol, err);
+
+   tzpol = _e_policy_wl_tzpol_add(res_tzpol);
+   EINA_SAFETY_ON_NULL_GOTO(tzpol, err);
+
+   wl_resource_set_implementation(res_tzpol,
+                                  &_tzpol_iface,
+                                  NULL,
+                                  _tzpol_cb_unbind);
+   return;
+
+err:
+   ERR("Could not create tizen_policy_interface res: %m");
+   wl_client_post_no_memory(client);
+}
+
+// --------------------------------------------------------
+// tizen_display_policy_interface
+// --------------------------------------------------------
+static const struct tizen_display_policy_interface _tz_dpy_pol_iface =
+{
+   _tz_dpy_pol_iface_cb_brightness_set,
+};
+
+static void
+_tz_dpy_pol_cb_unbind(struct wl_resource *res_tz_dpy_pol)
+{
+   E_Policy_Wl_Tz_Dpy_Pol *tz_dpy_pol;
+
+   tz_dpy_pol = _e_policy_wl_tz_dpy_pol_get(res_tz_dpy_pol);
+   EINA_SAFETY_ON_NULL_RETURN(tz_dpy_pol);
+
+   _e_policy_wl_tz_dpy_pol_del(tz_dpy_pol);
+}
+
+static void
+_tz_dpy_pol_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t ver, uint32_t id)
+{
+   E_Policy_Wl_Tz_Dpy_Pol *tz_dpy_pol;
+   struct wl_resource *res_tz_dpy_pol;
+
+   EINA_SAFETY_ON_NULL_GOTO(polwl, err);
+
+   res_tz_dpy_pol = wl_resource_create(client,
+                                       &tizen_display_policy_interface,
+                                       ver,
+                                       id);
+   EINA_SAFETY_ON_NULL_GOTO(res_tz_dpy_pol, err);
+
+   tz_dpy_pol = _e_policy_wl_tz_dpy_pol_add(res_tz_dpy_pol);
+   EINA_SAFETY_ON_NULL_GOTO(tz_dpy_pol, err);
+
+   wl_resource_set_implementation(res_tz_dpy_pol,
+                                  &_tz_dpy_pol_iface,
+                                  NULL,
+                                  _tz_dpy_pol_cb_unbind);
+   return;
+
+err:
+   ERR("Could not create tizen_display_policy_interface res: %m");
+   wl_client_post_no_memory(client);
+}
+
+// --------------------------------------------------------
+// tizen_ws_shell_interface::service
+// --------------------------------------------------------
+static void
+_tzsh_srv_iface_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzsh_srv)
+{
+   wl_resource_destroy(res_tzsh_srv);
+}
+
+static void
+_tzsh_srv_iface_cb_region_set(struct wl_client *client, struct wl_resource *res_tzsh_srv, int32_t type, int32_t angle, struct wl_resource *res_reg)
+{
+   E_Policy_Wl_Tzsh_Srv *tzsh_srv;
+   E_Policy_Wl_Tzsh_Region *tzsh_reg;
+
+   tzsh_srv = wl_resource_get_user_data(res_tzsh_srv);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_srv);
+
+   if (!eina_list_data_find(polwl->tzsh_srvs, tzsh_srv))
+     return;
+
+   tzsh_reg = wl_resource_get_user_data(res_reg);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_reg);
+
+   if (tzsh_srv->role == TZSH_SRV_ROLE_QUICKPANEL)
+     e_service_quickpanel_region_set(type, angle, tzsh_reg->tiler);
+   else if (tzsh_srv->role == TZSH_SRV_ROLE_VOLUME)
+     e_service_volume_region_set(type, angle, tzsh_reg->tiler);
+}
+
+static void
+_tzsh_srv_iface_cb_indicator_get(struct wl_client *client, struct wl_resource *res_tzsh_srv, uint32_t id)
+{
+   E_Policy_Wl_Tzsh_Srv *tzsh_srv;
+
+   tzsh_srv = wl_resource_get_user_data(res_tzsh_srv);
+
+   if (!eina_list_data_find(polwl->tzsh_srvs, tzsh_srv))
+     return;
+
+   /* TODO: create tws_indicator_service resource. */
+}
+
+static void
+_tzsh_srv_qp_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
+{
+   wl_resource_destroy(resource);
+}
+
+static void
+_tzsh_srv_qp_cb_msg(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t msg)
+{
+   E_Policy_Wl_Tzsh_Srv *tzsh_srv;
+
+   tzsh_srv = wl_resource_get_user_data(resource);
+
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_srv);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_srv->tzsh);
+
+#define EC  tzsh_srv->tzsh->ec
+   EINA_SAFETY_ON_NULL_RETURN(EC);
+
+   switch (msg)
+     {
+      case TWS_SERVICE_QUICKPANEL_MSG_SHOW:
+         e_service_quickpanel_show();
+         break;
+      case TWS_SERVICE_QUICKPANEL_MSG_HIDE:
+         e_service_quickpanel_hide();
+         break;
+      default:
+         ERR("Unknown message!! msg %d", msg);
+         break;
+     }
+#undef EC
+}
+
+static const struct tws_service_quickpanel_interface _tzsh_srv_qp_iface =
+{
+   _tzsh_srv_qp_cb_destroy,
+   _tzsh_srv_qp_cb_msg
+};
+
+static void
+_tzsh_srv_iface_cb_quickpanel_get(struct wl_client *client, struct wl_resource *res_tzsh_srv, uint32_t id)
+{
+   E_Policy_Wl_Tzsh_Srv *tzsh_srv;
+   struct wl_resource *res;
+
+   tzsh_srv = wl_resource_get_user_data(res_tzsh_srv);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_srv);
+
+   if (!eina_list_data_find(polwl->tzsh_srvs, tzsh_srv))
+     return;
+
+   res = wl_resource_create(client, &tws_service_quickpanel_interface, 1, id);
+   if (!res)
+     {
+        wl_client_post_no_memory(client);
+        return;
+     }
+
+   wl_resource_set_implementation(res, &_tzsh_srv_qp_iface, tzsh_srv, NULL);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+static void
+_tzsh_srv_scrsaver_cb_release(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
+{
+   wl_resource_destroy(resource);
+}
+
+static const struct tws_service_screensaver_interface _tzsh_srv_scrsaver_iface =
+{
+   _tzsh_srv_scrsaver_cb_release
+};
+
+static void
+_tzsh_srv_iface_cb_scrsaver_get(struct wl_client *client, struct wl_resource *res_tzsh_srv, uint32_t id)
+{
+   E_Policy_Wl_Tzsh_Srv *tzsh_srv;
+   struct wl_resource *res;
+
+   tzsh_srv = wl_resource_get_user_data(res_tzsh_srv);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_srv);
+
+   if (!eina_list_data_find(polwl->tzsh_srvs, tzsh_srv))
+     return;
+
+   res = wl_resource_create(client, &tws_service_screensaver_interface, 1, id);
+   if (!res)
+     {
+        wl_client_post_no_memory(client);
+        return;
+     }
+
+   wl_resource_set_implementation(res, &_tzsh_srv_scrsaver_iface, tzsh_srv, NULL);
+}
+
+static void
+_tzsh_srv_scrsaver_mng_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
+{
+   _scrsaver_mng_res = NULL;
+   wl_resource_destroy(resource);
+}
+
+static void
+_tzsh_srv_scrsaver_mng_cb_idle_time_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t time)
+{
+   E_Policy_Wl_Tzsh_Srv *tzsh_srv;
+   double timeout;
+
+   tzsh_srv = wl_resource_get_user_data(resource);
+
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_srv);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_srv->tzsh);
+
+   /* convert time to seconds (double) from milliseconds (unsigned int) */
+   timeout = (double)time * 0.001f;
+
+   e_screensaver_timeout_set(timeout);
+}
+
+static const struct tws_service_screensaver_manager_interface _tzsh_srv_scrsaver_mng_iface =
+{
+   _tzsh_srv_scrsaver_mng_cb_destroy,
+   _tzsh_srv_scrsaver_mng_cb_idle_time_set
+};
+
+static void
+_tzsh_srv_iface_cb_scrsaver_mng_get(struct wl_client *client, struct wl_resource *res_tzsh_srv, uint32_t id)
+{
+   E_Policy_Wl_Tzsh_Srv *tzsh_srv;
+   struct wl_resource *res;
+
+   tzsh_srv = wl_resource_get_user_data(res_tzsh_srv);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_srv);
+
+   if (!eina_list_data_find(polwl->tzsh_srvs, tzsh_srv))
+     return;
+
+   res = wl_resource_create(client, &tws_service_screensaver_manager_interface, 1, id);
+   if (!res)
+     {
+        wl_client_post_no_memory(client);
+        return;
+     }
+
+   _scrsaver_mng_res = res;
+
+   wl_resource_set_implementation(res, &_tzsh_srv_scrsaver_mng_iface, tzsh_srv, NULL);
+}
+
+static const struct tws_service_interface _tzsh_srv_iface =
+{
+   _tzsh_srv_iface_cb_destroy,
+   _tzsh_srv_iface_cb_region_set,
+   _tzsh_srv_iface_cb_indicator_get,
+   _tzsh_srv_iface_cb_quickpanel_get,
+   _tzsh_srv_iface_cb_scrsaver_mng_get,
+   _tzsh_srv_iface_cb_scrsaver_get
+};
+
+static void
+_tzsh_cb_srv_destroy(struct wl_resource *res_tzsh_srv)
+{
+   E_Policy_Wl_Tzsh_Srv *tzsh_srv;
+
+   tzsh_srv = wl_resource_get_user_data(res_tzsh_srv);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_srv);
+
+   if (!eina_list_data_find(polwl->tzsh_srvs, tzsh_srv))
+     return;
+
+   _e_policy_wl_tzsh_srv_del(tzsh_srv);
+}
+
+static void
+_tzsh_iface_cb_srv_create(struct wl_client *client, struct wl_resource *res_tzsh, uint32_t id, uint32_t surf_id, const char *name)
+{
+   E_Policy_Wl_Tzsh *tzsh;
+   E_Policy_Wl_Tzsh_Srv *tzsh_srv;
+   struct wl_resource *res_tzsh_srv;
+   E_Client *ec;
+   E_Pixmap *cp;
+   int role;
+
+   role = _e_policy_wl_tzsh_srv_role_get(name);
+   if (role == TZSH_SRV_ROLE_UNKNOWN)
+     {
+        wl_resource_post_error
+          (res_tzsh,
+           WL_DISPLAY_ERROR_INVALID_OBJECT,
+           "Invalid res_tzsh");
+        return;
+     }
+
+   tzsh = wl_resource_get_user_data(res_tzsh);
+   if (!tzsh)
+     {
+        wl_resource_post_error
+          (res_tzsh,
+           WL_DISPLAY_ERROR_INVALID_OBJECT,
+           "Invalid res_tzsh's user data");
+        return;
+     }
+
+   cp = _e_policy_wl_e_pixmap_get_from_id(client, surf_id);
+   if (!cp)
+     {
+        wl_resource_post_error
+          (res_tzsh,
+           WL_DISPLAY_ERROR_INVALID_OBJECT,
+           "Invalid surface id");
+        return;
+     }
+
+   ec = e_pixmap_client_get(cp);
+   if (ec)
+     {
+        if (!_e_policy_wl_e_client_is_valid(ec))
+          {
+             wl_resource_post_error
+               (res_tzsh,
+                WL_DISPLAY_ERROR_INVALID_OBJECT,
+                "Invalid surface id");
+             return;
+          }
+     }
+
+   res_tzsh_srv = wl_resource_create(client,
+                                     &tws_service_interface,
+                                     wl_resource_get_version(res_tzsh),
+                                     id);
+   if (!res_tzsh_srv)
+     {
+        ERR("Could not create tws_service resource: %m");
+        wl_client_post_no_memory(client);
+        return;
+     }
+
+   _e_policy_wl_tzsh_data_set(tzsh, TZSH_TYPE_SRV, cp, ec);
+
+   tzsh_srv = _e_policy_wl_tzsh_srv_add(tzsh,
+                                   role,
+                                   res_tzsh_srv,
+                                   name);
+   if (!tzsh_srv)
+     {
+        ERR("Could not create WS_Shell_Service");
+        wl_client_post_no_memory(client);
+        wl_resource_destroy(res_tzsh_srv);
+        return;
+     }
+
+   wl_resource_set_implementation(res_tzsh_srv,
+                                  &_tzsh_srv_iface,
+                                  tzsh_srv,
+                                  _tzsh_cb_srv_destroy);
+
+   if (role == TZSH_SRV_ROLE_QUICKPANEL)
+     e_service_quickpanel_client_set(tzsh->ec);
+   else if (role == TZSH_SRV_ROLE_VOLUME)
+     e_service_volume_client_set(tzsh->ec);
+   else if (role == TZSH_SRV_ROLE_LOCKSCREEN)
+     e_service_lockscreen_client_set(tzsh->ec);
+   else if (role == TZSH_SRV_ROLE_SCREENSAVER_MNG)
+     e_service_lockscreen_client_set(tzsh->ec);
+   else if (role == TZSH_SRV_ROLE_SCREENSAVER)
+     e_service_lockscreen_client_set(tzsh->ec);
+}
+
+// --------------------------------------------------------
+// tizen_ws_shell_interface::region
+// --------------------------------------------------------
+static void
+_tzsh_reg_cb_shell_destroy(struct wl_listener *listener, void *data)
+{
+   E_Policy_Wl_Tzsh_Region *tzsh_reg;
+
+   tzsh_reg = container_of(listener, E_Policy_Wl_Tzsh_Region, destroy_listener);
+
+   if (tzsh_reg->res_tzsh_reg)
+     {
+        wl_resource_destroy(tzsh_reg->res_tzsh_reg);
+        tzsh_reg->res_tzsh_reg = NULL;
+     }
+}
+
+static void
+_tzsh_reg_iface_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzsh_reg)
+{
+   wl_resource_destroy(res_tzsh_reg);
+}
+
+static void
+_tzsh_reg_iface_cb_add(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzsh_reg, int32_t x, int32_t y, int32_t w, int32_t h)
+{
+   E_Policy_Wl_Tzsh_Region *tzsh_reg;
+   Eina_Tiler *src;
+   int area_w = 0, area_h = 0;
+
+   tzsh_reg = wl_resource_get_user_data(res_tzsh_reg);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_reg);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_reg->tiler);
+
+   eina_tiler_area_size_get(tzsh_reg->tiler, &area_w, &area_h);
+   src = eina_tiler_new(area_w, area_h);
+   eina_tiler_tile_size_set(src, 1, 1);
+   eina_tiler_rect_add(src, &(Eina_Rectangle){x, y, w, h});
+   eina_tiler_union(tzsh_reg->tiler, src);
+   eina_tiler_free(src);
+}
+
+static void
+_tzsh_reg_iface_cb_subtract(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzsh_reg, int32_t x, int32_t y, int32_t w, int32_t h)
+{
+   E_Policy_Wl_Tzsh_Region *tzsh_reg;
+   Eina_Tiler *src;
+   int area_w = 0, area_h = 0;
+
+   tzsh_reg = wl_resource_get_user_data(res_tzsh_reg);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_reg);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_reg->tiler);
+
+   eina_tiler_area_size_get(tzsh_reg->tiler, &area_w, &area_h);
+   src = eina_tiler_new(area_w, area_h);
+   eina_tiler_tile_size_set(src, 1, 1);
+   eina_tiler_rect_add(src, &(Eina_Rectangle){x, y, w, h});
+   eina_tiler_subtract(tzsh_reg->tiler, src);
+   eina_tiler_free(src);
+}
+
+static const struct tws_region_interface _tzsh_reg_iface =
+{
+   _tzsh_reg_iface_cb_destroy,
+   _tzsh_reg_iface_cb_add,
+   _tzsh_reg_iface_cb_subtract
+};
+
+static void
+_tzsh_reg_cb_destroy(struct wl_resource *res_tzsh_reg)
+{
+   E_Policy_Wl_Tzsh_Region *tzsh_reg;
+
+   tzsh_reg = wl_resource_get_user_data(res_tzsh_reg);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_reg);
+
+   wl_list_remove(&tzsh_reg->destroy_listener.link);
+   eina_tiler_free(tzsh_reg->tiler);
+
+   E_FREE(tzsh_reg);
+}
+
+static void
+_tzsh_iface_cb_reg_create(struct wl_client *client, struct wl_resource *res_tzsh, uint32_t id)
+{
+   E_Policy_Wl_Tzsh *tzsh;
+   E_Policy_Wl_Tzsh_Region *tzsh_reg = NULL;
+   Eina_Tiler *tz = NULL;
+   struct wl_resource *res_tzsh_reg;
+   int zw = 0, zh = 0;
+
+   tzsh = wl_resource_get_user_data(res_tzsh);
+   if (!tzsh)
+     {
+        wl_resource_post_error
+          (res_tzsh,
+           WL_DISPLAY_ERROR_INVALID_OBJECT,
+           "Invalid res_tzsh's user data");
+        return;
+     }
+
+   tzsh_reg = E_NEW(E_Policy_Wl_Tzsh_Region, 1);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_reg);
+
+   e_zone_useful_geometry_get(e_zone_current_get(),
+                              NULL, NULL, &zw, &zh);
+
+   tz = eina_tiler_new(zw, zh);
+   EINA_SAFETY_ON_NULL_GOTO(tz, err);
+   tzsh_reg->tiler = tz;
+
+   eina_tiler_tile_size_set(tzsh_reg->tiler, 1, 1);
+
+   if (!(res_tzsh_reg = wl_resource_create(client,
+                                           &tws_region_interface,
+                                           wl_resource_get_version(res_tzsh),
+                                           id)))
+     {
+        ERR("Could not create tws_service resource: %m");
+        wl_client_post_no_memory(client);
+        goto err;
+     }
+
+   wl_resource_set_implementation(res_tzsh_reg,
+                                  &_tzsh_reg_iface,
+                                  tzsh_reg,
+                                  _tzsh_reg_cb_destroy);
+
+   tzsh_reg->tzsh = tzsh;
+   tzsh_reg->res_tzsh_reg = res_tzsh_reg;
+   tzsh_reg->destroy_listener.notify = _tzsh_reg_cb_shell_destroy;
+
+   wl_resource_add_destroy_listener(res_tzsh,
+                                    &tzsh_reg->destroy_listener);
+   return;
+
+err:
+   if (tzsh_reg->tiler) eina_tiler_free(tzsh_reg->tiler);
+   E_FREE(tzsh_reg);
+}
+
+// --------------------------------------------------------
+// tizen_ws_shell_interface::quickpanel
+// --------------------------------------------------------
+EINTERN void
+e_tzsh_qp_state_visible_update(E_Client *ec, Eina_Bool vis)
+{
+   E_Policy_Wl_Tzsh_Client *tzsh_client;
+   struct wl_array states;
+   E_Tzsh_QP_Event *ev;
+
+   tzsh_client = _e_policy_wl_tzsh_client_get_from_client(ec);
+   if (!tzsh_client) return;
+
+   wl_array_init(&states);
+
+   ev = wl_array_add(&states, sizeof(E_Tzsh_QP_Event));
+
+   ev->type = TWS_QUICKPANEL_STATE_TYPE_VISIBILITY;
+   ev->val = vis ? TWS_QUICKPANEL_STATE_VALUE_VISIBLE_SHOW : TWS_QUICKPANEL_STATE_VALUE_VISIBLE_HIDE;
+
+   tws_quickpanel_send_state_changed(tzsh_client->res_tzsh_client, &states);
+
+   wl_array_release(&states);
+}
+
+EINTERN void
+e_tzsh_qp_state_scrollable_update(E_Client *ec, Eina_Bool scrollable)
+{
+   E_Policy_Wl_Tzsh_Client *tzsh_client;
+   struct wl_array states;
+   E_Tzsh_QP_Event *ev;
+
+   tzsh_client = _e_policy_wl_tzsh_client_get_from_client(ec);
+   if (!tzsh_client) return;
+
+   wl_array_init(&states);
+
+   ev = wl_array_add(&states, sizeof(E_Tzsh_QP_Event));
+
+   ev->type = TWS_QUICKPANEL_STATE_TYPE_SCROLLABLE;
+   ev->val = scrollable ? TWS_QUICKPANEL_STATE_VALUE_SCROLLABLE_SET : TWS_QUICKPANEL_STATE_VALUE_SCROLLABLE_UNSET;
+
+   tws_quickpanel_send_state_changed(tzsh_client->res_tzsh_client, &states);
+
+   wl_array_release(&states);
+}
+
+EINTERN void
+e_tzsh_qp_state_orientation_update(E_Client *ec, int ridx)
+{
+   E_Policy_Wl_Tzsh_Client *tzsh_client;
+   struct wl_array states;
+   E_Tzsh_QP_Event *ev;
+
+   tzsh_client = _e_policy_wl_tzsh_client_get_from_client(ec);
+   if (!tzsh_client) return;
+
+   wl_array_init(&states);
+
+   ev = wl_array_add(&states, sizeof(E_Tzsh_QP_Event));
+
+   ev->type = TWS_QUICKPANEL_STATE_TYPE_ORIENTATION;
+   ev->val = TWS_QUICKPANEL_STATE_VALUE_ORIENTATION_0 + ridx;
+
+   tws_quickpanel_send_state_changed(tzsh_client->res_tzsh_client, &states);
+
+   wl_array_release(&states);
+}
+
+static void
+_tzsh_qp_iface_cb_release(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzsh_qp)
+{
+   wl_resource_destroy(res_tzsh_qp);
+}
+
+static void
+_tzsh_qp_iface_cb_show(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzsh_qp)
+{
+   E_Policy_Wl_Tzsh_Client *tzsh_client;
+   E_Client *ec;
+
+   tzsh_client = wl_resource_get_user_data(res_tzsh_qp);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_client);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_client->tzsh);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_client->tzsh->ec);
+
+   ec = tzsh_client->tzsh->ec;
+
+   if (!eina_list_data_find(polwl->tzsh_clients, tzsh_client))
+     return;
+
+   e_qp_client_show(ec);
+}
+
+static void
+_tzsh_qp_iface_cb_hide(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzsh_qp)
+{
+   E_Policy_Wl_Tzsh_Client *tzsh_client;
+   E_Client *ec;
+
+   tzsh_client = wl_resource_get_user_data(res_tzsh_qp);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_client);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_client->tzsh);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_client->tzsh->ec);
+
+   ec = tzsh_client->tzsh->ec;
+
+   if (!eina_list_data_find(polwl->tzsh_clients, tzsh_client))
+     return;
+
+   e_qp_client_hide(ec);
+}
+
+static void
+_tzsh_qp_iface_cb_enable(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzsh_qp)
+{
+   E_Policy_Wl_Tzsh_Client *tzsh_client;
+   E_Client *ec;
+
+   tzsh_client = wl_resource_get_user_data(res_tzsh_qp);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_client);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_client->tzsh);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_client->tzsh->ec);
+
+   ec = tzsh_client->tzsh->ec;
+
+   if (!eina_list_data_find(polwl->tzsh_clients, tzsh_client))
+     return;
+
+   e_qp_client_scrollable_set(ec, EINA_TRUE);
+}
+
+static void
+_tzsh_qp_iface_cb_disable(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzsh_qp)
+{
+   E_Policy_Wl_Tzsh_Client *tzsh_client;
+   E_Client *ec;
+
+   tzsh_client = wl_resource_get_user_data(res_tzsh_qp);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_client);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_client->tzsh);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_client->tzsh->ec);
+
+   ec = tzsh_client->tzsh->ec;
+
+   if (!eina_list_data_find(polwl->tzsh_clients, tzsh_client))
+     return;
+
+   e_qp_client_scrollable_set(ec, EINA_FALSE);
+}
+
+static void
+_tzsh_qp_iface_cb_state_get(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzsh_qp, int32_t type)
+{
+   E_Policy_Wl_Tzsh_Client *tzsh_client;
+   E_Client *ec;
+   Eina_Bool vis, scrollable;
+   int ridx;
+   int val = TWS_QUICKPANEL_STATE_VALUE_UNKNOWN;
+
+   tzsh_client = wl_resource_get_user_data(res_tzsh_qp);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_client);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_client->tzsh);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_client->tzsh->ec);
+
+   ec = tzsh_client->tzsh->ec;
+
+   if (!eina_list_data_find(polwl->tzsh_clients, tzsh_client))
+     return;
+
+   switch (type)
+     {
+      case TWS_QUICKPANEL_STATE_TYPE_VISIBILITY:
+        val = TWS_QUICKPANEL_STATE_VALUE_VISIBLE_HIDE;
+        vis = e_qp_visible_get();
+        if (vis) val = TWS_QUICKPANEL_STATE_VALUE_VISIBLE_SHOW;
+        break;
+      case TWS_QUICKPANEL_STATE_TYPE_SCROLLABLE:
+        val = TWS_QUICKPANEL_STATE_VALUE_SCROLLABLE_UNSET;
+        scrollable = e_qp_client_scrollable_get(ec);
+        if (scrollable) val = TWS_QUICKPANEL_STATE_VALUE_SCROLLABLE_SET;
+        break;
+      case TWS_QUICKPANEL_STATE_TYPE_ORIENTATION:
+        ridx = e_qp_orientation_get();
+        val = TWS_QUICKPANEL_STATE_VALUE_ORIENTATION_0 + ridx;
+        break;
+      default:
+        break;
+     }
+
+   tws_quickpanel_send_state_get_done(res_tzsh_qp, type, val, 0);
+}
+
+static const struct tws_quickpanel_interface _tzsh_qp_iface =
+{
+   _tzsh_qp_iface_cb_release,
+   _tzsh_qp_iface_cb_show,
+   _tzsh_qp_iface_cb_hide,
+   _tzsh_qp_iface_cb_enable,
+   _tzsh_qp_iface_cb_disable,
+   _tzsh_qp_iface_cb_state_get
+};
+
+static void
+_tzsh_cb_qp_destroy(struct wl_resource *res_tzsh_qp)
+{
+   E_Policy_Wl_Tzsh_Client *tzsh_client;
+
+   tzsh_client = wl_resource_get_user_data(res_tzsh_qp);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_client);
+
+   _e_policy_wl_tzsh_client_del(tzsh_client);
+}
+
+static void
+_tzsh_iface_cb_qp_get(struct wl_client *client, struct wl_resource *res_tzsh, uint32_t id, uint32_t surf_id)
+{
+   E_Policy_Wl_Tzsh *tzsh;
+   E_Policy_Wl_Tzsh_Client *tzsh_client;
+   struct wl_resource *res_tzsh_qp;
+   E_Client *ec;
+   E_Pixmap *cp;
+
+   tzsh = wl_resource_get_user_data(res_tzsh);
+   if (!tzsh)
+     {
+        wl_resource_post_error
+          (res_tzsh,
+           WL_DISPLAY_ERROR_INVALID_OBJECT,
+           "Invalid res_tzsh's user data");
+        return;
+     }
+
+   cp = _e_policy_wl_e_pixmap_get_from_id(client, surf_id);
+   if (!cp)
+     {
+        wl_resource_post_error
+          (res_tzsh,
+           WL_DISPLAY_ERROR_INVALID_OBJECT,
+           "Invalid surface id");
+        return;
+     }
+
+   ec = e_pixmap_client_get(cp);
+   if (ec)
+     {
+        if (!_e_policy_wl_e_client_is_valid(ec))
+          {
+             wl_resource_post_error
+               (res_tzsh,
+                WL_DISPLAY_ERROR_INVALID_OBJECT,
+                "Invalid surface id");
+             return;
+          }
+     }
+
+   res_tzsh_qp = wl_resource_create(client,
+                                    &tws_quickpanel_interface,
+                                    wl_resource_get_version(res_tzsh),
+                                    id);
+   if (!res_tzsh_qp)
+     {
+        ERR("Could not create tws_quickpanel resource: %m");
+        wl_client_post_no_memory(client);
+        return;
+     }
+
+   _e_policy_wl_tzsh_data_set(tzsh, TZSH_TYPE_CLIENT, cp, ec);
+
+   tzsh_client = _e_policy_wl_tzsh_client_add(tzsh, res_tzsh_qp);
+   if (!tzsh_client)
+     {
+        ERR("Could not create tzsh_client");
+        wl_client_post_no_memory(client);
+        return;
+     }
+
+   tzsh_client->qp_client = EINA_TRUE;
+   e_qp_client_add(tzsh->ec);
+
+   wl_resource_set_implementation(res_tzsh_qp,
+                                  &_tzsh_qp_iface,
+                                  tzsh_client,
+                                  _tzsh_cb_qp_destroy);
+}
+
+// --------------------------------------------------------
+// tizen_ws_shell_interface::tvservice
+// --------------------------------------------------------
+static void
+_tzsh_tvsrv_iface_cb_release(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzsh_tvsrv)
+{
+   wl_resource_destroy(res_tzsh_tvsrv);
+}
+
+static void
+_tzsh_tvsrv_iface_cb_bind(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzsh_tvsrv)
+{
+   E_Policy_Wl_Tzsh_Client *tzsh_client;
+
+   tzsh_client = wl_resource_get_user_data(res_tzsh_tvsrv);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_client);
+
+   if (!eina_list_data_find(polwl->tzsh_clients, tzsh_client))
+     return;
+
+   polwl->tvsrv_bind_list = eina_list_append(polwl->tvsrv_bind_list, tzsh_client);
+
+   _e_policy_wl_tzsh_srv_tvsrv_bind_update();
+}
+
+static void
+_tzsh_tvsrv_iface_cb_unbind(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzsh_tvsrv)
+{
+   E_Policy_Wl_Tzsh_Client *tzsh_client;
+
+   tzsh_client = wl_resource_get_user_data(res_tzsh_tvsrv);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_client);
+
+   if (!eina_list_data_find(polwl->tzsh_clients, tzsh_client))
+     return;
+
+   polwl->tvsrv_bind_list = eina_list_remove(polwl->tvsrv_bind_list, tzsh_client);
+
+   _e_policy_wl_tzsh_srv_tvsrv_bind_update();
+}
+
+static const struct tws_tvsrv_interface _tzsh_tvsrv_iface =
+{
+   _tzsh_tvsrv_iface_cb_release,
+   _tzsh_tvsrv_iface_cb_bind,
+   _tzsh_tvsrv_iface_cb_unbind
+};
+
+static void
+_tzsh_cb_tvsrv_destroy(struct wl_resource *res_tzsh_tvsrv)
+{
+   E_Policy_Wl_Tzsh_Client *tzsh_client;
+
+   tzsh_client = wl_resource_get_user_data(res_tzsh_tvsrv);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_client);
+
+   if (!eina_list_data_find(polwl->tzsh_clients, tzsh_client))
+     return;
+
+   polwl->tvsrv_bind_list = eina_list_remove(polwl->tvsrv_bind_list, tzsh_client);
+
+   _e_policy_wl_tzsh_srv_tvsrv_bind_update();
+   _e_policy_wl_tzsh_client_del(tzsh_client);
+}
+
+static void
+_tzsh_iface_cb_tvsrv_get(struct wl_client *client, struct wl_resource *res_tzsh, uint32_t id, uint32_t surf_id)
+{
+   E_Policy_Wl_Tzsh *tzsh;
+   E_Policy_Wl_Tzsh_Client *tzsh_client;
+   struct wl_resource *res_tzsh_tvsrv;
+   E_Pixmap *cp;
+   E_Client *ec;
+
+   tzsh = wl_resource_get_user_data(res_tzsh);
+   if (!tzsh)
+     {
+        wl_resource_post_error
+          (res_tzsh,
+           WL_DISPLAY_ERROR_INVALID_OBJECT,
+           "Invalid res_tzsh's user data");
+        return;
+     }
+
+   cp = _e_policy_wl_e_pixmap_get_from_id(client, surf_id);
+   if (!cp)
+     {
+        wl_resource_post_error
+          (res_tzsh,
+           WL_DISPLAY_ERROR_INVALID_OBJECT,
+           "Invalid surface id");
+        return;
+     }
+
+   ec = e_pixmap_client_get(cp);
+   if (ec)
+     {
+        if (!_e_policy_wl_e_client_is_valid(ec))
+          {
+             wl_resource_post_error
+               (res_tzsh,
+                WL_DISPLAY_ERROR_INVALID_OBJECT,
+                "Invalid surface id");
+             return;
+          }
+     }
+
+   res_tzsh_tvsrv = wl_resource_create(client,
+                                       &tws_tvsrv_interface,
+                                       wl_resource_get_version(res_tzsh),
+                                       id);
+   if (!res_tzsh_tvsrv)
+     {
+        ERR("Could not create tws_tvsrv resource: %m");
+        wl_client_post_no_memory(client);
+        return;
+     }
+
+   _e_policy_wl_tzsh_data_set(tzsh, TZSH_TYPE_CLIENT, cp, ec);
+
+   tzsh_client = _e_policy_wl_tzsh_client_add(tzsh, res_tzsh_tvsrv);
+   if (!tzsh_client)
+     {
+        ERR("Could not create tzsh_client");
+        wl_client_post_no_memory(client);
+        wl_resource_destroy(res_tzsh_tvsrv);
+        return;
+     }
+
+   wl_resource_set_implementation(res_tzsh_tvsrv,
+                                  &_tzsh_tvsrv_iface,
+                                  tzsh_client,
+                                  _tzsh_cb_tvsrv_destroy);
+}
+
+// --------------------------------------------------------
+// tizen_ws_shell_interface
+// --------------------------------------------------------
+static void
+_tzsh_iface_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzsh)
+{
+   wl_resource_destroy(res_tzsh);
+}
+
+static const struct tizen_ws_shell_interface _tzsh_iface =
+{
+   _tzsh_iface_cb_destroy,
+   _tzsh_iface_cb_srv_create,
+   _tzsh_iface_cb_reg_create,
+   _tzsh_iface_cb_qp_get,
+   _tzsh_iface_cb_tvsrv_get
+};
+
+static void
+_tzsh_cb_unbind(struct wl_resource *res_tzsh)
+{
+   E_Policy_Wl_Tzsh *tzsh;
+
+   tzsh = wl_resource_get_user_data(res_tzsh);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh);
+
+   _e_policy_wl_tzsh_del(tzsh);
+}
+
+static void
+_tzsh_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t ver, uint32_t id)
+{
+   E_Policy_Wl_Tzsh *tzsh;
+   struct wl_resource *res_tzsh;
+
+   EINA_SAFETY_ON_NULL_GOTO(polwl, err);
+
+   res_tzsh = wl_resource_create(client,
+                                 &tizen_ws_shell_interface,
+                                 ver,
+                                 id);
+   EINA_SAFETY_ON_NULL_GOTO(res_tzsh, err);
+
+   tzsh = _e_policy_wl_tzsh_add(res_tzsh);
+   EINA_SAFETY_ON_NULL_GOTO(tzsh, err);
+
+   wl_resource_set_implementation(res_tzsh,
+                                  &_tzsh_iface,
+                                  tzsh,
+                                  _tzsh_cb_unbind);
+
+   _e_policy_wl_tzsh_registered_srv_send(tzsh);
+   return;
+
+err:
+   ERR("Could not create tizen_ws_shell_interface res: %m");
+   wl_client_post_no_memory(client);
+}
+
+// --------------------------------------------------------
+// tizen_launchscreen_interface
+// --------------------------------------------------------
+static void
+_launchscreen_hide(uint32_t pid)
+{
+   Eina_List *l, *ll;
+   E_Policy_Wl_Tzlaunch *plauncher;
+   E_Policy_Wl_Tzlaunch_Img *pimg;
+
+   if(pid <= 0) return;
+
+   EINA_LIST_FOREACH(polwl->tzlaunchs, l, plauncher)
+     {
+        EINA_LIST_FOREACH(plauncher->imglist, ll, pimg)
+           if (pimg->pid == pid)
+             {
+                DBG("Launch Screen hide | pid %d", pid);
+                _launch_img_off(pimg);
+             }
+     }
+
+   return;
+}
+
+static void
+_launch_img_cb_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
+{
+   E_Policy_Wl_Tzlaunch_Img *tzlaunchimg = data;
+
+   if ((tzlaunchimg) && (tzlaunchimg->obj == obj))
+     tzlaunchimg->obj = NULL;
+}
+
+static void
+_launch_img_off(E_Policy_Wl_Tzlaunch_Img *tzlaunchimg)
+{
+   E_Client *ec = NULL;
+
+   if (!tzlaunchimg->valid) return;
+   if (!tzlaunchimg->ec) return;
+
+   ec = tzlaunchimg->ec;
+
+   if ((ec->pixmap) &&
+       (ec->pixmap == tzlaunchimg->ep))
+     {
+        if (ec->visible)
+          {
+             ec->visible = EINA_FALSE;
+             evas_object_hide(ec->frame);
+             ec->ignored = EINA_TRUE;
+          }
+
+        e_comp->launchscrns = eina_list_remove(e_comp->launchscrns, ec);
+
+        e_pixmap_del(tzlaunchimg->ep);
+        e_object_del(E_OBJECT(ec));
+     }
+
+   tzlaunchimg->ep = NULL;
+   tzlaunchimg->ec = NULL;
+   if (tzlaunchimg->timeout) ecore_timer_del(tzlaunchimg->timeout);
+   tzlaunchimg->timeout = NULL;
+   tzlaunchimg->valid = EINA_FALSE;
+}
+
+static Eina_Bool
+_launch_timeout(void *data)
+{
+   E_Policy_Wl_Tzlaunch_Img *tzlaunchimg;
+   tzlaunchimg = (E_Policy_Wl_Tzlaunch_Img *)data;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(tzlaunchimg, 0);
+
+   _launch_img_off(tzlaunchimg);
+
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_tzlaunchimg_iface_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzlaunchimg)
+{
+   wl_resource_destroy(res_tzlaunchimg);
+}
+
+static void
+_tzlaunchimg_iface_cb_launch(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzlaunchimg,
+                             const char *pfname, uint32_t ftype,
+                             uint32_t depth, uint32_t angle,
+                             uint32_t indicator, struct wl_array *options)
+{
+   E_Policy_Wl_Tzlaunch_Img *tzlaunchimg;
+   Evas_Load_Error err;
+   E_Client *ec = NULL;
+   E_Comp_Object_Content_Type content_type = 0;
+
+   tzlaunchimg = wl_resource_get_user_data(res_tzlaunchimg);
+   EINA_SAFETY_ON_NULL_RETURN(tzlaunchimg);
+   EINA_SAFETY_ON_NULL_RETURN(tzlaunchimg->ec);
+   EINA_SAFETY_ON_NULL_RETURN(tzlaunchimg->ec->frame);
+
+   ec = tzlaunchimg->ec;
+
+   // TO DO
+   // invaid parameter handle
+   DBG("%s | path %s(%d), indicator(%d), angle(%d)", __FUNCTION__, pfname, ftype, indicator, angle);
+   tzlaunchimg->path = pfname;
+   tzlaunchimg->type = ftype;
+   tzlaunchimg->indicator = indicator;
+   tzlaunchimg->angle = angle;
+
+   if (tzlaunchimg->type == E_LAUNCH_FILE_TYPE_IMAGE)
+     {
+        content_type = E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE;
+        tzlaunchimg->obj = evas_object_image_add(e_comp->evas);
+        EINA_SAFETY_ON_NULL_GOTO(tzlaunchimg->obj, error);
+        evas_object_image_file_set(tzlaunchimg->obj, tzlaunchimg->path, NULL);
+
+        err = evas_object_image_load_error_get(tzlaunchimg->obj);
+        EINA_SAFETY_ON_FALSE_GOTO(err == EVAS_LOAD_ERROR_NONE, error);
+
+        evas_object_image_fill_set(tzlaunchimg->obj, 0, 0,  e_comp->w, e_comp->h);
+        evas_object_image_filled_set(tzlaunchimg->obj, EINA_TRUE);
+     }
+   else
+     {
+        content_type = E_COMP_OBJECT_CONTENT_TYPE_EXT_EDJE;
+        tzlaunchimg->obj = edje_object_add(e_comp->evas);
+        EINA_SAFETY_ON_NULL_GOTO(tzlaunchimg->obj, error);
+        edje_object_file_set (tzlaunchimg->obj, tzlaunchimg->path, APP_DEFINE_GROUP_NAME);
+
+        evas_object_move(tzlaunchimg->obj, 0, 0);
+        evas_object_resize(tzlaunchimg->obj, e_comp->w, e_comp->h);
+     }
+
+   if (depth == 32) ec->argb = EINA_TRUE;
+   else ec->argb = EINA_FALSE;
+
+   if (!e_comp_object_content_set(ec->frame, tzlaunchimg->obj, content_type))
+     {
+        ERR("Setting comp object content for %p failed!", ec);
+        goto error;
+     }
+
+   evas_object_event_callback_add(tzlaunchimg->obj,
+                                  EVAS_CALLBACK_DEL,
+                                  _launch_img_cb_del, tzlaunchimg);
+
+   tzlaunchimg->valid = EINA_TRUE;
+
+   ec->ignored = EINA_FALSE;
+   ec->visible = EINA_TRUE;
+   ec->new_client = EINA_FALSE;
+   ec->icccm.accepts_focus = EINA_TRUE;
+
+   evas_object_show(ec->frame);
+   evas_object_raise(ec->frame);
+   EC_CHANGED(ec);
+
+   e_client_visibility_calculate();
+
+   if (tzlaunchimg->timeout)
+     ecore_timer_del(tzlaunchimg->timeout);
+   tzlaunchimg->timeout = ecore_timer_add(4.0f, _launch_timeout, tzlaunchimg);
+
+   return;
+error:
+   ERR("Could not complete %s", __FUNCTION__);
+   if (tzlaunchimg->obj)
+     evas_object_del(tzlaunchimg->obj);
+}
+
+static void
+_tzlaunchimg_iface_cb_show(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzlaunchimg)
+{
+   /* TODO: request launch img show */
+
+}
+
+static void
+_tzlaunchimg_iface_cb_hide(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzlaunchimg)
+{
+   /* TODO: request launch img hide */
+}
+
+static void
+_tzlaunchimg_iface_cb_owner(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzlaunchimg, uint32_t pid)
+{
+   E_Policy_Wl_Tzlaunch_Img *tzlaunchimg;
+
+   DBG("Launch img(%d) pid: %d", wl_resource_get_id(res_tzlaunchimg), pid);
+
+   tzlaunchimg = wl_resource_get_user_data(res_tzlaunchimg);
+   EINA_SAFETY_ON_NULL_RETURN(tzlaunchimg);
+
+   tzlaunchimg->pid = pid;
+   tzlaunchimg->ec->netwm.pid = pid;
+}
+
+
+static const struct tizen_launch_image_interface _tzlaunchimg_iface =
+{
+   _tzlaunchimg_iface_cb_destroy,
+   _tzlaunchimg_iface_cb_launch,
+   _tzlaunchimg_iface_cb_owner,
+   _tzlaunchimg_iface_cb_show,
+   _tzlaunchimg_iface_cb_hide
+};
+
+static E_Policy_Wl_Tzlaunch_Img *
+_tzlaunch_img_add(struct wl_resource *res_tzlaunch, struct wl_resource *res_tzlaunch_img)
+{
+   E_Policy_Wl_Tzlaunch *tzlaunch;
+   E_Policy_Wl_Tzlaunch_Img *tzlaunchimg;
+
+   tzlaunchimg = E_NEW(E_Policy_Wl_Tzlaunch_Img, 1);
+   EINA_SAFETY_ON_NULL_GOTO(tzlaunchimg, error);
+
+   tzlaunch = wl_resource_get_user_data(res_tzlaunch);
+   EINA_SAFETY_ON_NULL_GOTO(tzlaunch, error);
+
+   tzlaunch->imglist = eina_list_append(tzlaunch->imglist, tzlaunchimg);
+
+   tzlaunchimg->tzlaunch  = tzlaunch;
+   tzlaunchimg->res_tzlaunch_img = res_tzlaunch_img;
+
+   tzlaunchimg->ep = e_pixmap_new(E_PIXMAP_TYPE_EXT_OBJECT, 0);
+   EINA_SAFETY_ON_NULL_GOTO(tzlaunchimg->ep, error);
+   tzlaunchimg->ec = e_client_new(tzlaunchimg->ep, 0, 1);
+   EINA_SAFETY_ON_NULL_GOTO(tzlaunchimg->ec, error);
+
+   tzlaunchimg->ec->icccm.title = eina_stringshare_add("Launchscreen");
+   tzlaunchimg->ec->icccm.name = eina_stringshare_add("Launchscreen");
+   tzlaunchimg->ec->ignored = EINA_TRUE;
+
+   e_comp->launchscrns = eina_list_append(e_comp->launchscrns, tzlaunchimg->ec);
+
+   return tzlaunchimg;
+error:
+   if (tzlaunchimg)
+     {
+        ERR("Could not initialize launchscreen client");
+        if (tzlaunchimg->ep)
+          e_pixmap_del(tzlaunchimg->ep);
+        if (tzlaunchimg->ec)
+          e_object_del(E_OBJECT(tzlaunchimg->ec));
+        E_FREE(tzlaunchimg);
+     }
+   return NULL;
+}
+
+static void
+_tzlaunch_img_destroy(struct wl_resource *res_tzlaunchimg)
+{
+   E_Policy_Wl_Tzlaunch_Img *tzlaunchimg;
+   E_Policy_Wl_Tzlaunch *tzlaunch;
+
+   EINA_SAFETY_ON_NULL_RETURN(res_tzlaunchimg);
+
+   tzlaunchimg = wl_resource_get_user_data(res_tzlaunchimg);
+   EINA_SAFETY_ON_NULL_RETURN(tzlaunchimg);
+
+   if (tzlaunchimg->obj)
+     evas_object_event_callback_del_full(tzlaunchimg->obj, EVAS_CALLBACK_DEL, _launch_img_cb_del, tzlaunchimg);
+
+   _launch_img_off(tzlaunchimg);
+
+   tzlaunch = tzlaunchimg->tzlaunch;
+   tzlaunch->imglist = eina_list_remove(tzlaunch->imglist, tzlaunchimg);
+
+   memset(tzlaunchimg, 0x0, sizeof(E_Policy_Wl_Tzlaunch_Img));
+   E_FREE(tzlaunchimg);
+}
+
+
+static void
+_tzlaunch_iface_cb_create_img(struct wl_client *client, struct wl_resource *res_tzlaunch, uint32_t id)
+{
+
+   E_Policy_Wl_Tzlaunch_Img *plaunchimg;
+   struct wl_resource *res_tzlaunch_img;
+
+   res_tzlaunch_img = wl_resource_create(client,
+                                         &tizen_launch_image_interface,
+                                         wl_resource_get_version(res_tzlaunch),
+                                         id);
+   if (!res_tzlaunch_img)
+     {
+        wl_resource_post_error
+           (res_tzlaunch,
+            WL_DISPLAY_ERROR_INVALID_OBJECT,
+            "Invalid res_tzlaunch's user data");
+        return;
+     }
+
+   plaunchimg = _tzlaunch_img_add(res_tzlaunch, res_tzlaunch_img);
+   EINA_SAFETY_ON_NULL_GOTO(plaunchimg, err);
+
+   wl_resource_set_implementation(res_tzlaunch_img,
+                                  &_tzlaunchimg_iface,
+                                  plaunchimg,
+                                  _tzlaunch_img_destroy);
+
+   return;
+
+err:
+   ERR("Could not create tizen_launch_image_interface res: %m");
+   wl_client_post_no_memory(client);
+}
+
+
+static const struct tizen_launchscreen_interface _tzlaunch_iface =
+{
+   _tzlaunch_iface_cb_create_img
+};
+
+static void
+_tzlaunch_del(E_Policy_Wl_Tzlaunch *tzlaunch)
+{
+   E_Policy_Wl_Tzlaunch_Img *plaunchimg;
+   Eina_List *l, *ll;
+
+   EINA_SAFETY_ON_NULL_RETURN(tzlaunch);
+
+   // remove tzlaunch created imglist
+   EINA_LIST_FOREACH_SAFE(tzlaunch->imglist, l, ll, plaunchimg)
+     {
+        if (plaunchimg->tzlaunch != tzlaunch) continue;
+        wl_resource_destroy(plaunchimg->res_tzlaunch_img);
+        break;
+     }
+
+   polwl->tzlaunchs = eina_list_remove(polwl->tzlaunchs, tzlaunch);
+
+   memset(tzlaunch, 0x0, sizeof(E_Policy_Wl_Tzlaunch));
+   E_FREE(tzlaunch);
+}
+
+static E_Policy_Wl_Tzlaunch *
+_tzlaunch_add(struct wl_resource *res_tzlaunch)
+{
+   E_Policy_Wl_Tzlaunch *tzlaunch;
+
+   tzlaunch = E_NEW(E_Policy_Wl_Tzlaunch, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(tzlaunch, NULL);
+
+   tzlaunch->res_tzlaunch = res_tzlaunch;
+
+   polwl->tzlaunchs = eina_list_append(polwl->tzlaunchs, tzlaunch);
+
+   return tzlaunch;
+}
+
+static void
+_tzlaunch_cb_unbind(struct wl_resource *res_tzlaunch)
+{
+   E_Policy_Wl_Tzlaunch *tzlaunch = NULL;
+   Eina_List *l, *ll;
+
+   EINA_LIST_FOREACH_SAFE(polwl->tzlaunchs, l, ll, tzlaunch)
+     {
+        if (tzlaunch->res_tzlaunch != res_tzlaunch) continue;
+        _tzlaunch_del(tzlaunch);
+        break;
+     }
+}
+
+static void
+_tzlaunch_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t ver, uint32_t id)
+{
+   E_Policy_Wl_Tzlaunch *tzlaunch = NULL;
+   struct wl_resource *res_tzlaunch;
+
+   EINA_SAFETY_ON_NULL_GOTO(polwl, err);
+
+   res_tzlaunch = wl_resource_create(client,
+                                     &tizen_launchscreen_interface,
+                                     ver,
+                                     id);
+   EINA_SAFETY_ON_NULL_GOTO(res_tzlaunch, err);
+
+   tzlaunch = _tzlaunch_add(res_tzlaunch);
+   EINA_SAFETY_ON_NULL_GOTO(tzlaunch, err);
+
+   wl_resource_set_implementation(res_tzlaunch,
+                                  &_tzlaunch_iface,
+                                  tzlaunch,
+                                  _tzlaunch_cb_unbind);
+
+   return;
+
+err:
+   ERR("Could not create tizen_launchscreen_interface res: %m");
+   wl_client_post_no_memory(client);
+}
+
+static Eina_Bool
+_e_policy_wl_cb_scrsaver_on(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
+{
+   if (_scrsaver_mng_res)
+     tws_service_screensaver_manager_send_idle(_scrsaver_mng_res);
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_policy_wl_cb_scrsaver_off(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
+{
+   if (_scrsaver_mng_res)
+     tws_service_screensaver_manager_send_active(_scrsaver_mng_res);
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static void
+_e_policy_wl_cb_hook_shell_surface_ready(void *d, E_Client *ec)
+{
+   Eina_Bool res;
+
+   if (EINA_UNLIKELY(!ec))
+     return;
+
+   _e_policy_wl_aux_hint_apply(ec);
+
+   res = e_policy_client_maximize(ec);
+   if (res)
+     {
+        if ((ec->comp_data->shell.configure_send) &&
+            (ec->comp_data->shell.surface))
+          {
+             ec->comp_data->shell.configure_send(ec->comp_data->shell.surface,
+                                                 0, ec->w, ec->h);
+          }
+     }
+}
+
+// --------------------------------------------------------
+// public functions
+// --------------------------------------------------------
+void
+e_policy_wl_client_add(E_Client *ec)
+{
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+   if (!ec->pixmap) return;
+
+   _e_policy_wl_surf_client_set(ec);
+   _e_policy_wl_tzsh_client_set(ec);
+   _e_policy_wl_pending_bg_client_set(ec);
+}
+
+void
+e_policy_wl_client_del(E_Client *ec)
+{
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+   if (!ec->pixmap) return;
+
+   e_policy_wl_pixmap_del(ec->pixmap);
+   _e_policy_wl_tzsh_client_unset(ec);
+   _e_policy_wl_dpy_surf_del(ec);
+
+   polwl->pending_vis = eina_list_remove(polwl->pending_vis, ec);
+}
+
+void
+e_policy_wl_pixmap_del(E_Pixmap *cp)
+{
+   E_Policy_Wl_Tzpol *tzpol;
+   E_Policy_Wl_Surface *psurf;
+   Eina_List *l, *ll;
+   Eina_Iterator *it;
+
+   it = eina_hash_iterator_data_new(polwl->tzpols);
+   EINA_ITERATOR_FOREACH(it, tzpol)
+     EINA_LIST_FOREACH_SAFE(tzpol->psurfs, l, ll, psurf)
+       {
+          if (psurf->cp != cp) continue;
+          tzpol->psurfs = eina_list_remove_list(tzpol->psurfs, l);
+          _e_policy_wl_surf_del(psurf);
+       }
+   eina_iterator_free(it);
+}
+
+void
+e_policy_wl_aux_hint_init(void)
+{
+   int i, n;
+   n = (sizeof(hint_names) / sizeof(char *));
+
+   for (i = 0; i < n; i++)
+     {
+        e_hints_aux_hint_supported_add(hint_names[i]);
+     }
+   return;
+}
+
+Eina_Bool
+e_policy_wl_defer_job(void)
+{
+   struct wl_global *global = NULL;
+   EINA_SAFETY_ON_NULL_GOTO(polwl, err);
+
+   global = wl_global_create(e_comp_wl->wl.disp,
+                             &tizen_launchscreen_interface,
+                             1,
+                             NULL,
+                             _tzlaunch_cb_bind);
+   EINA_SAFETY_ON_NULL_GOTO(global, err);
+
+   polwl->globals = eina_list_append(polwl->globals, global);
+
+   return EINA_TRUE;
+
+err:
+   return EINA_FALSE;
+}
+
+#undef E_COMP_WL_HOOK_APPEND
+#define E_COMP_WL_HOOK_APPEND(l, t, cb, d) \
+  do                                      \
+    {                                     \
+       E_Comp_Wl_Hook *_h;                 \
+       _h = e_comp_wl_hook_add(t, cb, d);  \
+       assert(_h);                        \
+       l = eina_list_append(l, _h);       \
+    }                                     \
+  while (0)
+
+Eina_Bool
+e_policy_wl_init(void)
+{
+   struct wl_global *global;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl->wl.disp, EINA_FALSE);
+
+   polwl = E_NEW(E_Policy_Wl, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(polwl, EINA_FALSE);
+
+   /* create globals */
+   global = wl_global_create(e_comp_wl->wl.disp,
+                             &tizen_policy_interface,
+                             1,
+                             NULL,
+                             _tzpol_cb_bind);
+   EINA_SAFETY_ON_NULL_GOTO(global, err);
+   polwl->globals = eina_list_append(polwl->globals, global);
+
+   global = wl_global_create(e_comp_wl->wl.disp,
+                             &tizen_display_policy_interface,
+                             1,
+                             NULL,
+                             _tz_dpy_pol_cb_bind);
+   EINA_SAFETY_ON_NULL_GOTO(global, err);
+   polwl->globals = eina_list_append(polwl->globals, global);
+
+   global = wl_global_create(e_comp_wl->wl.disp,
+                             &tizen_ws_shell_interface,
+                             1,
+                             NULL,
+                             _tzsh_cb_bind);
+   EINA_SAFETY_ON_NULL_GOTO(global, err);
+   polwl->globals = eina_list_append(polwl->globals, global);
+
+   polwl->tzpols = eina_hash_pointer_new(_e_policy_wl_tzpol_del);
+
+#ifdef HAVE_CYNARA
+   if (cynara_initialize(&polwl->p_cynara, NULL) != CYNARA_API_SUCCESS)
+     ERR("cynara_initialize failed.");
+#endif
+
+   E_LIST_HANDLER_APPEND(handlers, E_EVENT_SCREENSAVER_ON,  _e_policy_wl_cb_scrsaver_on,  NULL);
+   E_LIST_HANDLER_APPEND(handlers, E_EVENT_SCREENSAVER_OFF, _e_policy_wl_cb_scrsaver_off, NULL);
+
+   E_COMP_WL_HOOK_APPEND(hooks_cw, E_COMP_WL_HOOK_SHELL_SURFACE_READY, _e_policy_wl_cb_hook_shell_surface_ready, NULL);
+
+   e_policy_display_init();
+
+   return EINA_TRUE;
+
+err:
+   if (polwl)
+     {
+        EINA_LIST_FREE(polwl->globals, global)
+          wl_global_destroy(global);
+
+        E_FREE(polwl);
+     }
+   return EINA_FALSE;
+}
+
+void
+e_policy_wl_shutdown(void)
+{
+   E_Policy_Wl_Tzsh *tzsh;
+   E_Policy_Wl_Tzsh_Srv *tzsh_srv;
+   E_Policy_Wl_Tzlaunch *tzlaunch;
+   E_Policy_Wl_Tz_Dpy_Pol *tz_dpy_pol;
+   struct wl_global *global;
+   int i;
+
+   e_policy_display_shutdown();
+
+   EINA_SAFETY_ON_NULL_RETURN(polwl);
+
+   E_FREE_LIST(hooks_cw, e_comp_wl_hook_del);
+   E_FREE_LIST(handlers, ecore_event_handler_del);
+
+   polwl->pending_vis = eina_list_free(polwl->pending_vis);
+
+   for (i = 0; i < TZSH_SRV_ROLE_MAX; i++)
+     {
+        tzsh_srv = polwl->srvs[i];
+        if (!tzsh_srv) continue;
+
+        wl_resource_destroy(tzsh_srv->res_tzsh_srv);
+     }
+
+   EINA_LIST_FREE(polwl->tzshs, tzsh)
+     wl_resource_destroy(tzsh->res_tzsh);
+
+   EINA_LIST_FREE(polwl->tz_dpy_pols, tz_dpy_pol)
+     {
+        E_Policy_Wl_Dpy_Surface *dpy_surf;
+        EINA_LIST_FREE(tz_dpy_pol->dpy_surfs, dpy_surf)
+          {
+             E_FREE(dpy_surf);
+          }
+        wl_resource_destroy(tz_dpy_pol->res_tz_dpy_pol);
+        E_FREE(tz_dpy_pol);
+     }
+
+   EINA_LIST_FREE(polwl->tzlaunchs, tzlaunch)
+     wl_resource_destroy(tzlaunch->res_tzlaunch);
+
+   EINA_LIST_FREE(polwl->globals, global)
+     wl_global_destroy(global);
+
+   E_FREE_FUNC(polwl->tzpols, eina_hash_free);
+
+#ifdef HAVE_CYNARA
+   if (polwl->p_cynara)
+     cynara_finish(polwl->p_cynara);
+#endif
+
+   E_FREE(polwl);
+}
diff --git a/src/bin/e_policy_wl.h b/src/bin/e_policy_wl.h
new file mode 100644 (file)
index 0000000..e1aa290
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef E_MOD_WL_H
+#define E_MOD_WL_H
+
+#include "config.h"
+#ifdef HAVE_WAYLAND_ONLY
+#include <e.h>
+
+Eina_Bool e_policy_wl_init(void);
+void      e_policy_wl_shutdown(void);
+Eina_Bool e_policy_wl_defer_job(void);
+void      e_policy_wl_client_add(E_Client *ec);
+void      e_policy_wl_client_del(E_Client *ec);
+void      e_policy_wl_pixmap_del(E_Pixmap *cp);
+
+/* visibility */
+void      e_policy_wl_visibility_send(E_Client *ec, int vis);
+
+/* iconify */
+void      e_policy_wl_iconify_state_change_send(E_Client *ec, int iconic);
+
+/* position */
+void      e_policy_wl_position_send(E_Client *ec);
+
+/* notification */
+void      e_policy_wl_notification_level_fetch(E_Client *ec);
+
+/* window screenmode */
+void      e_policy_wl_win_scrmode_apply(void);
+
+/* aux_hint */
+void      e_policy_wl_aux_hint_init(void);
+void      e_policy_wl_eval_pre_post_fetch(E_Client *ec);
+
+/* window brightness */
+Eina_Bool e_policy_wl_win_brightness_apply(E_Client *ec);
+
+/* tzsh quickpanel */
+EINTERN void e_tzsh_qp_state_visible_update(E_Client *ec, Eina_Bool vis);
+EINTERN void e_tzsh_qp_state_orientation_update(E_Client *ec, int ridx);
+EINTERN void e_tzsh_qp_state_scrollable_update(E_Client *ec, Eina_Bool scrollable);
+
+#endif /* HAVE_WAYLAND_ONLY */
+#endif /* E_MOD_WL_H */
diff --git a/src/bin/e_policy_wl_display.c b/src/bin/e_policy_wl_display.c
new file mode 100644 (file)
index 0000000..d843496
--- /dev/null
@@ -0,0 +1,288 @@
+#include "e_policy_wl_display.h"
+
+typedef struct _E_Display_Dbus_Info
+{
+   Eldbus_Connection *conn;
+} E_Display_Dbus_Info;
+
+#define BUS_NAME "org.enlightenment.wm"
+
+#define DEVICED_DEST "org.tizen.system.deviced"
+#define DEVICED_PATH "/Org/Tizen/System/DeviceD/Display"
+#define DEVICED_IFACE "org.tizen.system.deviced.display"
+#define DEVICED_LOCK_STATE "lockstate"
+#define DEVICED_UNLOCK_STATE "unlockstate"
+
+#define DEVICED_LCDON "lcdon"
+#define DEVICED_STAY_CUR_STATE "staycurstate"
+#define DEVICED_SLEEP_MARGIN "sleepmargin"
+
+/* static global variables */
+static E_Display_Dbus_Info _e_display_dbus_info;
+static Eina_List *_display_control_hooks = NULL;
+
+/* for screen mode */
+static Eina_List *_screen_mode_client_list = NULL;
+static E_Display_Screen_Mode _e_display_screen_mode;
+
+/* static functions */
+static Eina_Bool _e_policy_display_dbus_init(void);
+static void      _e_policy_display_dbus_shutdown(void);
+static void      _e_policy_display_dbus_request_name_cb(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED);
+
+static Eina_Bool _e_policy_wl_display_client_add_to_list(Eina_List** list, E_Client *ec);
+static Eina_Bool _e_policy_wl_display_client_remove_from_list(Eina_List** list, E_Client *ec);
+
+static void _e_policy_wl_display_hook_client_del(void *d EINA_UNUSED, E_Client *ec);
+static void _e_policy_wl_display_hook_client_visibility(void *d EINA_UNUSED, E_Client *ec);
+
+/* for screen mode */
+static Eina_Bool _e_policy_wl_display_screen_mode_find_visible_window(void);
+static void      _e_policy_wl_display_screen_mode_send(E_Display_Screen_Mode mode);
+
+
+static Eina_Bool
+_e_policy_display_dbus_init(void)
+{
+   if (eldbus_init() == 0) return EINA_FALSE;
+
+   _e_display_dbus_info.conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM);
+   EINA_SAFETY_ON_NULL_GOTO(_e_display_dbus_info.conn, failed);
+
+   eldbus_name_request(_e_display_dbus_info.conn,
+                       BUS_NAME,
+                       ELDBUS_NAME_REQUEST_FLAG_DO_NOT_QUEUE,
+                       _e_policy_display_dbus_request_name_cb,
+                       NULL);
+
+   return EINA_TRUE;
+
+failed:
+   _e_policy_display_dbus_shutdown();
+   return EINA_FALSE;
+}
+
+static void
+_e_policy_display_dbus_shutdown(void)
+{
+   if (_e_display_dbus_info.conn)
+     {
+        eldbus_name_release(_e_display_dbus_info.conn, BUS_NAME, NULL, NULL);
+        eldbus_connection_unref(_e_display_dbus_info.conn);
+        _e_display_dbus_info.conn = NULL;
+     }
+
+   eldbus_shutdown();
+}
+
+static void
+_e_policy_display_dbus_request_name_cb(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
+{
+   unsigned int flag;
+
+   if (eldbus_message_error_get(msg, NULL, NULL))
+     {
+        ERR("Could not request bus name");
+        return;
+     }
+
+   if (!eldbus_message_arguments_get(msg, "u", &flag))
+     {
+        ERR("Could not get arguments on on_name_request");
+        return;
+     }
+
+   if (!(flag & ELDBUS_NAME_REQUEST_REPLY_PRIMARY_OWNER))
+     {
+        WRN("Name already in use\n");
+     }
+}
+
+static Eina_Bool
+_e_policy_wl_display_client_add_to_list(Eina_List** list, E_Client *ec)
+{
+   if (!ec) return EINA_FALSE;
+
+   if (eina_list_data_find(*list, ec) == ec)
+     return EINA_TRUE;
+
+   *list = eina_list_append(*list, ec);
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_policy_wl_display_client_remove_from_list(Eina_List** list, E_Client *ec)
+{
+   if (!ec) return EINA_FALSE;
+
+   if (!eina_list_data_find(*list, ec))
+     return EINA_FALSE;
+
+   *list = eina_list_remove(*list, ec);
+
+   return EINA_TRUE;
+}
+
+static void
+_e_policy_wl_display_hook_client_del(void *d EINA_UNUSED, E_Client *ec)
+{
+   _e_policy_wl_display_client_remove_from_list(&_screen_mode_client_list, ec);
+}
+
+static void
+_e_policy_wl_display_hook_client_visibility(void *d EINA_UNUSED, E_Client *ec)
+{
+   if (ec->visibility.changed)
+     {
+        e_policy_display_screen_mode_apply();
+     }
+}
+
+static Eina_Bool
+_e_policy_wl_display_screen_mode_find_visible_window(void)
+{
+   Eina_List *l = NULL;
+   E_Client *ec = NULL;
+   Eina_Bool find = EINA_FALSE;
+   int ec_visibility;
+
+   if (_screen_mode_client_list == NULL) return EINA_FALSE;
+
+   EINA_LIST_FOREACH(_screen_mode_client_list, l, ec)
+     {
+        if (e_object_is_del(E_OBJECT(ec)))
+          ec_visibility = E_VISIBILITY_FULLY_OBSCURED;
+        else
+          ec_visibility = ec->visibility.obscured;
+
+        if ((ec_visibility == E_VISIBILITY_UNOBSCURED) ||
+            (ec_visibility == E_VISIBILITY_PARTIALLY_OBSCURED))
+          {
+             find = EINA_TRUE;
+             break;
+          }
+     }
+
+   return find;
+}
+
+static void
+_e_policy_wl_display_screen_mode_send(E_Display_Screen_Mode mode)
+{
+   Eldbus_Message *msg;
+   Eina_Bool ret;
+   unsigned int timeout = 0;
+
+   if (!_e_display_dbus_info.conn) return;
+
+   if (mode == E_DISPLAY_SCREEN_MODE_ALWAYS_ON)
+     {
+        msg = eldbus_message_method_call_new(DEVICED_DEST,
+                                             DEVICED_PATH,
+                                             DEVICED_IFACE,
+                                             DEVICED_LOCK_STATE);
+        if (!msg) return;
+
+        ret = eldbus_message_arguments_append(msg, "sssi",
+                                              DEVICED_LCDON,
+                                              DEVICED_STAY_CUR_STATE,
+                                              "",
+                                              timeout);
+     }
+   else
+     {
+        msg = eldbus_message_method_call_new(DEVICED_DEST,
+                                             DEVICED_PATH,
+                                             DEVICED_IFACE,
+                                             DEVICED_UNLOCK_STATE);
+        if (!msg) return;
+
+        ret = eldbus_message_arguments_append(msg, "ss",
+                                              DEVICED_LCDON,
+                                              DEVICED_SLEEP_MARGIN);
+     }
+
+   if (!ret)
+     {
+        if (msg)
+          eldbus_message_unref(msg);
+
+        return;
+     }
+
+   _e_display_screen_mode = mode;
+   DBG("[SCREEN_MODE] Request screen mode:%d\n", mode);
+
+   eldbus_connection_send(_e_display_dbus_info.conn, msg, NULL, NULL, -1);
+}
+
+#undef E_CLIENT_HOOK_APPEND
+#define E_CLIENT_HOOK_APPEND(l, t, cb, d) \
+  do                                      \
+    {                                     \
+       E_Client_Hook *_h;                 \
+       _h = e_client_hook_add(t, cb, d);  \
+       assert(_h);                        \
+       l = eina_list_append(l, _h);       \
+    }                                     \
+  while (0)
+
+Eina_Bool
+e_policy_display_init(void)
+{
+   if (!_e_policy_display_dbus_init()) return EINA_FALSE;
+
+   _e_display_screen_mode = E_DISPLAY_SCREEN_MODE_DEFAULT;
+
+   /* hook functions */
+   E_CLIENT_HOOK_APPEND(_display_control_hooks, E_CLIENT_HOOK_DEL, _e_policy_wl_display_hook_client_del, NULL);
+   E_CLIENT_HOOK_APPEND(_display_control_hooks, E_CLIENT_HOOK_EVAL_VISIBILITY, _e_policy_wl_display_hook_client_visibility, NULL);
+
+   return EINA_TRUE;
+}
+
+void
+e_policy_display_shutdown(void)
+{
+   E_FREE_LIST(_display_control_hooks, e_client_hook_del);
+
+   if (_screen_mode_client_list) eina_list_free(_screen_mode_client_list);
+
+   _e_policy_display_dbus_shutdown();
+}
+
+void
+e_policy_display_screen_mode_set(E_Client *ec, int mode)
+{
+   if (!ec) return;
+   if (e_object_is_del(E_OBJECT(ec))) return;
+
+   if (mode == 0)
+     {
+        _e_policy_wl_display_client_remove_from_list(&_screen_mode_client_list, ec);
+        e_policy_display_screen_mode_apply();
+     }
+   else
+     {
+        _e_policy_wl_display_client_add_to_list(&_screen_mode_client_list, ec);
+        e_policy_display_screen_mode_apply();
+     }
+}
+
+void
+e_policy_display_screen_mode_apply(void)
+{
+   /* check the _screen_mode_client_list and update the lcd locked status */
+   if (_e_policy_wl_display_screen_mode_find_visible_window())
+     {
+        if (_e_display_screen_mode == E_DISPLAY_SCREEN_MODE_DEFAULT)
+          _e_policy_wl_display_screen_mode_send(E_DISPLAY_SCREEN_MODE_ALWAYS_ON);
+     }
+   else
+     {
+        if (_e_display_screen_mode == E_DISPLAY_SCREEN_MODE_ALWAYS_ON)
+          _e_policy_wl_display_screen_mode_send(E_DISPLAY_SCREEN_MODE_DEFAULT);
+     }
+}
+
diff --git a/src/bin/e_policy_wl_display.h b/src/bin/e_policy_wl_display.h
new file mode 100644 (file)
index 0000000..db35cad
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef E_POLICY_WL_DISPLAY_H
+#define E_POLICY_WL_DISPLAY_H
+
+#include <e.h>
+
+typedef enum _E_Display_Screen_Mode
+{
+   E_DISPLAY_SCREEN_MODE_DEFAULT = 0,
+   E_DISPLAY_SCREEN_MODE_ALWAYS_ON = 1,
+} E_Display_Screen_Mode;
+
+Eina_Bool e_policy_display_init(void);
+void      e_policy_display_shutdown(void);
+
+void      e_policy_display_screen_mode_set(E_Client *ec, int mode);
+void      e_policy_display_screen_mode_apply(void);
+
+#endif
diff --git a/src/bin/services/e_service_gesture.c b/src/bin/services/e_service_gesture.c
new file mode 100644 (file)
index 0000000..174f307
--- /dev/null
@@ -0,0 +1,217 @@
+#include "e.h"
+#include "services/e_service_gesture.h"
+
+struct _E_Policy_Gesture
+{
+   Evas_Object *obj;
+   E_Policy_Gesture_Type type;
+
+   Eina_Bool active;
+
+   struct
+   {
+      int x;
+      int y;
+      int timestamp;
+      Eina_Bool pressed; /* to avoid processing that happened mouse move right after mouse up */
+   } mouse_info;
+
+   struct
+   {
+      E_Policy_Gesture_Start_Cb start;
+      E_Policy_Gesture_Move_Cb move;
+      E_Policy_Gesture_End_Cb end;
+      void *data;
+   } cb;
+};
+
+static void
+_gesture_obj_cb_mouse_up(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event)
+{
+   E_Policy_Gesture *gesture = data;
+   Evas_Event_Mouse_Up *ev = event;
+
+   gesture->mouse_info.pressed = EINA_FALSE;
+
+   if (!gesture->active)
+     return;
+
+   gesture->active = EINA_FALSE;
+
+   if (gesture->cb.end)
+     gesture->cb.end(gesture->cb.data, obj, ev->canvas.x, ev->canvas.y, ev->timestamp);
+}
+
+static Eina_Bool
+_gesture_line_check(E_Policy_Gesture *gesture, int x, int y)
+{
+   int dx, dy;
+   const int sensitivity = 50; /* FIXME: hard coded, it sould be configurable. */
+
+   dx = x - gesture->mouse_info.x;
+   dy = y - gesture->mouse_info.y;
+   if ((abs(dy) < sensitivity) &&
+       (abs(dx) < sensitivity))
+     return EINA_FALSE;
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_gesture_flick_check(E_Policy_Gesture *gesture, Evas_Object *obj, int x, int y, unsigned int timestamp)
+{
+   int dy;
+   int ox, oy, ow, oh;
+   unsigned int dt;
+   float vel = 0.0;
+   const float sensitivity = 0.25; /* FIXME: hard coded, it sould be configurable. */
+
+   evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
+   if (!E_INSIDE(x, y, ox, oy, ow, oh))
+     return EINA_FALSE;
+
+   dy = y - gesture->mouse_info.y;
+   dt = timestamp - gesture->mouse_info.timestamp;
+   if (dt == 0)
+     return EINA_FALSE;
+
+   vel = (float)dy / (float)dt;
+   if (fabs(vel) < sensitivity)
+     return EINA_FALSE;
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_gesture_check(E_Policy_Gesture *gesture, Evas_Object *obj, int x, int y, unsigned int timestamp)
+{
+   Eina_Bool ret = EINA_FALSE;
+
+   switch (gesture->type)
+     {
+      case POL_GESTURE_TYPE_NONE:
+         ret = EINA_TRUE;
+         break;
+      case POL_GESTURE_TYPE_LINE:
+         ret = _gesture_line_check(gesture, x, y);
+         break;
+      case POL_GESTURE_TYPE_FLICK:
+         ret = _gesture_flick_check(gesture, obj, x, y, timestamp);
+         break;
+      default:
+         ERR("Unknown gesture type %d", gesture->type);
+         break;
+     }
+
+   return ret;
+}
+
+static void
+_gesture_obj_cb_mouse_move(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event)
+{
+   E_Policy_Gesture *gesture = data;
+   Evas_Event_Mouse_Move *ev = event;
+   int x, y;
+   unsigned int timestamp;
+
+   if (!gesture->mouse_info.pressed)
+     return;
+
+   x = ev->cur.canvas.x;
+   y = ev->cur.canvas.y;
+   timestamp = ev->timestamp;
+
+   if (!gesture->active)
+     {
+        gesture->active = _gesture_check(gesture, obj, x, y, timestamp);
+        if (gesture->active)
+          {
+             /* if gesture is activated, terminate main touch event processing
+              * in enlightenment */
+             if (gesture->type != POL_GESTURE_TYPE_NONE)
+               e_comp_wl_touch_cancel();
+
+             if (gesture->cb.start)
+               gesture->cb.start(gesture->cb.data, obj, x, y, timestamp);
+          }
+        return;
+     }
+
+   if (gesture->cb.move)
+     gesture->cb.move(gesture->cb.data, obj, x, y, timestamp);
+}
+
+static void
+_gesture_obj_cb_mouse_down(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event)
+{
+   E_Policy_Gesture *gesture = data;
+   Evas_Event_Mouse_Down *ev = event;
+
+   gesture->active = EINA_FALSE;
+   gesture->mouse_info.pressed = EINA_TRUE;
+   gesture->mouse_info.x = ev->canvas.x;
+   gesture->mouse_info.y = ev->canvas.y;
+   gesture->mouse_info.timestamp = ev->timestamp;
+
+   gesture->active = _gesture_check(gesture, obj, ev->canvas.x, ev->canvas.y, ev->timestamp);
+   if (gesture->active)
+     {
+        if (gesture->cb.start)
+          gesture->cb.start(gesture->cb.data, obj, ev->canvas.x, ev->canvas.y, ev->timestamp);
+     }
+}
+
+EINTERN E_Policy_Gesture *
+e_service_gesture_add(Evas_Object *obj, E_Policy_Gesture_Type type)
+{
+   E_Policy_Gesture *gesture;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
+
+   gesture = E_NEW(E_Policy_Gesture, 1);
+   if (EINA_UNLIKELY(gesture == NULL))
+     return NULL;
+
+   gesture->obj = obj;
+   gesture->type = type;
+
+   /* we should to repeat mouse event to below object
+    * until we can make sure gesture */
+   if (type != POL_GESTURE_TYPE_NONE)
+     evas_object_repeat_events_set(obj, EINA_TRUE);
+
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
+                                  _gesture_obj_cb_mouse_down, gesture);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
+                                  _gesture_obj_cb_mouse_move, gesture);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
+                                  _gesture_obj_cb_mouse_up, gesture);
+
+   return gesture;
+}
+
+EINTERN void
+e_service_gesture_del(E_Policy_Gesture *gesture)
+{
+   EINA_SAFETY_ON_NULL_RETURN(gesture);
+
+   evas_object_event_callback_del(gesture->obj, EVAS_CALLBACK_MOUSE_DOWN,
+                                  _gesture_obj_cb_mouse_down);
+   evas_object_event_callback_del(gesture->obj, EVAS_CALLBACK_MOUSE_MOVE,
+                                  _gesture_obj_cb_mouse_move);
+   evas_object_event_callback_del(gesture->obj, EVAS_CALLBACK_MOUSE_UP,
+                                  _gesture_obj_cb_mouse_up);
+
+   free(gesture);
+}
+
+EINTERN void
+e_service_gesture_cb_set(E_Policy_Gesture *gesture, E_Policy_Gesture_Start_Cb cb_start, E_Policy_Gesture_Move_Cb cb_move, E_Policy_Gesture_End_Cb cb_end, void *data)
+{
+   EINA_SAFETY_ON_NULL_RETURN(gesture);
+
+   gesture->cb.start = cb_start;
+   gesture->cb.move = cb_move;
+   gesture->cb.end = cb_end;
+   gesture->cb.data = data;
+}
diff --git a/src/bin/services/e_service_gesture.h b/src/bin/services/e_service_gesture.h
new file mode 100644 (file)
index 0000000..836bf05
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef E_SERVICE_GESTURE
+#define E_SERVICE_GESTURE
+
+#include "e_policy_private_data.h"
+
+typedef struct _E_Policy_Gesture E_Policy_Gesture;
+
+typedef enum
+{
+   POL_GESTURE_TYPE_NONE,
+   POL_GESTURE_TYPE_LINE,
+   POL_GESTURE_TYPE_FLICK,
+} E_Policy_Gesture_Type;
+
+typedef void (*E_Policy_Gesture_Start_Cb)(void *data, Evas_Object *obj, int x, int y, unsigned int timestamp);
+typedef void (*E_Policy_Gesture_Move_Cb)(void *data, Evas_Object *obj, int x, int y, unsigned int timestamp);
+typedef void (*E_Policy_Gesture_End_Cb)(void *data, Evas_Object *obj, int x, int y, unsigned int timestamp);
+
+EINTERN E_Policy_Gesture  *e_service_gesture_add(Evas_Object *obj, E_Policy_Gesture_Type type);
+EINTERN void          e_service_gesture_del(E_Policy_Gesture *gesture);
+EINTERN void          e_service_gesture_cb_set(E_Policy_Gesture *gesture, E_Policy_Gesture_Start_Cb cb_start, E_Policy_Gesture_Move_Cb cb_move, E_Policy_Gesture_End_Cb cb_end, void *data);
+
+#endif /* E_SERVICE_GESTURE */
diff --git a/src/bin/services/e_service_lockscreen.c b/src/bin/services/e_service_lockscreen.c
new file mode 100644 (file)
index 0000000..1bb4c03
--- /dev/null
@@ -0,0 +1,23 @@
+#include "e.h"
+#include "services/e_service_lockscreen.h"
+
+EINTERN Eina_Bool
+e_service_lockscreen_client_set(E_Client *ec)
+{
+   if (!ec) return EINA_TRUE;
+   if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
+
+   ELOGF("LOCKSCREEN","Set Client", ec->pixmap, ec);
+
+   eina_stringshare_replace(&ec->icccm.window_role, "lockscreen");
+
+   // set lockscreen layer
+   if (E_LAYER_CLIENT_NOTIFICATION_LOW > evas_object_layer_get(ec->frame))
+     {
+        evas_object_layer_set(ec->frame, E_LAYER_CLIENT_NOTIFICATION_LOW);
+        ec->layer = E_LAYER_CLIENT_NOTIFICATION_LOW;
+     }
+
+   return EINA_TRUE;
+}
+
diff --git a/src/bin/services/e_service_lockscreen.h b/src/bin/services/e_service_lockscreen.h
new file mode 100644 (file)
index 0000000..5135022
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef E_SERVICE_LOCKSCREEN_H
+#define E_SERVICE_LOCKSCREEN_H
+
+#include "e_policy_private_data.h"
+
+EINTERN Eina_Bool     e_service_lockscreen_client_set(E_Client *ec);
+
+#endif
diff --git a/src/bin/services/e_service_quickpanel.c b/src/bin/services/e_service_quickpanel.c
new file mode 100644 (file)
index 0000000..eec0408
--- /dev/null
@@ -0,0 +1,1613 @@
+#include "e.h"
+#include "services/e_service_quickpanel.h"
+#include "services/e_service_gesture.h"
+#include "services/e_service_region.h"
+#include "e_policy_wl.h"
+
+#define SMART_NAME            "quickpanel_object"
+#define INTERNAL_ENTRY                    \
+   Mover_Data *md;                        \
+   md = evas_object_smart_data_get(obj)
+
+#define QP_SHOW(EC)              \
+do                               \
+{                                \
+   EC->visible = EINA_TRUE;      \
+   evas_object_show(EC->frame);  \
+} while (0)
+
+#define QP_HIDE(EC)              \
+do                               \
+{                                \
+   EC->visible = EINA_FALSE;     \
+   evas_object_hide(EC->frame);  \
+} while (0)
+
+#define QP_VISIBLE_SET(EC, VIS)  \
+do                               \
+{                                \
+   if (VIS) QP_SHOW(EC);         \
+   else     QP_HIDE(EC);         \
+} while(0)
+
+typedef struct _E_Policy_Quickpanel E_Policy_Quickpanel;
+typedef struct _Mover_Data Mover_Data;
+typedef struct _Mover_Effect_Data Mover_Effect_Data;
+
+typedef struct _E_QP_Client E_QP_Client;
+
+struct _E_Policy_Quickpanel
+{
+   E_Client *ec;
+   E_Client *below;
+   E_Client *stacking;
+   Evas_Object *mover;
+   Evas_Object *indi_obj;
+   Evas_Object *handler_obj;
+
+   Eina_List *intercept_hooks;
+   Eina_List *hooks;
+   Eina_List *events;
+   Ecore_Idle_Enterer *idle_enterer;
+   Ecore_Event_Handler *buf_change_hdlr;
+
+   struct
+   {
+      Eina_Bool below;
+   } changes;
+
+   E_Policy_Angle_Map rotation;
+
+   Eina_Bool show_block;
+
+   Eina_List *clients; /* list of E_QP_Client */
+};
+
+struct _Mover_Data
+{
+   E_Policy_Quickpanel *qp;
+   E_Client *ec;
+
+   Evas_Object *smart_obj; //smart object
+   Evas_Object *qp_layout_obj; // quickpanel's e_layout_object
+   Evas_Object *handler_mirror_obj; // quickpanel handler mirror object
+   Evas_Object *base_clip; // clipper for quickapnel base object
+   Evas_Object *handler_clip; // clipper for quickpanel handler object
+
+   Eina_Rectangle handler_rect;
+   E_Policy_Angle_Map rotation;
+
+   struct
+   {
+      Ecore_Animator *animator;
+      Mover_Effect_Data *data;
+      int x, y;
+      unsigned int timestamp;
+      float accel;
+      Eina_Bool visible;
+   } effect_info;
+};
+
+struct _Mover_Effect_Data
+{
+   Ecore_Animator *animator;
+   Evas_Object *mover;
+   int from;
+   int to;
+   Eina_Bool visible : 1;
+};
+
+struct _E_QP_Client
+{
+   E_Client *ec;
+   struct
+   {
+      Eina_Bool vis;
+      Eina_Bool scrollable;
+   } hint;
+};
+
+static E_Policy_Quickpanel *_pol_quickpanel = NULL;
+static Evas_Smart *_mover_smart = NULL;
+static Eina_Bool _changed = EINA_FALSE;
+
+static E_QP_Client * _e_qp_client_ec_get(E_Client *ec);
+static Eina_Bool     _e_qp_client_scrollable_update(void);
+
+static E_Policy_Quickpanel *
+_quickpanel_get()
+{
+   return _pol_quickpanel;
+}
+
+static void
+_mover_intercept_show(void *data, Evas_Object *obj)
+{
+   Mover_Data *md;
+   E_Client *ec;
+   Evas *e;
+
+   md = data;
+   md->qp->show_block = EINA_FALSE;
+
+   ec = md->ec;
+   QP_SHOW(ec);
+
+   /* force update */
+   e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
+   e_comp_object_dirty(ec->frame);
+   e_comp_object_render(ec->frame);
+
+  // create base_clip
+   e = evas_object_evas_get(obj);
+   md->base_clip = evas_object_rectangle_add(e);
+   e_layout_pack(md->qp_layout_obj, md->base_clip);
+   e_layout_child_move(md->base_clip, 0, 0);
+   e_layout_child_resize(md->base_clip, ec->w, ec->h);
+   evas_object_color_set(md->base_clip, 255, 255, 255, 255);
+   evas_object_show(md->base_clip);
+   evas_object_clip_set(ec->frame, md->base_clip);
+
+   // create handler_mirror_obj
+   md->handler_mirror_obj =  e_comp_object_util_mirror_add(ec->frame);
+   e_layout_pack(md->qp_layout_obj, md->handler_mirror_obj);
+   e_layout_child_move(md->handler_mirror_obj, ec->x, ec->y);
+   e_layout_child_resize(md->handler_mirror_obj, ec->w, ec->h);
+   evas_object_show(md->handler_mirror_obj);
+
+   // create handler_clip
+   md->handler_clip = evas_object_rectangle_add(e);
+   e_layout_pack(md->qp_layout_obj, md->handler_clip);
+   e_layout_child_move(md->handler_clip, md->handler_rect.x, md->handler_rect.y);
+   e_layout_child_resize(md->handler_clip, md->handler_rect.w, md->handler_rect.h);
+   evas_object_color_set(md->handler_clip, 255, 255, 255, 255);
+   evas_object_show(md->handler_clip);
+   evas_object_clip_set(md->handler_mirror_obj, md->handler_clip);
+
+   evas_object_show(obj);
+}
+
+static void
+_mover_smart_add(Evas_Object *obj)
+{
+   Mover_Data *md;
+
+   md = E_NEW(Mover_Data, 1);
+   if (EINA_UNLIKELY(!md))
+     return;
+
+   md->smart_obj = obj;
+   md->qp_layout_obj = e_layout_add(evas_object_evas_get(obj));
+   evas_object_color_set(md->qp_layout_obj, 255, 255, 255, 255);
+   evas_object_smart_member_add(md->qp_layout_obj, md->smart_obj);
+
+   evas_object_smart_data_set(obj, md);
+
+   evas_object_move(obj, -1 , -1);
+   evas_object_layer_set(obj, EVAS_LAYER_MAX - 1); // EVAS_LAYER_MAX :L cursor layer
+   evas_object_intercept_show_callback_add(obj, _mover_intercept_show, md);
+}
+
+static void
+_mover_smart_del(Evas_Object *obj)
+{
+   E_Client *ec;
+
+   INTERNAL_ENTRY;
+
+   ec = md->qp->ec;
+   if (md->base_clip)
+     {
+        evas_object_clip_unset(md->base_clip);
+        e_layout_unpack(md->base_clip);
+        evas_object_del(md->base_clip);
+     }
+   if (md->handler_clip)
+     {
+        evas_object_clip_unset(md->handler_clip);
+        e_layout_unpack(md->handler_clip);
+        evas_object_del(md->handler_clip);
+     }
+   if (md->handler_mirror_obj)
+     {
+        e_layout_unpack(md->handler_mirror_obj);
+        evas_object_del(md->handler_mirror_obj);
+     }
+
+   if (md->qp_layout_obj) evas_object_del(md->qp_layout_obj);
+
+   evas_object_color_set(ec->frame, ec->netwm.opacity, ec->netwm.opacity, ec->netwm.opacity, ec->netwm.opacity);
+
+   md->qp->mover = NULL;
+
+   e_zone_orientation_block_set(md->qp->ec->zone, "quickpanel-mover", EINA_FALSE);
+
+   free(md);
+}
+
+static void
+_mover_smart_show(Evas_Object *obj)
+{
+   INTERNAL_ENTRY;
+
+   evas_object_show(md->qp_layout_obj);
+}
+
+static void
+_mover_smart_hide(Evas_Object *obj)
+{
+   INTERNAL_ENTRY;
+
+   evas_object_hide(md->qp_layout_obj);
+}
+
+static void
+_mover_smart_move(Evas_Object *obj, int x, int y)
+{
+   INTERNAL_ENTRY;
+
+   evas_object_move(md->qp_layout_obj, x, y);
+}
+
+static void
+_mover_smart_resize(Evas_Object *obj, int w, int h)
+{
+   INTERNAL_ENTRY;
+
+   e_layout_virtual_size_set(md->qp_layout_obj, w, h);
+   evas_object_resize(md->qp_layout_obj, w, h);
+}
+
+static void
+_mover_smart_init(void)
+{
+   if (_mover_smart) return;
+   {
+      static const Evas_Smart_Class sc =
+      {
+         SMART_NAME,
+         EVAS_SMART_CLASS_VERSION,
+         _mover_smart_add,
+         _mover_smart_del,
+         _mover_smart_move,
+         _mover_smart_resize,
+         _mover_smart_show,
+         _mover_smart_hide,
+         NULL, /* color_set */
+         NULL, /* clip_set */
+         NULL, /* clip_unset */
+         NULL, /* calculate */
+         NULL, /* member_add */
+         NULL, /* member_del */
+
+         NULL, /* parent */
+         NULL, /* callbacks */
+         NULL, /* interfaces */
+         NULL  /* data */
+      };
+      _mover_smart = evas_smart_class_new(&sc);
+   }
+}
+
+static Eina_Bool
+_mover_obj_handler_move(Mover_Data *md, int x, int y)
+{
+   E_Zone *zone;
+   E_Client *ec;
+
+   ec = md->ec;
+   zone = ec->zone;
+   switch (md->rotation)
+     {
+      case E_POLICY_ANGLE_MAP_90:
+         if ((x + md->handler_rect.w) > zone->w) return EINA_FALSE;
+
+         md->handler_rect.x = x;
+         e_layout_child_resize(md->base_clip, md->handler_rect.x, ec->h);
+         e_layout_child_move(md->handler_mirror_obj, md->handler_rect.x - ec->w + md->handler_rect.w, md->handler_rect.y);
+         e_layout_child_move(md->handler_clip, md->handler_rect.x, md->handler_rect.y);
+         break;
+      case E_POLICY_ANGLE_MAP_180:
+         if ((y - md->handler_rect.h) < 0) return EINA_FALSE;
+
+         md->handler_rect.y = y;
+         e_layout_child_move(md->base_clip, md->handler_rect.x, md->handler_rect.y);
+         e_layout_child_resize(md->base_clip, ec->w, ec->h - md->handler_rect.y);
+         e_layout_child_move(md->handler_mirror_obj, md->handler_rect.x, md->handler_rect.y - md->handler_rect.h);
+         e_layout_child_move(md->handler_clip, md->handler_rect.x, md->handler_rect.y - md->handler_rect.h);
+         break;
+      case E_POLICY_ANGLE_MAP_270:
+         if ((x - md->handler_rect.w) < 0) return EINA_FALSE;
+
+         md->handler_rect.x = x;
+         e_layout_child_move(md->base_clip, md->handler_rect.x, md->handler_rect.y);
+         e_layout_child_resize(md->base_clip, ec->w - md->handler_rect.x, ec->h);
+         e_layout_child_move(md->handler_mirror_obj, md->handler_rect.x - md->handler_rect.w, md->handler_rect.y);
+         e_layout_child_move(md->handler_clip, md->handler_rect.x - md->handler_rect.w, md->handler_rect.y);
+         break;
+      default:
+        if ((y + md->handler_rect.h) > zone->h) return EINA_FALSE;
+
+        md->handler_rect.y = y;
+        e_layout_child_resize(md->base_clip, ec->w, md->handler_rect.y);
+        e_layout_child_move(md->handler_mirror_obj, md->handler_rect.x, md->handler_rect.y - ec->h + md->handler_rect.h);
+        e_layout_child_move(md->handler_clip, md->handler_rect.x, md->handler_rect.y);
+     }
+
+   return EINA_TRUE;
+}
+
+static Evas_Object *
+_mover_obj_new(E_Policy_Quickpanel *qp)
+{
+   Evas_Object *mover;
+   Mover_Data *md;
+   int x, y, w, h;
+
+   /* Pause changing zone orientation during mover object is working. */
+   e_zone_orientation_block_set(qp->ec->zone, "quickpanel-mover", EINA_TRUE);
+
+   _mover_smart_init();
+   mover = evas_object_smart_add(evas_object_evas_get(qp->ec->frame), _mover_smart);
+
+   /* Should setup 'md' before call evas_object_show() */
+   md = evas_object_smart_data_get(mover);
+   md->qp = qp;
+   md->ec = qp->ec;
+   md->rotation = qp->rotation;
+
+   e_service_region_rectangle_get(qp->handler_obj, qp->rotation, &x, &y, &w, &h);
+   EINA_RECTANGLE_SET(&md->handler_rect, x, y, w, h);
+
+   evas_object_move(mover, 0, 0);
+   evas_object_resize(mover, qp->ec->w, qp->ec->h);
+   evas_object_show(mover);
+
+   qp->mover = mover;
+   qp->show_block = EINA_FALSE;
+
+   return mover;
+}
+
+static Evas_Object *
+_mover_obj_new_with_move(E_Policy_Quickpanel *qp, int x, int y, unsigned int timestamp)
+{
+   Evas_Object *mover;
+   Mover_Data *md;
+
+   mover = _mover_obj_new(qp);
+   if (!mover)
+     return NULL;
+
+   md = evas_object_smart_data_get(mover);
+   md->effect_info.x = x;
+   md->effect_info.y = y;
+   md->effect_info.timestamp = timestamp;
+
+   _mover_obj_handler_move(md, x, y);
+
+   return mover;
+}
+
+static void
+_mover_obj_visible_set(Evas_Object *mover, Eina_Bool visible)
+{
+   Mover_Data *md;
+   E_Client *ec;
+   int x = 0, y = 0;
+
+   md = evas_object_smart_data_get(mover);
+   ec = md->ec;
+
+   switch (md->rotation)
+     {
+      case E_POLICY_ANGLE_MAP_90:
+         x = visible ? ec->zone->w : 0;
+         break;
+      case E_POLICY_ANGLE_MAP_180:
+         y = visible ? 0 : ec->zone->h;
+         break;
+      case E_POLICY_ANGLE_MAP_270:
+         x = visible ? 0 : ec->zone->w;
+         break;
+      default:
+         y = visible ? ec->zone->h : 0;
+         break;
+     }
+
+   _mover_obj_handler_move(md, x, y);
+}
+
+static Eina_Bool
+_mover_obj_move(Evas_Object *mover, int x, int y, unsigned int timestamp)
+{
+   Mover_Data *md;
+   int dp;
+   unsigned int dt;
+
+   if (!mover) return EINA_FALSE;
+
+   md = evas_object_smart_data_get(mover);
+   if (!_mover_obj_handler_move(md, x, y)) return EINA_FALSE;
+
+   /* Calculate the acceleration of movement,
+    * determine the visibility of quickpanel based on the result. */
+   dt = timestamp - md->effect_info.timestamp;
+   switch (md->rotation)
+     {
+      case E_POLICY_ANGLE_MAP_90:
+         dp = x - md->effect_info.x;
+         break;
+      case E_POLICY_ANGLE_MAP_180:
+         dp = md->effect_info.y - y;
+         break;
+      case E_POLICY_ANGLE_MAP_270:
+         dp = md->effect_info.x - x;
+         break;
+      default:
+         dp = y - md->effect_info.y;
+         break;
+     }
+   if (dt) md->effect_info.accel = (float)dp / (float)dt;
+
+   /* Store current information to next calculation */
+   md->effect_info.x = x;
+   md->effect_info.y = y;
+   md->effect_info.timestamp = timestamp;
+
+   return EINA_TRUE;
+}
+
+static Mover_Effect_Data *
+_mover_obj_effect_data_new(Evas_Object *mover, int from, int to, Eina_Bool visible)
+{
+   Mover_Effect_Data *ed;
+
+   ed = E_NEW(Mover_Effect_Data, 1);
+   if (!ed) return NULL;
+
+   ed->mover = mover;
+   ed->visible = visible;
+   ed->from = from;
+   ed->to = to;
+
+   return ed;
+}
+
+static void
+_mover_obj_effect_cb_mover_obj_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Mover_Effect_Data *ed = data;
+   Mover_Data *md;
+
+   ed = data;
+   md = evas_object_smart_data_get(ed->mover);
+   QP_VISIBLE_SET(md->qp->ec, ed->visible);
+
+   /* make sure NULL before calling ecore_animator_del() */
+   ed->mover = NULL;
+
+   ecore_animator_del(ed->animator);
+   ed->animator = NULL;
+}
+
+static void
+_mover_obj_effect_data_free(Mover_Effect_Data *ed)
+{
+   E_Policy_Quickpanel *qp;
+   Mover_Data *md;
+   E_QP_Client *qp_client;
+   Eina_List *l;
+
+   if (ed->mover)
+     {
+        md = evas_object_smart_data_get(ed->mover);
+        QP_VISIBLE_SET(md->qp->ec, ed->visible);
+
+        evas_object_event_callback_del(ed->mover, EVAS_CALLBACK_DEL, _mover_obj_effect_cb_mover_obj_del);
+        evas_object_del(ed->mover);
+     }
+
+   qp = _quickpanel_get();
+   if (qp)
+     {
+        EINA_LIST_FOREACH(qp->clients, l, qp_client)
+          e_tzsh_qp_state_visible_update(qp_client->ec,
+                                         ed->visible);
+     }
+
+   free(ed);
+}
+
+static Eina_Bool
+_mover_obj_effect_update(void *data, double pos)
+{
+   Mover_Effect_Data *ed = data;
+   Mover_Data *md;
+   int new_x = 0, new_y = 0;
+   double progress = 0;
+
+   progress = ecore_animator_pos_map(pos, ECORE_POS_MAP_DECELERATE, 0, 0);
+
+   md = evas_object_smart_data_get(ed->mover);
+
+   switch (md->rotation)
+     {
+      case E_POLICY_ANGLE_MAP_90:
+      case E_POLICY_ANGLE_MAP_270:
+         new_x = ed->from + (ed->to * progress);
+         break;
+      default:
+      case E_POLICY_ANGLE_MAP_180:
+         new_y = ed->from + (ed->to * progress);
+         break;
+     }
+   _mover_obj_handler_move(md, new_x, new_y);
+
+   if (pos == 1.0)
+     {
+        ecore_animator_del(ed->animator);
+        ed->animator = NULL;
+
+        _mover_obj_effect_data_free(ed);
+
+        return ECORE_CALLBACK_CANCEL;
+     }
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static void
+_mover_obj_effect_start(Evas_Object *mover, Eina_Bool visible)
+{
+   Mover_Data *md;
+   E_Client *ec;
+   Mover_Effect_Data *ed;
+   int from;
+   int to;
+   double duration;
+   const double ref = 0.1;
+
+   md = evas_object_smart_data_get(mover);
+   ec = md->qp->ec;
+
+   switch (md->rotation)
+     {
+      case E_POLICY_ANGLE_MAP_90:
+         from = md->handler_rect.x;
+         to = (visible) ? (ec->zone->w - from) : (-from);
+         duration = ((double)abs(to) / (ec->zone->w / 2)) * ref;
+         break;
+      case E_POLICY_ANGLE_MAP_180:
+         from = md->handler_rect.y;
+         to = (visible) ? (-from) : (ec->zone->h - from);
+         duration = ((double)abs(to) / (ec->zone->h / 2)) * ref;
+         break;
+      case E_POLICY_ANGLE_MAP_270:
+         from = md->handler_rect.x;
+         to = (visible) ? (-from) : (ec->zone->w - from);
+         duration = ((double)abs(to) / (ec->zone->w / 2)) * ref;
+         break;
+      default:
+         from = md->handler_rect.y;
+         to = (visible) ? (ec->zone->h - from) : (-from);
+         duration = ((double)abs(to) / (ec->zone->h / 2)) * ref;
+         break;
+     }
+
+   /* create effect data */
+   ed = _mover_obj_effect_data_new(mover, from, to, visible);
+
+   /* start move effect */
+   ed->animator = ecore_animator_timeline_add(duration,
+                                              _mover_obj_effect_update,
+                                              ed);
+
+   evas_object_event_callback_add(mover, EVAS_CALLBACK_DEL, _mover_obj_effect_cb_mover_obj_del, ed);
+
+   md->effect_info.animator = ed->animator;
+   md->effect_info.visible = visible;
+   md->effect_info.data = ed;
+}
+
+static void
+_mover_obj_effect_stop(Evas_Object *mover)
+{
+   Mover_Data *md;
+
+   md = evas_object_smart_data_get(mover);
+   md->effect_info.data->mover = NULL;
+
+   evas_object_event_callback_del(mover, EVAS_CALLBACK_DEL, _mover_obj_effect_cb_mover_obj_del);
+
+   E_FREE_FUNC(md->effect_info.animator, ecore_animator_del);
+}
+
+static Eina_Bool
+_mover_obj_visibility_eval(Evas_Object *mover)
+{
+   E_Client *ec;
+   Mover_Data *md;
+   Eina_Bool threshold;
+   const float sensitivity = 1.5; /* hard coded. (arbitrary) */
+
+   md = evas_object_smart_data_get(mover);
+   ec = md->ec;
+
+   switch (md->rotation)
+     {
+        case E_POLICY_ANGLE_MAP_90:
+           threshold = (md->handler_rect.x > (ec->zone->w / 2));
+           break;
+        case E_POLICY_ANGLE_MAP_180:
+           threshold = (md->handler_rect.y < (ec->zone->h / 2));
+           break;
+        case E_POLICY_ANGLE_MAP_270:
+           threshold = (md->handler_rect.x < (ec->zone->w / 2));
+           break;
+        default:
+           threshold = (md->handler_rect.y > (ec->zone->h / 2));
+           break;
+     }
+
+   if ((md->effect_info.accel > sensitivity) ||
+       ((md->effect_info.accel > -sensitivity) && threshold))
+     return EINA_TRUE;
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+_mover_obj_is_animating(Evas_Object *mover)
+{
+   Mover_Data *md;
+
+   md = evas_object_smart_data_get(mover);
+
+   return !!md->effect_info.animator;
+}
+
+static Eina_Bool
+_mover_obj_effect_visible_get(Evas_Object *mover)
+{
+   Mover_Data *md;
+
+   md = evas_object_smart_data_get(mover);
+
+   return md->effect_info.visible;
+}
+
+static void
+_region_obj_cb_gesture_start(void *data, Evas_Object *handler, int x, int y, unsigned int timestamp)
+{
+   E_Policy_Quickpanel *qp;
+
+   qp = data;
+   if (EINA_UNLIKELY(!qp))
+     return;
+
+   if (EINA_UNLIKELY(!qp->ec))
+     return;
+
+   if (e_object_is_del(E_OBJECT(qp->ec)))
+     return;
+
+   if (qp->mover)
+     {
+        if (_mover_obj_is_animating(qp->mover))
+          return;
+
+        DBG("Mover object already existed");
+        evas_object_del(qp->mover);
+     }
+
+   _mover_obj_new_with_move(qp, x, y, timestamp);
+}
+
+static void
+_region_obj_cb_gesture_move(void *data, Evas_Object *handler, int x, int y, unsigned int timestamp)
+{
+   E_Policy_Quickpanel *qp;
+
+   qp = data;
+   if (!qp->mover)
+     return;
+
+   if (_mover_obj_is_animating(qp->mover))
+     return;
+
+   _mover_obj_move(qp->mover, x, y, timestamp);
+}
+
+static void
+_region_obj_cb_gesture_end(void *data EINA_UNUSED, Evas_Object *handler, int x, int y, unsigned int timestamp)
+{
+   E_Policy_Quickpanel *qp;
+   Eina_Bool v;
+
+   qp = data;
+   if (!qp->mover)
+     {
+        DBG("Could not find quickpanel mover object");
+        return;
+     }
+
+   if (_mover_obj_is_animating(qp->mover))
+     return;
+
+   v = _mover_obj_visibility_eval(qp->mover);
+   _mover_obj_effect_start(qp->mover, v);
+}
+
+static void
+_quickpanel_free(E_Policy_Quickpanel *qp)
+{
+   E_FREE_LIST(qp->clients, free);
+   E_FREE_FUNC(qp->mover, evas_object_del);
+   E_FREE_FUNC(qp->indi_obj, evas_object_del);
+   E_FREE_FUNC(qp->handler_obj, evas_object_del);
+   E_FREE_FUNC(qp->idle_enterer, ecore_idle_enterer_del);
+   E_FREE_LIST(qp->events, ecore_event_handler_del);
+   E_FREE_LIST(qp->hooks, e_client_hook_del);
+   E_FREE_LIST(qp->intercept_hooks, e_comp_object_intercept_hook_del);
+   E_FREE(_pol_quickpanel);
+}
+
+static void
+_quickpanel_hook_client_del(void *d, E_Client *ec)
+{
+   E_Policy_Quickpanel *qp;
+
+   qp = d;
+   if (EINA_UNLIKELY(!qp))
+     return;
+
+   if (!ec) return;
+
+   if (qp->ec != ec)
+     return;
+
+   _quickpanel_free(qp);
+
+   e_zone_orientation_force_update_del(ec->zone, ec);
+}
+
+static void
+_quickpanel_client_evas_cb_show(void *data, Evas *evas, Evas_Object *obj, void *event)
+{
+   E_Policy_Quickpanel *qp;
+
+   qp = data;
+   if (EINA_UNLIKELY(!qp))
+     return;
+
+   evas_object_show(qp->handler_obj);
+   evas_object_raise(qp->handler_obj);
+   evas_object_hide(qp->indi_obj);
+
+   E_FREE_FUNC(qp->buf_change_hdlr, ecore_event_handler_del);
+}
+
+static Eina_Bool
+_quickpanel_cb_buffer_change(void *data, int type, void *event)
+{
+   E_Policy_Quickpanel *qp;
+   E_Event_Client *ev;
+   E_Client *ec;
+
+   qp = data;
+   if (!qp->ec)
+     goto end;
+
+   ev = event;
+   ec = ev->ec;
+   if (qp->ec != ec)
+     goto end;
+
+   /* render forcibly */
+   e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
+   e_comp_object_dirty(ec->frame);
+   e_comp_object_render(ec->frame);
+
+   /* make frame event */
+   e_pixmap_image_clear(ec->pixmap, EINA_TRUE);
+
+end:
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static void
+_quickpanel_client_evas_cb_hide(void *data, Evas *evas, Evas_Object *obj, void *event)
+{
+   E_Policy_Quickpanel *qp;
+
+   qp = data;
+   if (EINA_UNLIKELY(!qp))
+     return;
+
+   evas_object_hide(qp->handler_obj);
+   evas_object_show(qp->indi_obj);
+}
+
+static void
+_quickpanel_client_evas_cb_move(void *data, Evas *evas, Evas_Object *obj, void *event)
+{
+   E_Policy_Quickpanel *qp;
+   int x, y, hx, hy;
+
+   qp = data;
+   if (EINA_UNLIKELY(!qp))
+     return;
+
+   e_service_region_rectangle_get(qp->handler_obj, qp->rotation, &hx, &hy, NULL, NULL);
+   evas_object_geometry_get(obj, &x, &y, NULL, NULL);
+   evas_object_move(qp->handler_obj, x + hx, y + hy);
+}
+
+static void
+_quickpanel_handler_rect_add(E_Policy_Quickpanel *qp, E_Policy_Angle_Map ridx, int x, int y, int w, int h)
+{
+   E_Client *ec;
+   Evas_Object *obj;
+
+   ec = qp->ec;
+
+   ELOGF("QUICKPANEL", "Handler Geo Set | x %d, y %d, w %d, h %d",
+         NULL, NULL, x, y, w, h);
+
+   if (qp->handler_obj)
+     goto end;
+
+   obj = e_service_region_object_new();
+   evas_object_name_set(obj, "qp::handler_obj");
+   if (!obj)
+     return;
+
+   e_service_region_cb_set(obj,
+                       _region_obj_cb_gesture_start,
+                       _region_obj_cb_gesture_move,
+                       _region_obj_cb_gesture_end, qp);
+
+   /* Add handler object to smart member to follow the client's stack */
+   evas_object_smart_member_add(obj, ec->frame);
+   evas_object_propagate_events_set(obj, 0);
+   if (evas_object_visible_get(ec->frame))
+     evas_object_show(obj);
+
+   qp->handler_obj = obj;
+
+end:
+   e_service_region_rectangle_set(qp->handler_obj, ridx, x, y, w, h);
+}
+
+static void
+_quickpanel_handler_region_set(E_Policy_Quickpanel *qp, E_Policy_Angle_Map ridx, Eina_Tiler *tiler)
+{
+   Eina_Iterator *it;
+   Eina_Rectangle *r;
+   int x = 0, y = 0;
+
+   /* FIXME supported single rectangle, not tiler */
+
+   it = eina_tiler_iterator_new(tiler);
+   EINA_ITERATOR_FOREACH(it, r)
+     {
+        _quickpanel_handler_rect_add(qp, ridx, r->x, r->y, r->w, r->h);
+
+        /* FIXME: this should be set by another way like indicator */
+        if (ridx == E_POLICY_ANGLE_MAP_180)
+          {
+             x = 0;
+             y = qp->ec->zone->h - r->h;
+          }
+        else if (ridx == E_POLICY_ANGLE_MAP_270)
+          {
+             x = qp->ec->zone->w - r->w;
+             y = 0;
+          }
+        e_service_region_rectangle_set(qp->indi_obj, ridx, x, y, r->w, r->h);
+
+        break;
+     }
+   eina_iterator_free(it);
+}
+
+static void
+_e_qp_vis_change(E_Policy_Quickpanel *qp, Eina_Bool vis, Eina_Bool with_effect)
+{
+   E_Client *ec;
+   Evas_Object *mover;
+   Eina_Bool res, cur_vis = EINA_FALSE;
+   int x, y, w, h;
+
+   res = _e_qp_client_scrollable_update();
+   if (!res) return;
+
+   ec = qp->ec;
+
+   evas_object_geometry_get(ec->frame, &x, &y, &w, &h);
+
+   if (E_INTERSECTS(x, y, w, h, ec->zone->x, ec->zone->y, ec->zone->w, ec->zone->h))
+     cur_vis = evas_object_visible_get(ec->frame);
+
+   if (cur_vis == vis)
+     return;
+
+   mover = qp->mover;
+
+   if (with_effect)
+     {
+        if (mover)
+          {
+             if (_mover_obj_is_animating(mover))
+               {
+                  if (_mover_obj_effect_visible_get(mover) == vis)
+                    return;
+
+                  _mover_obj_effect_stop(mover);
+               }
+          }
+        else
+          {
+             mover = _mover_obj_new(qp);
+             _mover_obj_visible_set(mover, !vis);
+          }
+
+        _mover_obj_effect_start(mover, vis);
+     }
+   else
+     {
+        if (mover)
+          {
+             if (_mover_obj_is_animating(mover))
+               _mover_obj_effect_stop(mover);
+             evas_object_del(mover);
+          }
+
+        QP_VISIBLE_SET(ec, vis);
+     }
+}
+
+static Eina_Bool
+_quickpanel_cb_rotation_begin(void *data, int type, void *event)
+{
+   E_Policy_Quickpanel *qp;
+   E_Event_Client *ev = event;
+   E_Client *ec;
+
+   qp = data;
+   if (EINA_UNLIKELY(!qp))
+     goto end;
+
+   ec = ev->ec;
+   if (EINA_UNLIKELY(!ec))
+     goto end;
+
+   if (qp->ec != ec)
+     goto end;
+
+   E_FREE_FUNC(qp->mover, evas_object_del);
+
+   evas_object_hide(qp->indi_obj);
+   evas_object_hide(qp->handler_obj);
+
+end:
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_quickpanel_cb_rotation_cancel(void *data, int type, void *event)
+{
+   E_Policy_Quickpanel *qp;
+   E_Event_Client *ev = event;
+   E_Client *ec;
+
+   qp = data;
+   if (EINA_UNLIKELY(!qp))
+     goto end;
+
+   ec = ev->ec;
+   if (EINA_UNLIKELY(!ec))
+     goto end;
+
+   if (qp->ec != ec)
+     goto end;
+
+   if (evas_object_visible_get(ec->frame))
+     evas_object_show(qp->handler_obj);
+   else
+     evas_object_show(qp->indi_obj);
+
+end:
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_quickpanel_cb_rotation_done(void *data, int type, void *event)
+{
+   E_Policy_Quickpanel *qp;
+   E_Event_Client *ev = event;
+   E_Client *ec;
+   E_QP_Client *qp_client;
+   Eina_List *l;
+
+   qp = data;
+   if (EINA_UNLIKELY(!qp))
+     goto end;
+
+   ec = ev->ec;
+   if (EINA_UNLIKELY(!ec))
+     goto end;
+
+   if (qp->ec != ec)
+     goto end;
+
+   qp->rotation = e_policy_angle_map(ec->e.state.rot.ang.curr);
+
+   if (evas_object_visible_get(ec->frame))
+     evas_object_show(qp->handler_obj);
+   else
+     evas_object_show(qp->indi_obj);
+
+   EINA_LIST_FOREACH(qp->clients, l, qp_client)
+     e_tzsh_qp_state_orientation_update(qp_client->ec,
+                                        qp->rotation);
+
+end:
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+/* NOTE: if the state(show/hide/stack) of windows which are stacked below
+ * quickpanel is changed, we close the quickpanel.
+ * the most major senario is that quickpanel should be closed when WiFi popup to
+ * show the available connection list is shown by click the button on
+ * the quickpanel to turn on the WiFi.
+ * @see  _quickpanel_cb_client_show(),
+ *       _quickpanel_cb_client_hide()
+ *       _quickpanel_cb_client_stack()
+ *       _quickpanel_cb_client_remove()
+ *       _quickpanel_idle_enter()
+ */
+static E_Client *
+_quickpanel_below_visible_client_get(E_Policy_Quickpanel *qp)
+{
+   E_Client *ec;
+
+   for (ec = e_client_below_get(qp->ec); ec; ec = e_client_below_get(ec))
+     {
+        if (!ec->visible) continue;
+        if (!ec->icccm.accepts_focus) continue;
+
+        return ec;
+     }
+
+   return NULL;
+}
+
+static void
+_quickpanel_below_change_eval(void *data, void *event)
+{
+   E_Policy_Quickpanel *qp;
+   E_Event_Client *ev;
+
+   qp = data;
+   if (EINA_UNLIKELY(!qp))
+     return;
+
+   ev = event;
+   if (EINA_UNLIKELY((!ev) || (!ev->ec)))
+     return;
+
+   if (e_policy_client_is_cursor(ev->ec))
+     return;
+
+   qp->changes.below = EINA_TRUE;
+   _changed = EINA_TRUE;
+}
+
+static Eina_Bool
+_quickpanel_cb_client_show(void *data, int type, void *event)
+{
+   _quickpanel_below_change_eval(data, event);
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_quickpanel_cb_client_hide(void *data, int type, void *event)
+{
+   _quickpanel_below_change_eval(data, event);
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_quickpanel_cb_client_stack(void *data, int type, void *event)
+{
+   E_Policy_Quickpanel *qp;
+   E_Event_Client *ev;
+
+   qp = data;
+   EINA_SAFETY_ON_NULL_GOTO(qp, end);
+
+   ev = event;
+   EINA_SAFETY_ON_NULL_GOTO(ev, end);
+
+   qp->stacking = ev->ec;
+
+   DBG("Stacking Client '%s'(%p)",
+       ev->ec->icccm.name ? ev->ec->icccm.name : "", ev->ec);
+
+   _quickpanel_below_change_eval(data, event);
+end:
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_quickpanel_cb_client_remove(void *data, int type, void *event)
+{
+   _quickpanel_below_change_eval(data, event);
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Evas_Object *
+_quickpanel_indicator_object_new(E_Policy_Quickpanel *qp)
+{
+   Evas_Object *indi_obj;
+
+   indi_obj = e_service_region_object_new();
+   evas_object_name_set(indi_obj, "qp::indicator_obj");
+   if (!indi_obj)
+     return NULL;
+
+   evas_object_repeat_events_set(indi_obj, EINA_FALSE);
+   /* FIXME: make me move to explicit layer something like POL_LAYER */
+   evas_object_layer_set(indi_obj, EVAS_LAYER_MAX - 1);
+
+   e_service_region_cb_set(indi_obj,
+                       _region_obj_cb_gesture_start,
+                       _region_obj_cb_gesture_move,
+                       _region_obj_cb_gesture_end, qp);
+
+   evas_object_show(indi_obj);
+
+   return indi_obj;
+}
+
+static Eina_Bool
+_quickpanel_idle_enter(void *data)
+{
+   E_Policy_Quickpanel *qp;
+
+   if (!_changed)
+     goto end;
+   _changed = EINA_FALSE;
+
+   qp = data;
+   if (EINA_UNLIKELY(!qp))
+     goto end;
+
+   if (qp->changes.below)
+     {
+        E_Client *below;
+
+        below = _quickpanel_below_visible_client_get(qp);
+        if (qp->below != below)
+          {
+             DBG("qp->below '%s'(%p) new_below '%s'(%p)\n",
+                 qp->below ? (qp->below->icccm.name ? qp->below->icccm.name : "") : "",
+                 qp->below,
+                 below ? (below->icccm.name ? below->icccm.name : "") : "",
+                 below);
+
+             qp->below = below;
+
+             /* QUICKFIX
+              * hide the quickpanel, if below client is the stacking client.
+              * it means to find out whether or not it was launched.
+              */
+             if ((qp->stacking == below) &&
+                 (qp->ec->visible))
+               e_service_quickpanel_hide();
+
+             _e_qp_client_scrollable_update();
+          }
+
+        qp->stacking = NULL;
+        qp->changes.below = EINA_FALSE;
+     }
+
+end:
+   return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool
+_quickpanel_intercept_hook_show(void *data, E_Client *ec)
+{
+   E_Policy_Quickpanel *qp;
+
+   qp = data;
+   if (EINA_UNLIKELY(!qp))
+     goto end;
+
+   if (qp->ec != ec)
+     goto end;
+
+   if (qp->show_block)
+     {
+        ec->visible = EINA_FALSE;
+        return EINA_FALSE;
+     }
+
+end:
+   return EINA_TRUE;
+}
+
+static E_QP_Client *
+_e_qp_client_ec_get(E_Client *ec)
+{
+   E_Policy_Quickpanel *qp = _quickpanel_get();
+   E_QP_Client *qp_client = NULL;
+   Eina_List *l;
+
+   EINA_LIST_FOREACH(qp->clients, l, qp_client)
+     {
+        if (qp_client->ec == ec)
+          return qp_client;
+     }
+
+   return qp_client;
+}
+
+/* return value
+ *  EINA_TRUE : user can scrool the QP.
+ *  EINA_FALSE: user can't scroll QP since below window doesn't want.
+ */
+static Eina_Bool
+_e_qp_client_scrollable_update(void)
+{
+   E_Policy_Quickpanel *qp;
+   E_QP_Client *qp_client;
+   Eina_Bool res = EINA_TRUE;
+
+   qp = _quickpanel_get();
+   EINA_SAFETY_ON_NULL_RETURN_VAL(qp, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(qp->ec, EINA_FALSE);
+   EINA_SAFETY_ON_TRUE_RETURN_VAL(e_object_is_del(E_OBJECT(qp->ec)), EINA_FALSE);
+
+   if (!qp->below)
+     {
+        evas_object_pass_events_set(qp->handler_obj, EINA_FALSE);
+        evas_object_pass_events_set(qp->indi_obj, EINA_FALSE);
+        return EINA_TRUE;
+     }
+
+   /* Do not show and scroll the quickpanel window if the qp_client winodw
+    * which is placed at the below of the quickpanel window doesn't want
+    * to show and scroll the quickpanel window.
+    */
+   qp_client = _e_qp_client_ec_get(qp->below);
+   if ((qp_client) && (!qp_client->hint.scrollable))
+     {
+        evas_object_pass_events_set(qp->handler_obj, EINA_TRUE);
+        evas_object_pass_events_set(qp->indi_obj, EINA_TRUE);
+        res = EINA_FALSE;
+     }
+   else
+     {
+        evas_object_pass_events_set(qp->handler_obj, EINA_FALSE);
+        evas_object_pass_events_set(qp->indi_obj, EINA_FALSE);
+        res = EINA_TRUE;
+     }
+
+   return res;
+}
+
+
+#undef E_CLIENT_HOOK_APPEND
+#define E_CLIENT_HOOK_APPEND(l, t, cb, d) \
+  do                                      \
+    {                                     \
+       E_Client_Hook *_h;                 \
+       _h = e_client_hook_add(t, cb, d);  \
+       assert(_h);                        \
+       l = eina_list_append(l, _h);       \
+    }                                     \
+  while (0)
+
+#undef E_COMP_OBJECT_INTERCEPT_HOOK_APPEND
+#define E_COMP_OBJECT_INTERCEPT_HOOK_APPEND(l, t, cb, d) \
+  do                                                     \
+    {                                                    \
+       E_Comp_Object_Intercept_Hook *_h;                 \
+       _h = e_comp_object_intercept_hook_add(t, cb, d);  \
+       assert(_h);                                       \
+       l = eina_list_append(l, _h);                      \
+    }                                                    \
+  while (0)
+
+/* NOTE: supported single client for quickpanel for now. */
+EINTERN void
+e_service_quickpanel_client_set(E_Client *ec)
+{
+   E_Policy_Quickpanel *qp;
+
+   if (EINA_UNLIKELY(!ec))
+     {
+        qp = _quickpanel_get();
+        if (qp)
+          _quickpanel_free(qp);
+        return;
+     }
+
+   /* check for client being deleted */
+   if (e_object_is_del(E_OBJECT(ec))) return;
+
+   /* check for wayland pixmap */
+   if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
+
+   /* if we have not setup evas callbacks for this client, do it */
+   if (_pol_quickpanel) return;
+
+   ELOGF("QUICKPANEL", "Set Client | ec %p", NULL, NULL, ec);
+
+   qp = calloc(1, sizeof(*qp));
+   if (!qp)
+     return;
+
+   _pol_quickpanel = qp;
+
+   qp->ec = ec;
+   qp->show_block = EINA_TRUE;
+   qp->below = _quickpanel_below_visible_client_get(qp);
+   qp->indi_obj = _quickpanel_indicator_object_new(qp);
+   if (!qp->indi_obj)
+     {
+        free(qp);
+        return;
+     }
+
+   eina_stringshare_replace(&ec->icccm.window_role, "quickpanel");
+
+   // set quickpanel layer
+   if (E_POLICY_QUICKPANEL_LAYER != evas_object_layer_get(ec->frame))
+     {
+        evas_object_layer_set(ec->frame, E_POLICY_QUICKPANEL_LAYER);
+     }
+   ec->layer = E_POLICY_QUICKPANEL_LAYER;
+
+   // set skip iconify
+   ec->exp_iconify.skip_iconify = 1;
+   ec->e.state.rot.type = E_CLIENT_ROTATION_TYPE_DEPENDENT;
+
+   /* add quickpanel to force update list of zone */
+   e_zone_orientation_force_update_add(ec->zone, ec);
+
+   QP_HIDE(ec);
+
+   evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_SHOW, _quickpanel_client_evas_cb_show, qp);
+   evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_HIDE, _quickpanel_client_evas_cb_hide, qp);
+   evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_MOVE, _quickpanel_client_evas_cb_move, qp);
+
+   E_CLIENT_HOOK_APPEND(qp->hooks,   E_CLIENT_HOOK_DEL,                       _quickpanel_hook_client_del,     qp);
+   E_LIST_HANDLER_APPEND(qp->events, E_EVENT_CLIENT_ROTATION_CHANGE_BEGIN,    _quickpanel_cb_rotation_begin,   qp);
+   E_LIST_HANDLER_APPEND(qp->events, E_EVENT_CLIENT_ROTATION_CHANGE_CANCEL,   _quickpanel_cb_rotation_cancel,  qp);
+   E_LIST_HANDLER_APPEND(qp->events, E_EVENT_CLIENT_ROTATION_CHANGE_END,      _quickpanel_cb_rotation_done,    qp);
+   E_LIST_HANDLER_APPEND(qp->events, E_EVENT_CLIENT_SHOW,                     _quickpanel_cb_client_show,      qp);
+   E_LIST_HANDLER_APPEND(qp->events, E_EVENT_CLIENT_HIDE,                     _quickpanel_cb_client_hide,      qp);
+   E_LIST_HANDLER_APPEND(qp->events, E_EVENT_CLIENT_STACK,                    _quickpanel_cb_client_stack,     qp);
+   E_LIST_HANDLER_APPEND(qp->events, E_EVENT_CLIENT_REMOVE,                   _quickpanel_cb_client_remove,    qp);
+   E_LIST_HANDLER_APPEND(qp->events, E_EVENT_CLIENT_BUFFER_CHANGE,            _quickpanel_cb_buffer_change,    qp);
+
+   E_COMP_OBJECT_INTERCEPT_HOOK_APPEND(qp->intercept_hooks, E_COMP_OBJECT_INTERCEPT_HOOK_SHOW_HELPER, _quickpanel_intercept_hook_show, qp);
+
+
+   qp->idle_enterer = ecore_idle_enterer_add(_quickpanel_idle_enter, qp);
+}
+
+EINTERN E_Client *
+e_service_quickpanel_client_get(void)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(_pol_quickpanel, NULL);
+
+   return _pol_quickpanel->ec;
+}
+
+EINTERN Eina_Bool
+e_service_quickpanel_region_set(int type, int angle, Eina_Tiler *tiler)
+{
+   E_Policy_Quickpanel *qp;
+   E_Policy_Angle_Map ridx;
+
+   qp = _quickpanel_get();
+   if (EINA_UNLIKELY(!qp))
+     return EINA_FALSE;
+
+   if (EINA_UNLIKELY(!qp->ec))
+     return EINA_FALSE;
+
+   if (e_object_is_del(E_OBJECT(qp->ec)))
+     return EINA_FALSE;
+
+   // FIXME: region type
+   if (type != 0)
+     return EINA_FALSE;
+
+   ridx = e_policy_angle_map(angle);
+   _quickpanel_handler_region_set(qp, ridx, tiler);
+
+   return EINA_TRUE;
+}
+
+EINTERN void
+e_service_quickpanel_show(void)
+{
+   E_Policy_Quickpanel *qp;
+
+   qp = _quickpanel_get();
+   EINA_SAFETY_ON_NULL_RETURN(qp);
+   EINA_SAFETY_ON_NULL_RETURN(qp->ec);
+   EINA_SAFETY_ON_TRUE_RETURN(e_object_is_del(E_OBJECT(qp->ec)));
+
+   _e_qp_vis_change(qp, EINA_TRUE, EINA_TRUE);
+}
+
+EINTERN void
+e_service_quickpanel_hide(void)
+{
+   E_Policy_Quickpanel *qp;
+
+   qp = _quickpanel_get();
+   EINA_SAFETY_ON_NULL_RETURN(qp);
+   EINA_SAFETY_ON_NULL_RETURN(qp->ec);
+   EINA_SAFETY_ON_TRUE_RETURN(e_object_is_del(E_OBJECT(qp->ec)));
+
+   _e_qp_vis_change(qp, EINA_FALSE, EINA_TRUE);
+}
+
+EINTERN Eina_Bool
+e_qp_visible_get(void)
+{
+   E_Policy_Quickpanel *qp;
+   E_Client *ec;
+   Eina_Bool vis = EINA_FALSE;
+   int x, y, w, h;
+
+   qp = _quickpanel_get();
+   EINA_SAFETY_ON_NULL_RETURN_VAL(qp, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(qp->ec, EINA_FALSE);
+   EINA_SAFETY_ON_TRUE_RETURN_VAL(e_object_is_del(E_OBJECT(qp->ec)), EINA_FALSE);
+
+   ec = qp->ec;
+   evas_object_geometry_get(ec->frame, &x, &y, &w, &h);
+
+   if (E_INTERSECTS(x, y, w, h, ec->zone->x, ec->zone->y, ec->zone->w, ec->zone->h))
+     vis = evas_object_visible_get(ec->frame);
+
+   return vis;
+}
+
+EINTERN int
+e_qp_orientation_get(void)
+{
+   E_Policy_Quickpanel *qp;
+
+   qp = _quickpanel_get();
+   EINA_SAFETY_ON_NULL_RETURN_VAL(qp, E_POLICY_ANGLE_MAP_0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(qp->ec, E_POLICY_ANGLE_MAP_0);
+   EINA_SAFETY_ON_TRUE_RETURN_VAL(e_object_is_del(E_OBJECT(qp->ec)), E_POLICY_ANGLE_MAP_0);
+
+   return qp->rotation;
+}
+
+EINTERN void
+e_qp_client_add(E_Client *ec)
+{
+   E_Policy_Quickpanel *qp;
+   E_QP_Client *qp_client;
+
+   qp = _quickpanel_get();
+   EINA_SAFETY_ON_NULL_RETURN(qp);
+   EINA_SAFETY_ON_NULL_RETURN(qp->ec);
+   EINA_SAFETY_ON_TRUE_RETURN(e_object_is_del(E_OBJECT(qp->ec)));
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+   EINA_SAFETY_ON_TRUE_RETURN(e_object_is_del(E_OBJECT(ec)));
+
+   qp_client = E_NEW(E_QP_Client, 1);
+   qp_client->ec = ec;
+   qp_client->hint.vis = EINA_TRUE;
+   qp_client->hint.scrollable = EINA_TRUE;
+
+   qp->clients = eina_list_append(qp->clients, qp_client);
+}
+
+EINTERN void
+e_qp_client_del(E_Client *ec)
+{
+   E_Policy_Quickpanel *qp;
+   E_QP_Client *qp_client;
+
+   qp = _quickpanel_get();
+   EINA_SAFETY_ON_NULL_RETURN(qp);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   qp_client = _e_qp_client_ec_get(ec);
+   EINA_SAFETY_ON_NULL_RETURN(qp_client);
+
+   qp->clients = eina_list_remove(qp->clients, qp_client);
+
+   E_FREE(qp_client);
+}
+
+EINTERN void
+e_qp_client_show(E_Client *ec)
+{
+   E_Policy_Quickpanel *qp;
+   E_QP_Client *qp_client;
+
+   qp = _quickpanel_get();
+   EINA_SAFETY_ON_NULL_RETURN(qp);
+   EINA_SAFETY_ON_NULL_RETURN(qp->ec);
+   EINA_SAFETY_ON_TRUE_RETURN(e_object_is_del(E_OBJECT(qp->ec)));
+
+   qp_client = _e_qp_client_ec_get(ec);
+   EINA_SAFETY_ON_NULL_RETURN(qp_client);
+   EINA_SAFETY_ON_FALSE_RETURN(qp_client->hint.scrollable);
+
+   _e_qp_vis_change(qp, EINA_TRUE, EINA_TRUE);
+}
+
+EINTERN void
+e_qp_client_hide(E_Client *ec)
+{
+   E_Policy_Quickpanel *qp;
+   E_QP_Client *qp_client;
+
+   qp = _quickpanel_get();
+   EINA_SAFETY_ON_NULL_RETURN(qp);
+   EINA_SAFETY_ON_NULL_RETURN(qp->ec);
+   EINA_SAFETY_ON_TRUE_RETURN(e_object_is_del(E_OBJECT(qp->ec)));
+
+   qp_client = _e_qp_client_ec_get(ec);
+   EINA_SAFETY_ON_NULL_RETURN(qp_client);
+   EINA_SAFETY_ON_FALSE_RETURN(qp_client->hint.scrollable);
+
+   _e_qp_vis_change(qp, EINA_FALSE, EINA_TRUE);
+}
+
+EINTERN Eina_Bool
+e_qp_client_scrollable_set(E_Client *ec, Eina_Bool set)
+{
+   E_Policy_Quickpanel *qp;
+   E_QP_Client *qp_client;
+
+   qp = _quickpanel_get();
+   EINA_SAFETY_ON_NULL_RETURN_VAL(qp, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(qp->ec, EINA_FALSE);
+   EINA_SAFETY_ON_TRUE_RETURN_VAL(e_object_is_del(E_OBJECT(qp->ec)), EINA_FALSE);
+
+   qp_client = _e_qp_client_ec_get(ec);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(qp_client, EINA_FALSE);
+
+   if (qp_client->hint.scrollable != set)
+     qp_client->hint.scrollable = set;
+
+   _e_qp_client_scrollable_update();
+
+   return EINA_FALSE;
+}
+
+EINTERN Eina_Bool
+e_qp_client_scrollable_get(E_Client *ec)
+{
+   E_Policy_Quickpanel *qp;
+   E_QP_Client *qp_client;
+
+   qp = _quickpanel_get();
+   EINA_SAFETY_ON_NULL_RETURN_VAL(qp, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(qp->ec, EINA_FALSE);
+   EINA_SAFETY_ON_TRUE_RETURN_VAL(e_object_is_del(E_OBJECT(qp->ec)), EINA_FALSE);
+
+   qp_client = _e_qp_client_ec_get(ec);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(qp_client, EINA_FALSE);
+
+   return qp_client->hint.scrollable;
+}
diff --git a/src/bin/services/e_service_quickpanel.h b/src/bin/services/e_service_quickpanel.h
new file mode 100644 (file)
index 0000000..d598975
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef E_SERVICE_QUICKPANEL_H
+#define E_SERVICE_QUICKPANEL_H
+
+#include "e_policy_private_data.h"
+
+EINTERN void          e_service_quickpanel_client_set(E_Client *ec);
+EINTERN E_Client     *e_service_quickpanel_client_get(void);
+EINTERN void          e_service_quickpanel_show(void);
+EINTERN void          e_service_quickpanel_hide(void);
+EINTERN Eina_Bool     e_service_quickpanel_region_set(int type, int angle, Eina_Tiler *tiler);
+EINTERN Evas_Object  *e_service_quickpanel_handler_object_add(E_Client *ec, int x, int y, int w, int h);
+EINTERN void          e_service_quickpanel_handler_object_del(Evas_Object *handler);
+
+EINTERN Eina_Bool    e_qp_visible_get(void);
+EINTERN int          e_qp_orientation_get(void);
+
+EINTERN void         e_qp_client_add(E_Client *ec);
+EINTERN void         e_qp_client_del(E_Client *ec);
+EINTERN void         e_qp_client_show(E_Client *ec);
+EINTERN void         e_qp_client_hide(E_Client *ec);
+EINTERN Eina_Bool    e_qp_client_scrollable_set(E_Client *ec, Eina_Bool set);
+EINTERN Eina_Bool    e_qp_client_scrollable_get(E_Client *ec);
+
+#endif
diff --git a/src/bin/services/e_service_region.c b/src/bin/services/e_service_region.c
new file mode 100644 (file)
index 0000000..331d23f
--- /dev/null
@@ -0,0 +1,202 @@
+#include "e.h"
+#include "services/e_service_region.h"
+
+/* FIXME: temporary use quickpanel to find out ui orientation */
+#include "services/e_service_quickpanel.h"
+
+#define ENTRY(...)                                 \
+   E_Policy_Region *region;                             \
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ro, EINA_FALSE); \
+   region = evas_object_data_get(ro, EO_DATA_KEY); \
+   if (EINA_UNLIKELY(!region))                     \
+     return __VA_ARGS__
+
+/* FIXME: Implementation for log that can access commonly */
+#ifdef INF
+#undef INF
+#endif
+
+#define INF(f, x...) NULL
+
+#define EO_DATA_KEY  "pol-region"
+
+struct _E_Policy_Region
+{
+   Evas_Object       *obj;
+   E_Policy_Gesture       *gesture;
+   Eina_List         *event_list;
+   Eina_Rectangle     geom[E_POLICY_ANGLE_MAP_NUM];
+   E_Policy_Angle_Map            rotation;
+};
+
+static void
+_region_rotation_set(E_Policy_Region *region, int angle)
+{
+   if (!e_policy_angle_valid_check(angle))
+     return;
+
+   region->rotation = e_policy_angle_map(angle);
+}
+
+static void
+_region_obj_geometry_update(E_Policy_Region *region)
+{
+   E_Policy_Angle_Map r;
+
+   r = region->rotation;
+
+   INF("Update Geometry: rotation %d x %d y %d w %d h %d",
+       e_policy_angle_get(r), region->geom[r].x, region->geom[r].y, region->geom[r].w, region->geom[r].h);
+
+   evas_object_geometry_set(region->obj,
+                            region->geom[r].x, region->geom[r].y,
+                            region->geom[r].w, region->geom[r].h);
+}
+
+static Eina_Bool
+_region_rotation_cb_change_end(void *data, int type, void *event)
+{
+   E_Policy_Region *region;
+   E_Event_Client *ev;
+   E_Client *ec;
+
+   region = data;
+   if (EINA_UNLIKELY(!region))
+     goto end;
+
+   ev = event;
+   if (EINA_UNLIKELY(!ev))
+     goto end;
+
+   ec = ev->ec;
+   if (EINA_UNLIKELY(!ec))
+     goto end;
+
+   if (e_service_quickpanel_client_get() != ec)
+     goto end;
+
+   _region_rotation_set(region, ec->e.state.rot.ang.curr);
+   _region_obj_geometry_update(region);
+
+end:
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_region_rotation_init(E_Policy_Region *region)
+{
+   E_Client *ec;
+
+   /* FIXME: temporary use quickpanel to find out ui orientation */
+   ec = e_service_quickpanel_client_get();
+   if (ec)
+     _region_rotation_set(region, ec->e.state.rot.ang.curr);
+
+   E_LIST_HANDLER_APPEND(region->event_list, E_EVENT_CLIENT_ROTATION_CHANGE_END, _region_rotation_cb_change_end, region);
+
+   return EINA_TRUE;
+}
+
+static void
+_region_free(E_Policy_Region *region)
+{
+   INF("Free Instant");
+   E_FREE_LIST(region->event_list, ecore_event_del);
+   E_FREE_FUNC(region->gesture, e_service_gesture_del);
+   E_FREE_FUNC(region->obj, evas_object_del);
+   free(region);
+}
+
+static void
+_region_object_cb_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
+{
+   E_Policy_Region *region;
+
+   region = data;
+   if (EINA_UNLIKELY(!region))
+     return;
+
+   _region_free(region);
+}
+
+EINTERN Evas_Object *
+e_service_region_object_new(void)
+{
+   E_Policy_Region *region;
+   Evas_Object *o;
+
+   INF("New Instant");
+
+   region = calloc(1, sizeof(*region));
+   if (!region)
+     return NULL;
+
+   o = evas_object_rectangle_add(e_comp->evas);
+   evas_object_color_set(o, 0, 0, 0, 0);
+   evas_object_repeat_events_set(o, EINA_TRUE);
+   region->obj = o;
+
+   if (!_region_rotation_init(region))
+     goto err_event;
+
+   evas_object_data_set(o, EO_DATA_KEY, region);
+   evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _region_object_cb_del, region);
+
+   return o;
+err_event:
+   evas_object_del(o);
+   free(region);
+
+   return NULL;
+}
+
+EINTERN Eina_Bool
+e_service_region_cb_set(Evas_Object *ro, E_Policy_Gesture_Start_Cb cb_start, E_Policy_Gesture_Move_Cb cb_move, E_Policy_Gesture_End_Cb cb_end, void *data)
+{
+   E_Policy_Gesture *gesture;
+
+   ENTRY(EINA_FALSE);
+
+   INF("Set Callback function");
+   if (!region->gesture)
+     {
+        gesture = e_service_gesture_add(ro, POL_GESTURE_TYPE_LINE);
+        if (!gesture)
+          return EINA_FALSE;
+
+        region->gesture = gesture;
+     }
+
+   e_service_gesture_cb_set(region->gesture, cb_start, cb_move, cb_end, data);
+
+   return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_service_region_rectangle_set(Evas_Object *ro, E_Policy_Angle_Map ridx, int x, int y, int w, int h)
+{
+   ENTRY(EINA_FALSE);
+
+   INF("Add Rectangle: a %d x %d y %d w %d h %d",
+       e_policy_angle_get(ridx), x, y, w, h);
+
+   EINA_RECTANGLE_SET(&region->geom[ridx], x, y, w, h);
+
+   if (ridx == region->rotation)
+     _region_obj_geometry_update(region);
+
+   return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_service_region_rectangle_get(Evas_Object *ro, E_Policy_Angle_Map ridx, int *x, int *y, int *w, int *h)
+{
+   ENTRY(EINA_FALSE);
+
+   if (x) *x = region->geom[ridx].x;
+   if (y) *y = region->geom[ridx].y;
+   if (w) *w = region->geom[ridx].w;
+   if (h) *h = region->geom[ridx].h;
+
+   return EINA_TRUE;
+}
diff --git a/src/bin/services/e_service_region.h b/src/bin/services/e_service_region.h
new file mode 100644 (file)
index 0000000..93aa469
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef E_SERVICE_REGION
+#define E_SERVICE_REGION
+
+#include "services/e_service_gesture.h"
+#include "e_policy_private_data.h"
+
+typedef struct _E_Policy_Region E_Policy_Region;
+
+EINTERN Evas_Object        *e_service_region_object_new(void);
+EINTERN Eina_Bool           e_service_region_rectangle_set(Evas_Object *ro, E_Policy_Angle_Map ridx, int x, int y, int w, int h);
+EINTERN Eina_Bool           e_service_region_rectangle_get(Evas_Object *ro, E_Policy_Angle_Map ridx, int *x, int *y, int *w, int *h);
+EINTERN Eina_Bool           e_service_region_cb_set(Evas_Object *ro, E_Policy_Gesture_Start_Cb cb_start, E_Policy_Gesture_Move_Cb cb_move, E_Policy_Gesture_End_Cb cb_end, void *data);
+
+#endif
diff --git a/src/bin/services/e_service_volume.c b/src/bin/services/e_service_volume.c
new file mode 100644 (file)
index 0000000..9c79e2a
--- /dev/null
@@ -0,0 +1,468 @@
+#include "e.h"
+#include "services/e_service_volume.h"
+
+#include <wayland-server.h>
+#include <tzsh_server.h>
+
+#define REGION_OBJS_FOREACH(l, o) \
+   EINA_LIST_FOREACH(_volume_region_objs[_volume_cur_angle_map], l, o)
+
+#define REGION_OBJS_VISIBLE_CHANGE(V) \
+do { \
+   Eina_List *l; \
+   Evas_Object *o; \
+   EINA_LIST_FOREACH(_volume_region_objs[_volume_cur_angle_map], l, o) \
+     { \
+        if (V) evas_object_show(o); \
+        else evas_object_hide(o); \
+     } \
+} while(0)
+#define REGION_OBJS_SHOW() REGION_OBJS_VISIBLE_CHANGE(EINA_TRUE)
+#define REGION_OBJS_HIDE() REGION_OBJS_VISIBLE_CHANGE(EINA_FALSE)
+
+/* private data for volume */
+static struct wl_resource  *_volume_wl_touch = NULL;
+static E_Client            *_volume_ec = NULL;
+static Eina_List           *_volume_region_objs[E_POLICY_ANGLE_MAP_NUM];
+static E_Policy_Angle_Map              _volume_cur_angle_map = E_POLICY_ANGLE_MAP_0;
+static Eina_Bool            _volume_ec_ev_init = EINA_FALSE;
+
+/* event handler */
+static Ecore_Event_Handler *_rot_handler = NULL;
+static E_Client_Hook       *_volume_del_hook = NULL;
+
+EINTERN E_Client *
+e_service_volume_client_get(void)
+{
+   return _volume_ec;
+}
+
+static void
+_volume_region_obj_cb_mouse_move(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
+{
+   Evas_Event_Mouse_Move *e = event;
+
+   wl_touch_send_motion(_volume_wl_touch, e->timestamp, 0, // id 0 for the 1st figner
+                        wl_fixed_from_int(e->cur.canvas.x - _volume_ec->client.x),
+                        wl_fixed_from_int(e->cur.canvas.y - _volume_ec->client.y));
+}
+
+static void
+_volume_region_obj_cb_mouse_down(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
+{
+   Evas_Event_Mouse_Down *e = event;
+   uint32_t serial;
+
+   serial = wl_display_next_serial(e_comp_wl->wl.disp);
+   wl_touch_send_down(_volume_wl_touch, serial, e->timestamp,
+                      _volume_ec->comp_data->surface, 0,
+                      wl_fixed_from_int(e->canvas.x - _volume_ec->client.x),
+                      wl_fixed_from_int(e->canvas.y - _volume_ec->client.y));
+}
+
+static void
+_volume_region_obj_cb_mouse_up(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
+{
+   Evas_Event_Mouse_Up *e = event;
+   uint32_t serial;
+
+   serial = wl_display_next_serial(e_comp_wl->wl.disp);
+   wl_touch_send_up(_volume_wl_touch, serial, e->timestamp, 0);
+}
+
+static void
+_volume_region_obj_cb_multi_down(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
+{
+   Evas_Event_Multi_Down *e = event;
+   uint32_t serial;
+
+   serial = wl_display_next_serial(e_comp_wl->wl.disp);
+   wl_touch_send_down(_volume_wl_touch, serial, e->timestamp,
+                      _volume_ec->comp_data->surface, e->device,
+                      wl_fixed_from_int(e->canvas.x - _volume_ec->client.x),
+                      wl_fixed_from_int(e->canvas.y - _volume_ec->client.y));
+}
+
+static void
+_volume_region_obj_cb_multi_up(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
+{
+   Evas_Event_Multi_Up *e = event;
+   uint32_t serial;
+
+   serial = wl_display_next_serial(e_comp_wl->wl.disp);
+   wl_touch_send_up(_volume_wl_touch, serial, e->timestamp, e->device);
+}
+
+static void
+_volume_region_obj_cb_multi_move(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
+{
+   Evas_Event_Multi_Move *e = event;
+
+   wl_touch_send_motion(_volume_wl_touch, e->timestamp, e->device,
+                        wl_fixed_from_int(e->cur.canvas.x - _volume_ec->client.x),
+                        wl_fixed_from_int(e->cur.canvas.y - _volume_ec->client.y));
+}
+
+static void
+_volume_client_evas_cb_show(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
+{
+   /* show region objects in current rotation */
+   REGION_OBJS_SHOW();
+}
+
+static void
+_volume_client_evas_cb_hide(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
+{
+   /* hide region objects in current rotation */
+   REGION_OBJS_HIDE();
+}
+
+static void
+_volume_client_evas_cb_move(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *volume_obj, void *event EINA_UNUSED)
+{
+   Eina_List *l;
+   Eina_Rectangle *r;
+   Evas_Object *region_obj;
+   int x, y;
+
+   REGION_OBJS_FOREACH(l, region_obj)
+     {
+        r = evas_object_data_get(region_obj, "content_rect");
+        if (EINA_UNLIKELY(r == NULL))
+          continue;
+
+        evas_object_geometry_get(volume_obj, &x, &y, NULL, NULL);
+        evas_object_move(region_obj, x + r->x, y + r->y);
+     }
+}
+
+static void
+_volume_client_evas_cb_restack(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
+{
+   Eina_List *l;
+   Evas_Object *region_obj;
+
+   REGION_OBJS_FOREACH(l, region_obj)
+      evas_object_stack_above(region_obj, _volume_ec->frame);
+}
+
+static Eina_Bool
+_region_objs_is_empty(void)
+{
+   int i;
+
+   for (i = E_POLICY_ANGLE_MAP_0; i < E_POLICY_ANGLE_MAP_NUM; i++)
+     {
+        if (_volume_region_objs[i])
+          return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+}
+
+static void
+_region_obj_del(Evas_Object *obj)
+{
+   Eina_Rectangle *r;
+
+   r = evas_object_data_get(obj, "content_rect");
+   E_FREE_FUNC(r, eina_rectangle_free);
+   evas_object_del(obj);
+}
+
+static void
+_region_objs_del(E_Policy_Angle_Map angle_map)
+{
+   Evas_Object *obj;
+
+   EINA_LIST_FREE(_volume_region_objs[angle_map], obj)
+      _region_obj_del(obj);
+
+   if ((_volume_ec_ev_init) &&
+       (_region_objs_is_empty()))
+     {
+        _volume_ec_ev_init = EINA_FALSE;
+
+        evas_object_event_callback_del(_volume_ec->frame, EVAS_CALLBACK_SHOW,
+                                       _volume_client_evas_cb_show);
+        evas_object_event_callback_del(_volume_ec->frame, EVAS_CALLBACK_HIDE,
+                                       _volume_client_evas_cb_hide);
+        evas_object_event_callback_del(_volume_ec->frame, EVAS_CALLBACK_MOVE,
+                                       _volume_client_evas_cb_move);
+        evas_object_event_callback_del(_volume_ec->frame, EVAS_CALLBACK_RESTACK,
+                                       _volume_client_evas_cb_restack);
+     }
+}
+
+static void
+_volume_client_unset(void)
+{
+   int i;
+
+   for (i = E_POLICY_ANGLE_MAP_0; i < E_POLICY_ANGLE_MAP_NUM; i++)
+     _region_objs_del(i);
+
+   E_FREE_FUNC(_rot_handler, ecore_event_handler_del);
+   E_FREE_FUNC(_volume_del_hook, e_client_hook_del);
+
+   _volume_wl_touch = NULL;
+   _volume_ec = NULL;
+}
+
+static void
+_volume_hook_client_del(void *d EINA_UNUSED, E_Client *ec)
+{
+   if (EINA_UNLIKELY(!ec)) return;
+   if (EINA_LIKELY(_volume_ec != ec)) return;
+
+   ELOGF("VOLUME","Del Client", ec->pixmap, ec);
+
+   _volume_client_unset();
+}
+
+static Eina_Bool
+_volume_client_cb_rot_done(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+   E_Event_Client_Rotation_Change_End *e = event;
+   E_Policy_Angle_Map new_idx;
+
+   if (EINA_UNLIKELY(e == NULL))
+     goto end;
+
+   new_idx = e_policy_angle_map(_volume_ec->e.state.rot.ang.curr);
+   if (EINA_UNLIKELY(new_idx == -1))
+     goto end;
+
+   if (e->ec != _volume_ec)
+     goto end;
+
+   /* is new rotation same with previous? */
+   if (_volume_cur_angle_map == new_idx)
+     goto end;
+
+   /* hide region object in current rotation */
+   REGION_OBJS_HIDE();
+
+   /* update current rotation */
+   _volume_cur_angle_map = new_idx;
+
+   /* show region object in current rotation */
+   REGION_OBJS_SHOW();
+
+end:
+   return ECORE_CALLBACK_RENEW;
+}
+
+EINTERN Eina_Bool
+e_service_volume_client_set(E_Client *ec)
+{
+   if (!ec)
+     {
+        if (_volume_ec)
+          _volume_client_unset();
+
+        return EINA_TRUE;
+     }
+
+   if (_volume_ec)
+     {
+        ERR("Volume client is already registered."
+            "Multi volume service is not supported.");
+        return EINA_FALSE;
+     }
+
+   if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
+
+   ELOGF("VOLUME","Set Client", ec->pixmap, ec);
+
+   _volume_ec = ec;
+   _volume_cur_angle_map = e_policy_angle_map(ec->e.state.rot.ang.curr);
+
+   /* repeat events for volume client. */
+   evas_object_repeat_events_set(ec->frame, EINA_TRUE);
+
+   _rot_handler =
+      ecore_event_handler_add(E_EVENT_CLIENT_ROTATION_CHANGE_END,
+                              (Ecore_Event_Handler_Cb)_volume_client_cb_rot_done,
+                              NULL);
+   _volume_del_hook =
+      e_client_hook_add(E_CLIENT_HOOK_DEL, _volume_hook_client_del, NULL);
+
+   // set volume layer
+   if (E_POLICY_VOLUME_LAYER != evas_object_layer_get(ec->frame))
+     {
+        evas_object_layer_set(ec->frame, E_POLICY_VOLUME_LAYER);
+     }
+   ec->layer = E_POLICY_VOLUME_LAYER;
+
+   // set skip iconify
+   ec->exp_iconify.skip_iconify = 1;
+
+   return EINA_TRUE;
+}
+
+static Evas_Object *
+_volume_content_region_obj_new(void)
+{
+   Evas_Object *obj;
+
+   obj = evas_object_rectangle_add(evas_object_evas_get(_volume_ec->frame));
+
+   /* make it transparent */
+   evas_object_color_set(obj, 0, 0, 0, 0);
+
+   /* set stack of obj object on the volume object. */
+   evas_object_layer_set(obj, evas_object_layer_get(_volume_ec->frame));
+   evas_object_stack_above(obj, _volume_ec->frame);
+
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
+                                  _volume_region_obj_cb_mouse_move, NULL);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
+                                  _volume_region_obj_cb_mouse_down, NULL);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
+                                  _volume_region_obj_cb_mouse_up, NULL);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_MULTI_DOWN,
+                                  _volume_region_obj_cb_multi_down, NULL);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_MULTI_UP,
+                                  _volume_region_obj_cb_multi_up, NULL);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_MULTI_MOVE,
+                                  _volume_region_obj_cb_multi_move, NULL);
+
+   return obj;
+}
+
+static void
+_region_objs_tile_set(E_Policy_Angle_Map angle_map, Eina_Tiler *tiler)
+{
+   Eina_List *objs_list, *l, *ll;
+   Eina_Iterator *it;
+   Eina_Rectangle *r, *cr;
+   Evas_Object *obj;
+
+   objs_list = _volume_region_objs[angle_map];
+   it = eina_tiler_iterator_new(tiler);
+   EINA_ITERATOR_FOREACH(it, r)
+     {
+        /* trying to reuse allocated object */
+        obj = eina_list_data_get(objs_list);
+        if (obj)
+          {
+             objs_list = eina_list_next(objs_list);
+             cr = evas_object_data_get(obj, "content_rect");
+             E_FREE_FUNC(cr, eina_rectangle_free);
+          }
+        else
+          {
+             obj = _volume_content_region_obj_new();
+             _volume_region_objs[angle_map] = eina_list_append(_volume_region_objs[angle_map], obj);
+          }
+
+        INF("\t@@@@@ Region Set: %d %d %d %d", r->x, r->y, r->w, r->h);
+        /* set geometry of region object */
+        evas_object_move(obj, _volume_ec->client.x + r->x, _volume_ec->client.y + r->y);
+        evas_object_resize(obj, r->w, r->h);
+
+        /* store the value of reigon as a region object's data */
+        cr = eina_rectangle_new(r->x, r->y, r->w, r->h);
+        evas_object_data_set(obj, "content_rect", cr);
+
+        if (angle_map == _volume_cur_angle_map)
+          {
+             if (evas_object_visible_get(_volume_ec->frame))
+               evas_object_show(obj);
+          }
+     }
+   eina_iterator_free(it);
+
+   /* delete rest of objects after reusing */
+   EINA_LIST_FOREACH_SAFE(objs_list, l, ll, obj)
+     {
+        _region_obj_del(obj);
+        _volume_region_objs[angle_map] =
+           eina_list_remove_list(_volume_region_objs[angle_map], l);
+     }
+}
+
+static void
+_volume_content_region_set(E_Policy_Angle_Map angle_map, Eina_Tiler *tiler)
+{
+   if (!tiler)
+     {
+        _region_objs_del(angle_map);
+        return;
+     }
+
+   _region_objs_tile_set(angle_map, tiler);
+}
+
+static struct wl_resource *
+_volume_wl_touch_resource_get(void)
+{
+   Eina_List *l;
+   struct wl_client *wc;
+   struct wl_resource *res;
+
+   if (_volume_wl_touch) goto end;
+
+   wc = wl_resource_get_client(_volume_ec->comp_data->surface);
+   EINA_LIST_FOREACH(e_comp_wl->touch.resources, l, res)
+     {
+        if (wl_resource_get_client(res) != wc) continue;
+
+        _volume_wl_touch = res;
+        goto end;
+     }
+
+end:
+   return _volume_wl_touch;
+}
+
+EINTERN Eina_Bool
+e_service_volume_region_set(int type, int angle, Eina_Tiler *tiler)
+{
+   E_Policy_Angle_Map angle_map;
+
+   if (EINA_UNLIKELY(!_volume_ec))
+     {
+        ERR("No registered volume client");
+        return EINA_FALSE;
+     }
+
+   angle_map = e_policy_angle_map(angle);
+   if (EINA_UNLIKELY(angle_map == -1))
+     return EINA_FALSE;
+
+   /* FIXME: use enum instead of constant */
+   if (EINA_UNLIKELY(type != 1))
+     {
+        ERR("Not supported region type %d", type);
+        return EINA_FALSE;
+     }
+
+   if (EINA_UNLIKELY(_volume_wl_touch_resource_get() == NULL))
+     {
+        ERR("Could not found wl_touch resource for volume");
+        return EINA_FALSE;
+     }
+
+   ELOGF("VOLUME","Content Region Set: angle %d, tiler %p",
+         NULL, NULL, angle, tiler);
+
+   _volume_content_region_set(angle_map, tiler);
+
+   if (!_volume_ec_ev_init)
+     {
+        _volume_ec_ev_init = EINA_TRUE;
+
+        evas_object_event_callback_add(_volume_ec->frame, EVAS_CALLBACK_SHOW,
+                                       _volume_client_evas_cb_show, NULL);
+        evas_object_event_callback_add(_volume_ec->frame, EVAS_CALLBACK_HIDE,
+                                       _volume_client_evas_cb_hide, NULL);
+        evas_object_event_callback_add(_volume_ec->frame, EVAS_CALLBACK_MOVE,
+                                       _volume_client_evas_cb_move, NULL);
+        evas_object_event_callback_add(_volume_ec->frame, EVAS_CALLBACK_RESTACK,
+                                       _volume_client_evas_cb_restack, NULL);
+     }
+
+   return EINA_TRUE;
+}
diff --git a/src/bin/services/e_service_volume.h b/src/bin/services/e_service_volume.h
new file mode 100644 (file)
index 0000000..7df57e4
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef E_SERVICE_VOLUME_H
+#define E_SERVICE_VOLUME_H
+
+#include <e.h>
+#include "e_policy_private_data.h"
+
+EINTERN Eina_Bool     e_service_volume_client_set(E_Client *ec);
+EINTERN E_Client     *e_service_volume_client_get(void);
+EINTERN Eina_Bool     e_service_volume_region_set(int region_type, int angle, Eina_Tiler *tiler);
+
+#endif /* E_SERVICE_VOLUME_H */