e_devicemgr: import devicemgr module to enlightenment core 15/188015/5
authorJengHyun Kang <jhyuni.kang@samsung.com>
Thu, 30 Aug 2018 09:39:01 +0000 (18:39 +0900)
committerJengHyun Kang <jhyuni.kang@samsung.com>
Wed, 5 Sep 2018 08:16:32 +0000 (17:16 +0900)
Change-Id: If7d9a33e173d24e71ef4ae252ce9382a7f206fa4

17 files changed:
src/bin/Makefile.mk
src/bin/e_comp_screen.c
src/bin/e_comp_wl.c
src/bin/e_comp_wl.h
src/bin/e_comp_wl_input.c
src/bin/e_devicemgr.c [new file with mode: 0644]
src/bin/e_devicemgr.h [new file with mode: 0644]
src/bin/e_devicemgr_block.c [new file with mode: 0644]
src/bin/e_devicemgr_conf.c [new file with mode: 0644]
src/bin/e_devicemgr_input.c [new file with mode: 0644]
src/bin/e_devicemgr_inputgen.c [new file with mode: 0644]
src/bin/e_devicemgr_private.h [new file with mode: 0644]
src/bin/e_devicemgr_wl.c [new file with mode: 0644]
src/bin/e_includes.h
src/bin/e_info_client.c
src/bin/e_info_server.c
src/bin/e_main.c

index 82fef0c..8e12366 100644 (file)
@@ -129,7 +129,9 @@ src/bin/e_keyrouter_private.h \
 src/bin/e_gesture.h \
 src/bin/e_input.h \
 src/bin/e_dbus_conn.h \
-src/bin/e_xdg_shell_v6.h
+src/bin/e_xdg_shell_v6.h \
+src/bin/e_devicemgr.h \
+src/bin/e_devicemgr_private.h
 
 enlightenment_src = \
 src/bin/e_actions.c \
@@ -243,7 +245,13 @@ src/bin/e_input_inputs.c \
 src/bin/e_input_device.c \
 src/bin/e_input_evdev.c \
 src/bin/e_dbus_conn.c \
-src/bin/e_xdg_shell_v6.c
+src/bin/e_xdg_shell_v6.c \
+src/bin/e_devicemgr.c \
+src/bin/e_devicemgr_conf.c \
+src/bin/e_devicemgr_block.c \
+src/bin/e_devicemgr_input.c \
+src/bin/e_devicemgr_inputgen.c \
+src/bin/e_devicemgr_wl.c
 
 src_bin_enlightenment_CPPFLAGS = $(E_CPPFLAGS) -DEFL_BETA_API_SUPPORT -DEFL_EO_API_SUPPORT -DE_LOGGING=1 @WAYLAND_CFLAGS@ $(TTRACE_CFLAGS) $(DLOG_CFLAGS) $(PIXMAN_CFLAGS) $(POLICY_CFLAGS) @TIZEN_REMOTE_SURFACE_CFLAGS@
 if HAVE_LIBGOMP
index bbbf560..c4bc318 100644 (file)
@@ -288,7 +288,7 @@ _e_comp_screen_pointer_renew(E_Input_Event_Input_Device_Del *ev)
 {
      if ((e_comp_wl->ptr.num_devices == 0) && e_comp_wl->ptr.ec && e_comp_wl->ptr.ec->pointer_enter_sent)
      {
-        if (e_comp_wl->input_device_manager.last_device_ptr)
+        if (e_devicemgr->last_device_ptr)
           {
              Evas_Device *last_ptr = NULL, *dev;
              Eina_List *list, *l;
@@ -302,9 +302,9 @@ _e_comp_screen_pointer_renew(E_Input_Event_Input_Device_Del *ev)
                   description = evas_device_description_get(dev);
 
                   if (!name || !description) continue;
-                  if ((!strncmp(name, e_comp_wl->input_device_manager.last_device_ptr->name, strlen(e_comp_wl->input_device_manager.last_device_ptr->name))) &&
-                      (!strncmp(description, e_comp_wl->input_device_manager.last_device_ptr->identifier, strlen(e_comp_wl->input_device_manager.last_device_ptr->identifier))) &&
-                      (evas_device_class_get(dev) == (Evas_Device_Class)e_comp_wl->input_device_manager.last_device_ptr->clas))
+                  if ((!strncmp(name, e_devicemgr->last_device_ptr->name, strlen(e_devicemgr->last_device_ptr->name))) &&
+                      (!strncmp(description, e_devicemgr->last_device_ptr->identifier, strlen(e_devicemgr->last_device_ptr->identifier))) &&
+                      (evas_device_class_get(dev) == (Evas_Device_Class)e_devicemgr->last_device_ptr->clas))
                     {
                        last_ptr = dev;
                        break;
index 520feb2..b479538 100644 (file)
@@ -611,17 +611,17 @@ _e_comp_wl_evas_cb_restack(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EIN
    e_comp_wl_subsurface_stack_update(ec);
 }
 
-static E_Comp_Wl_Input_Device *
+static E_Devicemgr_Input_Device *
 _e_comp_wl_device_last_device_get(Ecore_Device_Class dev_class)
 {
    switch (dev_class)
      {
       case ECORE_DEVICE_CLASS_MOUSE:
-         return e_comp_wl->input_device_manager.last_device_ptr;
+         return e_devicemgr->last_device_ptr;
       case ECORE_DEVICE_CLASS_KEYBOARD:
-         return e_comp_wl->input_device_manager.last_device_kbd;
+         return e_devicemgr->last_device_kbd;
       case ECORE_DEVICE_CLASS_TOUCH:
-         return e_comp_wl->input_device_manager.last_device_touch;
+         return e_devicemgr->last_device_touch;
       default:
          return NULL;;
      }
@@ -629,25 +629,25 @@ _e_comp_wl_device_last_device_get(Ecore_Device_Class dev_class)
 }
 
 static void
-_e_comp_wl_device_last_device_set(Ecore_Device_Class dev_class, E_Comp_Wl_Input_Device *device)
+_e_comp_wl_device_last_device_set(Ecore_Device_Class dev_class, E_Devicemgr_Input_Device *device)
 {
    switch (dev_class)
      {
       case ECORE_DEVICE_CLASS_MOUSE:
-         e_comp_wl->input_device_manager.last_device_ptr = device;
+         e_devicemgr->last_device_ptr = device;
          break;
       case ECORE_DEVICE_CLASS_KEYBOARD:
-         e_comp_wl->input_device_manager.last_device_kbd = device;
+         e_devicemgr->last_device_kbd = device;
          break;
       case ECORE_DEVICE_CLASS_TOUCH:
-         e_comp_wl->input_device_manager.last_device_touch = device;
+         e_devicemgr->last_device_touch = device;
          break;
       default:
          break;
      }
 }
 
-static E_Comp_Wl_Input_Device *
+static E_Devicemgr_Input_Device *
 _e_comp_wl_device_client_last_device_get(E_Client *ec, Ecore_Device_Class dev_class)
 {
    switch (dev_class)
@@ -665,7 +665,7 @@ _e_comp_wl_device_client_last_device_get(E_Client *ec, Ecore_Device_Class dev_cl
 }
 
 static void
-_e_comp_wl_device_client_last_device_set(E_Client *ec, Ecore_Device_Class dev_class, E_Comp_Wl_Input_Device *device)
+_e_comp_wl_device_client_last_device_set(E_Client *ec, Ecore_Device_Class dev_class, E_Devicemgr_Input_Device *device)
 {
    switch (dev_class)
      {
@@ -686,7 +686,7 @@ _e_comp_wl_device_client_last_device_set(E_Client *ec, Ecore_Device_Class dev_cl
 static void
 _e_comp_wl_device_send_event_device(E_Client *ec, Evas_Device *dev, uint32_t timestamp)
 {
-   E_Comp_Wl_Input_Device *last_device, *ec_last_device, *input_dev;
+   E_Devicemgr_Input_Device *last_device, *ec_last_device, *input_dev;
    struct wl_resource *dev_res;
    const char *dev_name;
    Ecore_Device_Class dev_class;
@@ -710,7 +710,7 @@ _e_comp_wl_device_send_event_device(E_Client *ec, Evas_Device *dev, uint32_t tim
 
    serial = wl_display_next_serial(e_comp_wl->wl.disp);
    wc = wl_resource_get_client(ec->comp_data->surface);
-   EINA_LIST_FOREACH(e_comp_wl->input_device_manager.device_list, l, input_dev)
+   EINA_LIST_FOREACH(e_devicemgr->device_list, l, input_dev)
      {
         if (!eina_streq(input_dev->identifier, dev_name) || (input_dev->clas != dev_class)) continue;
         if ((!last_device) || (last_device != input_dev) || (!ec_last_device) || (ec_last_device != input_dev))
@@ -730,7 +730,7 @@ _e_comp_wl_device_send_event_device(E_Client *ec, Evas_Device *dev, uint32_t tim
 static void
 _e_comp_wl_device_send_last_event_device(E_Client *ec, Ecore_Device_Class dev_class, uint32_t timestamp)
 {
-   E_Comp_Wl_Input_Device *last_device;
+   E_Devicemgr_Input_Device *last_device;
    struct wl_resource *dev_res;
    struct wl_client *wc;
    uint32_t serial;
@@ -755,7 +755,7 @@ _e_comp_wl_device_send_last_event_device(E_Client *ec, Ecore_Device_Class dev_cl
  static void
 _e_comp_wl_send_event_device(struct wl_client *wc, uint32_t timestamp, Ecore_Device *dev, uint32_t serial)
 {
-   E_Comp_Wl_Input_Device *input_dev;
+   E_Devicemgr_Input_Device *input_dev;
    struct wl_resource *dev_res;
    const char *dev_name;
    Eina_List *l, *ll;
@@ -764,7 +764,7 @@ _e_comp_wl_send_event_device(struct wl_client *wc, uint32_t timestamp, Ecore_Dev
 
    dev_name = ecore_device_identifier_get(dev);
 
-   EINA_LIST_FOREACH(e_comp_wl->input_device_manager.device_list, l, input_dev)
+   EINA_LIST_FOREACH(e_devicemgr->device_list, l, input_dev)
      {
         if (!eina_streq(input_dev->identifier, dev_name)) continue;
         _e_comp_wl_device_last_device_set(ecore_device_class_get(dev), input_dev);
@@ -821,7 +821,7 @@ _e_comp_wl_cursor_timer(void *data)
 static void
 _e_comp_wl_device_send_axis(const char *dev_name, Evas_Device_Class dev_class, E_Client *ec, enum tizen_input_device_axis_type axis_type, double value)
 {
-   E_Comp_Wl_Input_Device *input_dev;
+   E_Devicemgr_Input_Device *input_dev;
    struct wl_resource *dev_res;
    struct wl_client *wc;
    Eina_List *l, *ll;
@@ -834,7 +834,7 @@ _e_comp_wl_device_send_axis(const char *dev_name, Evas_Device_Class dev_class, E
    f_value = wl_fixed_from_double(value);
    wc = wl_resource_get_client(ec->comp_data->surface);
 
-   EINA_LIST_FOREACH(e_comp_wl->input_device_manager.device_list, l, input_dev)
+   EINA_LIST_FOREACH(e_devicemgr->device_list, l, input_dev)
      {
         if ((strcmp(input_dev->identifier, dev_name)) || (input_dev->clas != (Ecore_Device_Class)dev_class)) continue;
         EINA_LIST_FOREACH(input_dev->resources, ll, dev_res)
@@ -849,13 +849,13 @@ static void
 _e_comp_wl_device_renew_axis(const char *dev_name, Evas_Device_Class dev_class, E_Client *ec, unsigned int idx, double radius_x, double radius_y, double pressure, double angle)
 {
    _e_comp_wl_device_send_axis(dev_name, dev_class, ec, TIZEN_INPUT_DEVICE_AXIS_TYPE_RADIUS_X, radius_x);
-   e_comp_wl->input_device_manager.multi[idx].radius_x = radius_x;
+   e_devicemgr->multi[idx].radius_x = radius_x;
    _e_comp_wl_device_send_axis(dev_name, dev_class, ec, TIZEN_INPUT_DEVICE_AXIS_TYPE_RADIUS_Y, radius_y);
-   e_comp_wl->input_device_manager.multi[idx].radius_y = radius_y;
+   e_devicemgr->multi[idx].radius_y = radius_y;
    _e_comp_wl_device_send_axis(dev_name, dev_class, ec, TIZEN_INPUT_DEVICE_AXIS_TYPE_PRESSURE, pressure);
-   e_comp_wl->input_device_manager.multi[idx].pressure = pressure;
+   e_devicemgr->multi[idx].pressure = pressure;
    _e_comp_wl_device_send_axis(dev_name, dev_class, ec, TIZEN_INPUT_DEVICE_AXIS_TYPE_ANGLE, angle);
-   e_comp_wl->input_device_manager.multi[idx].angle = angle;
+   e_devicemgr->multi[idx].angle = angle;
 }
 
 static void
@@ -863,25 +863,25 @@ _e_comp_wl_device_handle_axes(const char *dev_name, Evas_Device_Class dev_class,
 {
    if (idx >= E_COMP_WL_TOUCH_MAX) return;
 
-   if (e_comp_wl->input_device_manager.multi[idx].radius_x != radius_x)
+   if (e_devicemgr->multi[idx].radius_x != radius_x)
      {
         _e_comp_wl_device_send_axis(dev_name, dev_class, ec, TIZEN_INPUT_DEVICE_AXIS_TYPE_RADIUS_X, radius_x);
-        e_comp_wl->input_device_manager.multi[idx].radius_x = radius_x;
+        e_devicemgr->multi[idx].radius_x = radius_x;
      }
-   if (e_comp_wl->input_device_manager.multi[idx].radius_y != radius_y)
+   if (e_devicemgr->multi[idx].radius_y != radius_y)
      {
         _e_comp_wl_device_send_axis(dev_name, dev_class, ec, TIZEN_INPUT_DEVICE_AXIS_TYPE_RADIUS_Y, radius_y);
-        e_comp_wl->input_device_manager.multi[idx].radius_y = radius_y;
+        e_devicemgr->multi[idx].radius_y = radius_y;
      }
-   if (e_comp_wl->input_device_manager.multi[idx].pressure != pressure)
+   if (e_devicemgr->multi[idx].pressure != pressure)
      {
         _e_comp_wl_device_send_axis(dev_name, dev_class, ec, TIZEN_INPUT_DEVICE_AXIS_TYPE_PRESSURE, pressure);
-        e_comp_wl->input_device_manager.multi[idx].pressure = pressure;
+        e_devicemgr->multi[idx].pressure = pressure;
      }
-   if (e_comp_wl->input_device_manager.multi[idx].angle != angle)
+   if (e_devicemgr->multi[idx].angle != angle)
      {
         _e_comp_wl_device_send_axis(dev_name, dev_class, ec, TIZEN_INPUT_DEVICE_AXIS_TYPE_ANGLE, angle);
-        e_comp_wl->input_device_manager.multi[idx].angle = angle;
+        e_devicemgr->multi[idx].angle = angle;
      }
 }
 
@@ -5755,7 +5755,7 @@ e_comp_wl_touch_send(E_Client *ec, int idx, int x, int y, Eina_Bool pressed, Eco
 {
    struct wl_client *wc;
    uint32_t serial;
-   E_Comp_Wl_Input_Device *device = NULL;
+   E_Devicemgr_Input_Device *device = NULL;
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, EINA_FALSE);
@@ -5790,7 +5790,7 @@ e_comp_wl_touch_send(E_Client *ec, int idx, int x, int y, Eina_Bool pressed, Eco
 EINTERN Eina_Bool
 e_comp_wl_touch_update_send(E_Client *ec, int idx, int x, int y, Ecore_Device *dev, double radius_x, double radius_y, double pressure, double angle, uint32_t time)
 {
-   E_Comp_Wl_Input_Device *device;
+   E_Devicemgr_Input_Device *device;
    uint32_t serial;
    struct wl_client *wc;
 
index 1e69ab0..1ad68a7 100644 (file)
@@ -44,9 +44,7 @@ typedef struct _E_Comp_Wl_Surface_State E_Comp_Wl_Surface_State;
 typedef struct _E_Comp_Wl_Client_Data E_Comp_Wl_Client_Data;
 typedef struct _E_Comp_Wl_Data E_Comp_Wl_Data;
 typedef struct _E_Comp_Wl_Output E_Comp_Wl_Output;
-typedef struct _E_Comp_Wl_Input_Device E_Comp_Wl_Input_Device;
 typedef struct _E_Comp_Wl_Hook E_Comp_Wl_Hook;
-typedef struct _E_Comp_Wl_Input_Device_Multi E_Comp_Wl_Input_Device_Multi;
 
 
 typedef enum _E_Comp_Wl_Buffer_Type
@@ -172,23 +170,6 @@ struct _E_Comp_Wl_Subsurf_Data
      } remote_surface;
 };
 
-struct _E_Comp_Wl_Input_Device
-{
-   Eina_List *resources;
-   const char *name;
-   const char *identifier;
-   Ecore_Device_Class clas;
-   Ecore_Device_Subclass subclas;
-};
-
-struct _E_Comp_Wl_Input_Device_Multi
-{
-   double radius_x;
-   double radius_y;
-   double pressure;
-   double angle;
-};
-
 struct _E_Comp_Wl_Data
 {
    struct
@@ -228,17 +209,6 @@ struct _E_Comp_Wl_Data
 
    struct
      {
-        struct wl_global *global;
-        Eina_List *resources;
-        Eina_List *device_list;
-        E_Comp_Wl_Input_Device *last_device_ptr;
-        E_Comp_Wl_Input_Device *last_device_touch;
-        E_Comp_Wl_Input_Device *last_device_kbd;
-        E_Comp_Wl_Input_Device_Multi multi[E_COMP_WL_TOUCH_MAX];
-     } input_device_manager;
-
-   struct
-     {
         Eina_List *resources;
         Eina_List *focused;
         Eina_Bool enabled : 1;
@@ -491,9 +461,9 @@ struct _E_Comp_Wl_Client_Data
       unsigned char layer : 1;
    } fetch;
 
-   E_Comp_Wl_Input_Device *last_device_ptr;
-   E_Comp_Wl_Input_Device *last_device_touch;
-   E_Comp_Wl_Input_Device *last_device_kbd;
+   E_Devicemgr_Input_Device *last_device_ptr;
+   E_Devicemgr_Input_Device *last_device_touch;
+   E_Devicemgr_Input_Device *last_device_kbd;
 
    E_Util_Transform *viewport_transform;
 
index fae385b..fc2a9b1 100644 (file)
@@ -199,9 +199,9 @@ _e_comp_wl_input_cb_pointer_get(struct wl_client *client, struct wl_resource *re
                   desc = evas_device_description_get(dev);
                   if (!name || !desc) continue;
 
-                  if ((!strncmp(name, e_comp_wl->input_device_manager.last_device_ptr->name, strlen(e_comp_wl->input_device_manager.last_device_ptr->name))) &&
-                      (!strncmp(desc, e_comp_wl->input_device_manager.last_device_ptr->identifier, strlen(e_comp_wl->input_device_manager.last_device_ptr->identifier))) &&
-                      (evas_device_class_get(dev) == (Evas_Device_Class)e_comp_wl->input_device_manager.last_device_ptr->clas))
+                  if ((!strncmp(name, e_devicemgr->last_device_ptr->name, strlen(e_devicemgr->last_device_ptr->name))) &&
+                      (!strncmp(desc, e_devicemgr->last_device_ptr->identifier, strlen(e_devicemgr->last_device_ptr->identifier))) &&
+                      (evas_device_class_get(dev) == (Evas_Device_Class)e_devicemgr->last_device_ptr->clas))
                     {
                        last_ptr = dev;
                        break;
diff --git a/src/bin/e_devicemgr.c b/src/bin/e_devicemgr.c
new file mode 100644 (file)
index 0000000..3e92213
--- /dev/null
@@ -0,0 +1,180 @@
+//#include "e.h"
+#include "e_devicemgr_private.h"
+
+E_API E_Devicemgr *e_devicemgr;
+
+static int _e_devicemgr_intercept_hooks_delete = 0;
+static int _e_devicemgr_intercept_hooks_walking = 0;
+
+static Eina_Inlist *_e_devicemgr_intercept_hooks[] =
+{
+   [E_DEVICEMGR_INTERCEPT_HOOK_DETENT] = NULL,
+};
+
+int _devicemgr_log_dom = -1;
+
+E_API E_Devicemgr_Intercept_Hook *
+e_devicemgr_intercept_hook_add(E_Devicemgr_Intercept_Hook_Point hookpoint, E_Devicemgr_Intercept_Hook_Cb func, const void *data)
+{
+   E_Devicemgr_Intercept_Hook *ch;
+
+   EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint < 0 || hookpoint >= E_DEVICEMGR_INTERCEPT_HOOK_LAST,
+                                  EINA_FALSE);
+
+   ch = E_NEW(E_Devicemgr_Intercept_Hook, 1);
+   if (!ch) return NULL;
+   ch->hookpoint = hookpoint;
+   ch->func = func;
+   ch->data = (void*)data;
+   _e_devicemgr_intercept_hooks[hookpoint] = eina_inlist_append(_e_devicemgr_intercept_hooks[hookpoint], EINA_INLIST_GET(ch));
+   return ch;
+}
+
+E_API void
+e_devicemgr_intercept_hook_del(E_Devicemgr_Intercept_Hook *ch)
+{
+   EINA_SAFETY_ON_NULL_RETURN(ch);
+
+   ch->delete_me = 1;
+   if (_e_devicemgr_intercept_hooks_walking == 0)
+     {
+        _e_devicemgr_intercept_hooks[ch->hookpoint] = eina_inlist_remove(_e_devicemgr_intercept_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
+        free(ch);
+     }
+   else
+     _e_devicemgr_intercept_hooks_delete++;
+}
+
+static void
+_e_devicemgr_intercept_hooks_clean(void)
+{
+   Eina_Inlist *l;
+   E_Devicemgr_Intercept_Hook *ch;
+   unsigned int x;
+   for (x = 0; x < E_DEVICEMGR_INTERCEPT_HOOK_LAST; x++)
+     EINA_INLIST_FOREACH_SAFE(_e_devicemgr_intercept_hooks[x], l, ch)
+       {
+          if (!ch->delete_me) continue;
+          _e_devicemgr_intercept_hooks[x] = eina_inlist_remove(_e_devicemgr_intercept_hooks[x], EINA_INLIST_GET(ch));
+         free(ch);
+       }
+}
+
+E_API Eina_Bool
+e_devicemgr_intercept_hook_call(E_Devicemgr_Intercept_Hook_Point hookpoint, void *event)
+{
+   E_Devicemgr_Intercept_Hook *ch;
+   Eina_Bool res = EINA_TRUE, ret = EINA_TRUE;
+
+   EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint < 0 || hookpoint >= E_DEVICEMGR_INTERCEPT_HOOK_LAST,
+                                  EINA_FALSE);
+
+   _e_devicemgr_intercept_hooks_walking++;
+   EINA_INLIST_FOREACH(_e_devicemgr_intercept_hooks[hookpoint], ch)
+     {
+        if (ch->delete_me) continue;
+        res = ch->func(ch->data, hookpoint, event);
+        if (!res) ret = EINA_FALSE;
+     }
+   _e_devicemgr_intercept_hooks_walking--;
+   if ((_e_devicemgr_intercept_hooks_walking == 0) && (_e_devicemgr_intercept_hooks_delete > 0))
+     _e_devicemgr_intercept_hooks_clean();
+
+   return ret;
+}
+
+E_API Eina_Bool
+e_devicemgr_is_blocking_event(Ecore_Device_Class clas)
+{
+   unsigned int dev_clas = 0x0;
+
+   switch (clas)
+     {
+        case ECORE_DEVICE_CLASS_KEYBOARD:
+          dev_clas = TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD;
+          break;
+        case ECORE_DEVICE_CLASS_MOUSE:
+          dev_clas = TIZEN_INPUT_DEVICE_MANAGER_CLAS_MOUSE;
+          break;
+        case ECORE_DEVICE_CLASS_TOUCH:
+          dev_clas = TIZEN_INPUT_DEVICE_MANAGER_CLAS_TOUCHSCREEN;
+          break;
+        default:
+          return EINA_FALSE;
+     }
+
+   if (e_devicemgr->block.devtype & dev_clas)
+     return EINA_TRUE;
+
+   return EINA_FALSE;
+}
+
+E_API int
+e_devicemgr_init(void)
+{
+   E_Devicemgr_Config_Data *dconfig = NULL;
+   Eina_Bool res = EINA_FALSE;
+
+   EINA_SAFETY_ON_NULL_GOTO(e_comp, failed);
+
+   _devicemgr_log_dom = eina_log_domain_register("e-devicemgr", EINA_COLOR_BLUE);
+   EINA_SAFETY_ON_FALSE_GOTO(_devicemgr_log_dom >= 0, failed);
+   eina_log_domain_level_set("e-devicemgr", EINA_LOG_LEVEL_INFO);
+
+   e_devicemgr = E_NEW(E_Devicemgr, 1);
+   EINA_SAFETY_ON_NULL_GOTO(e_devicemgr, failed);
+
+   dconfig = E_NEW(E_Devicemgr_Config_Data, 1);
+   EINA_SAFETY_ON_NULL_GOTO(dconfig, failed);
+
+   e_devicemgr_conf_init(dconfig);
+   e_devicemgr->dconfig = dconfig;
+
+   res = e_devicemgr_wl_init();
+   EINA_SAFETY_ON_FALSE_GOTO(res, wl_failed);
+
+   res = e_devicemgr_input_init();
+   EINA_SAFETY_ON_FALSE_GOTO(res, input_failed);
+
+   return EINA_TRUE;
+
+input_failed:
+   e_devicemgr_input_shutdown();
+
+wl_failed:
+   e_devicemgr_wl_shutdown();
+
+failed:
+   if (e_devicemgr)
+     {
+
+        if (e_devicemgr->dconfig)
+          {
+             e_devicemgr_conf_fini(e_devicemgr->dconfig);
+             E_FREE(e_devicemgr->dconfig);
+             e_devicemgr->dconfig = NULL;
+          }
+
+        E_FREE(e_devicemgr);
+        e_devicemgr = NULL;
+     }
+   eina_log_domain_unregister(_devicemgr_log_dom);
+   _devicemgr_log_dom = -1;
+   return EINA_FALSE;
+}
+
+E_API int
+e_devicemgr_shutdown(void)
+{
+   eina_log_domain_unregister(_devicemgr_log_dom);
+   _devicemgr_log_dom = -1;
+   if (e_devicemgr->dconfig)
+     {
+        e_devicemgr_conf_fini(e_devicemgr->dconfig);
+        E_FREE(e_devicemgr->dconfig);
+        e_devicemgr->dconfig = NULL;
+     }
+   E_FREE(e_devicemgr);
+   return EINA_TRUE;
+}
+
diff --git a/src/bin/e_devicemgr.h b/src/bin/e_devicemgr.h
new file mode 100644 (file)
index 0000000..00bd6e1
--- /dev/null
@@ -0,0 +1,106 @@
+#ifdef E_TYPEDEFS
+
+typedef enum _E_Devicemgr_Intercept_Hook_Point
+{
+   E_DEVICEMGR_INTERCEPT_HOOK_DETENT,
+   E_DEVICEMGR_INTERCEPT_HOOK_LAST
+} E_Devicemgr_Intercept_Hook_Point;
+
+typedef Eina_Bool (*E_Devicemgr_Intercept_Hook_Cb) (void *data, int point, void *event);
+typedef struct _E_Devicemgr_Intercept_Hook E_Devicemgr_Intercept_Hook;
+
+typedef struct _E_Devicemgr_Conf_Edd E_Devicemgr_Conf_Edd;
+typedef struct _E_Devicemgr_Config_Data E_Devicemgr_Config_Data;
+typedef struct _E_Devicemgr_Wl_Data E_Devicemgr_Wl_Data;
+
+typedef struct _E_Devicemgr_Input_Device
+{
+   Eina_List *resources;
+   const char *name;
+   const char *identifier;
+   Ecore_Device_Class clas;
+   Ecore_Device_Subclass subclas;
+} E_Devicemgr_Input_Device;
+
+typedef struct _E_Devicemgr_Input_Device_Multi
+{
+   double radius_x;
+   double radius_y;
+   double pressure;
+   double angle;
+} E_Devicemgr_Input_Device_Multi;
+
+typedef struct _E_Devicemgr E_Devicemgr;
+
+#else
+#ifndef E_DEVICEMGR_H
+#define E_DEVICEMGR_H
+
+extern E_API E_Devicemgr *e_devicemgr;
+
+struct _E_Devicemgr
+{
+   E_Devicemgr_Config_Data *dconfig;
+   E_Devicemgr_Wl_Data *wl_data;
+
+   Ecore_Event_Filter *ev_filter;
+   Eina_List *handlers;
+
+   Eina_List *device_list;
+   E_Devicemgr_Input_Device *last_device_ptr;
+   E_Devicemgr_Input_Device *last_device_touch;
+   E_Devicemgr_Input_Device *last_device_kbd;
+   E_Devicemgr_Input_Device_Multi multi[E_COMP_WL_TOUCH_MAX];
+
+   struct
+     {
+        unsigned int devtype;
+        struct wl_client *client;
+        Ecore_Timer *duration_timer;
+     } block;
+
+   Eina_List *pressed_keys;
+   unsigned int pressed_button;
+   unsigned int pressed_finger;
+
+   int virtual_key_device_fd;
+   int virtual_mouse_device_fd;
+
+   struct
+   {
+      Eina_List *kbd_list;
+      Eina_List *ptr_list;
+      Eina_List *touch_list;
+
+      Eina_List *resource_list;
+   } inputgen;
+
+   struct
+   {
+      char *identifier;
+      int wheel_click_angle;
+   } detent;
+
+   Eina_List *watched_clients;
+};
+
+struct _E_Devicemgr_Intercept_Hook
+{
+   EINA_INLIST;
+   E_Devicemgr_Intercept_Hook_Point hookpoint;
+   E_Devicemgr_Intercept_Hook_Cb func;
+   void *data;
+   unsigned char delete_me : 1;
+};
+
+E_API E_Devicemgr_Intercept_Hook *e_devicemgr_intercept_hook_add(E_Devicemgr_Intercept_Hook_Point hookpoint, E_Devicemgr_Intercept_Hook_Cb func, const void *data);
+E_API void e_devicemgr_intercept_hook_del(E_Devicemgr_Intercept_Hook *ch);
+E_API Eina_Bool e_devicemgr_intercept_hook_call(E_Devicemgr_Intercept_Hook_Point hookpoint, void *event);
+E_API Eina_Bool e_devicemgr_is_blocking_event(Ecore_Device_Class clas);
+
+E_API int e_devicemgr_init(void);
+E_API int e_devicemgr_shutdown(void);
+
+#endif
+#endif
+
diff --git a/src/bin/e_devicemgr_block.c b/src/bin/e_devicemgr_block.c
new file mode 100644 (file)
index 0000000..f50018e
--- /dev/null
@@ -0,0 +1,252 @@
+#include "e_devicemgr_private.h"
+
+Eina_Bool
+e_devicemgr_block_check_keyboard(Ecore_Event_Key *ev, Eina_Bool pressed)
+{
+   Eina_List *l, *l_next;
+   int *keycode, *data;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
+
+   if (e_devicemgr->block.devtype & TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD)
+     {
+        if (!pressed)
+          {
+             EINA_LIST_FOREACH_SAFE(e_devicemgr->pressed_keys, l, l_next, data)
+               {
+                  if (ev->keycode == *data)
+                    {
+                       DMERR("%d is already press key. Propagate this key event.\n", *data);
+                       e_devicemgr->pressed_keys = eina_list_remove_list(e_devicemgr->pressed_keys, l);
+                       E_FREE(data);
+                       return ECORE_CALLBACK_PASS_ON;
+                    }
+               }
+          }
+        return ECORE_CALLBACK_DONE;
+     }
+
+   if (pressed)
+     {
+        keycode = E_NEW(int, 1);
+        EINA_SAFETY_ON_NULL_RETURN_VAL(keycode, ECORE_CALLBACK_PASS_ON);
+
+        *keycode = ev->keycode;
+
+        EINA_LIST_FOREACH(e_devicemgr->pressed_keys, l, data)
+          {
+             if (*data == *keycode)
+               {
+                  E_FREE(keycode);
+                  return ECORE_CALLBACK_PASS_ON;
+               }
+          }
+        e_devicemgr->pressed_keys = eina_list_append(e_devicemgr->pressed_keys, keycode);
+     }
+   else
+     {
+        EINA_LIST_FOREACH_SAFE(e_devicemgr->pressed_keys, l, l_next, data)
+          {
+             if (ev->keycode == *data)
+               {
+                  e_devicemgr->pressed_keys = eina_list_remove_list(e_devicemgr->pressed_keys, l);
+                  E_FREE(data);
+               }
+          }
+     }
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+Eina_Bool
+e_devicemgr_block_check_button(Ecore_Event_Mouse_Button *ev, Eina_Bool pressed)
+{
+   Ecore_Device *dev;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
+   dev = ev->dev;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(dev, ECORE_CALLBACK_PASS_ON);
+
+   if (ecore_device_class_get(dev) == ECORE_DEVICE_CLASS_MOUSE)
+     {
+        if (e_devicemgr->block.devtype & TIZEN_INPUT_DEVICE_MANAGER_CLAS_MOUSE)
+          {
+             if (!pressed)
+               {
+                  if (e_devicemgr->pressed_button & (1 << ev->buttons))
+                    {
+                       e_devicemgr->pressed_button &= ~(1 << ev->buttons);
+                       return ECORE_CALLBACK_PASS_ON;
+                    }
+               }
+             return ECORE_CALLBACK_DONE;
+          }
+
+        if (pressed)
+          {
+             e_devicemgr->pressed_button |= (1 << ev->buttons);
+          }
+        else
+          e_devicemgr->pressed_button &= ~(1 << ev->buttons);
+     }
+   else if (ecore_device_class_get(dev) == ECORE_DEVICE_CLASS_TOUCH)
+     {
+        if (e_devicemgr->block.devtype & TIZEN_INPUT_DEVICE_MANAGER_CLAS_TOUCHSCREEN)
+          {
+             if (!pressed)
+               {
+                  if (e_devicemgr->pressed_finger & (1 << ev->multi.device))
+                    {
+                       e_devicemgr->pressed_finger &= ~(1 << ev->multi.device);
+                       return ECORE_CALLBACK_PASS_ON;
+                    }
+               }
+             return ECORE_CALLBACK_DONE;
+          }
+
+        if (pressed)
+          {
+             e_devicemgr->pressed_finger |= (1 << ev->multi.device);
+          }
+        else
+          e_devicemgr->pressed_finger &= ~(1 << ev->multi.device);
+     }
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+Eina_Bool
+e_devicemgr_block_check_move(Ecore_Event_Mouse_Move *ev)
+{
+   Ecore_Device *dev;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
+   dev = ev->dev;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(dev, ECORE_CALLBACK_PASS_ON);
+
+   if (ecore_device_class_get(dev) == ECORE_DEVICE_CLASS_MOUSE)
+     {
+        if (e_devicemgr->block.devtype & TIZEN_INPUT_DEVICE_MANAGER_CLAS_MOUSE)
+          {
+             return ECORE_CALLBACK_DONE;
+          }
+     }
+   else if (ecore_device_class_get(dev) == ECORE_DEVICE_CLASS_TOUCH)
+     {
+        if (e_devicemgr->block.devtype & TIZEN_INPUT_DEVICE_MANAGER_CLAS_TOUCHSCREEN)
+          {
+             return ECORE_CALLBACK_DONE;
+          }
+     }
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static void
+_e_devicemgr_block_client_remove(struct wl_client *client)
+{
+   if (client != e_devicemgr->block.client) return;
+
+   e_devicemgr->block.devtype = 0x0;
+   if (e_devicemgr->block.duration_timer)
+     {
+        ecore_timer_del(e_devicemgr->block.duration_timer);
+        e_devicemgr->block.duration_timer = NULL;
+     }
+   e_devicemgr->block.client = NULL;
+}
+
+static Eina_Bool
+_e_devicemgr_block_timer(void *data)
+{
+   struct wl_resource *resource = (struct wl_resource *)data;
+   struct wl_client *client = wl_resource_get_client(resource);
+
+   if ((e_devicemgr->block.client) && (e_devicemgr->block.client != client))
+     {
+        return ECORE_CALLBACK_CANCEL;
+     }
+
+   _e_devicemgr_block_client_remove(client);
+   e_devicemgr_wl_block_send_expired(resource);
+
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_e_devicemgr_block_client_cb_destroy(struct wl_listener *l, void *data)
+{
+   struct wl_client *client = (struct wl_client *)data;
+
+   if (!e_devicemgr->block.client) return;
+
+   wl_list_remove(&l->link);
+   E_FREE(l);
+
+   _e_devicemgr_block_client_remove(client);
+}
+
+static void
+_e_devicemgr_block_client_add(struct wl_client *client, struct wl_resource *resource, uint32_t clas, uint32_t duration)
+{
+   struct wl_listener *destroy_listener = NULL;
+   double milli_duration = (double)(duration) / 1000.0;
+
+   /* Last request of block can renew timer time */
+   if (e_devicemgr->block.duration_timer)
+     ecore_timer_del(e_devicemgr->block.duration_timer);
+   e_devicemgr->block.duration_timer = ecore_timer_add(milli_duration, _e_devicemgr_block_timer, resource);
+
+   e_devicemgr->block.devtype |= clas;
+
+   if (e_devicemgr->block.client) return;
+   e_devicemgr->block.client = client;
+
+   destroy_listener = E_NEW(struct wl_listener, 1);
+   EINA_SAFETY_ON_NULL_GOTO(destroy_listener, failed);
+   destroy_listener->notify = _e_devicemgr_block_client_cb_destroy;
+   wl_client_add_destroy_listener(client, destroy_listener);
+
+   return;
+
+failed:
+   ecore_timer_del(e_devicemgr->block.duration_timer);
+   e_devicemgr->block.duration_timer = NULL;
+   e_devicemgr->block.client = NULL;
+}
+
+int
+e_devicemgr_block_add(struct wl_client *client, struct wl_resource *resource, uint32_t clas, uint32_t duration)
+{
+   uint32_t all_class = TIZEN_INPUT_DEVICE_MANAGER_CLAS_MOUSE |
+                        TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD |
+                        TIZEN_INPUT_DEVICE_MANAGER_CLAS_TOUCHSCREEN;
+
+   if ((e_devicemgr->block.client) && (e_devicemgr->block.client != client))
+     {
+        return TIZEN_INPUT_DEVICE_MANAGER_ERROR_BLOCKED_ALREADY;
+     }
+   if (!(clas & all_class))
+     {
+        return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_CLASS;
+     }
+
+   _e_devicemgr_block_client_add(client, resource, clas, duration);
+
+   /* TODO: Release pressed button or key */
+
+   return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+}
+
+int
+e_devicemgr_block_remove(struct wl_client *client)
+{
+   if ((e_devicemgr->block.client) && (e_devicemgr->block.client != client))
+    {
+       return TIZEN_INPUT_DEVICE_MANAGER_ERROR_BLOCKED_ALREADY;
+    }
+
+   _e_devicemgr_block_client_remove(client);
+
+   return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+}
diff --git a/src/bin/e_devicemgr_conf.c b/src/bin/e_devicemgr_conf.c
new file mode 100644 (file)
index 0000000..e3050dc
--- /dev/null
@@ -0,0 +1,46 @@
+#include "e_devicemgr_private.h"
+
+#define E_DEVICEMGR_INPUT_DFLT_BACK_KEYCODE 166
+
+void
+_e_devicemgr_conf_value_check(E_Devicemgr_Config_Data* dconfig)
+{
+   if (!dconfig->conf) dconfig->conf = E_NEW(E_Devicemgr_Conf_Edd, 1);
+   EINA_SAFETY_ON_NULL_RETURN(dconfig->conf);
+
+   dconfig->conf->input.back_keycode = E_DEVICEMGR_INPUT_DFLT_BACK_KEYCODE;
+}
+
+void
+e_devicemgr_conf_init(E_Devicemgr_Config_Data *dconfig)
+{
+   dconfig->conf_edd = E_CONFIG_DD_NEW("Devicemgr_Config", E_Devicemgr_Conf_Edd);
+#undef T
+#undef D
+#define T E_Devicemgr_Conf_Edd
+#define D dconfig->conf_edd
+   E_CONFIG_VAL(D, T, input.button_remap_enable, CHAR);
+   E_CONFIG_VAL(D, T, input.virtual_key_device_enable, CHAR);
+   E_CONFIG_VAL(D, T, input.virtual_mouse_device_enable, CHAR);
+   E_CONFIG_VAL(D, T, input.back_keycode, INT);
+
+#undef T
+#undef D
+   dconfig->conf = e_config_domain_load("module.devicemgr", dconfig->conf_edd);
+
+   if (!dconfig->conf)
+     {
+        WRN("Failed to find module.devicemgr config file.\n");
+     }
+   _e_devicemgr_conf_value_check(dconfig);
+}
+
+void
+e_devicemgr_conf_fini(E_Devicemgr_Config_Data *dconfig)
+{
+   if (dconfig->conf)
+     {
+        E_FREE(dconfig->conf);
+     }
+   E_CONFIG_DD_FREE(dconfig->conf_edd);
+}
diff --git a/src/bin/e_devicemgr_input.c b/src/bin/e_devicemgr_input.c
new file mode 100644 (file)
index 0000000..ff40681
--- /dev/null
@@ -0,0 +1,536 @@
+#include "e_devicemgr_private.h"
+
+static int
+_e_devicemgr_input_pointer_warp(int x, int y)
+{
+   e_input_device_pointer_warp(NULL, x, y);
+   DMDBG("The pointer warped to (%d, %d) !\n", x, y);
+
+   return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+}
+
+int
+e_devicemgr_input_pointer_warp(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, wl_fixed_t x, wl_fixed_t y)
+{
+   E_Client *ec;
+   int new_x, new_y;
+   int ret;
+
+   if (!(ec = wl_resource_get_user_data(surface)) || !ec->visible)
+     {
+        DMDBG("The given surface is invalid or invisible !\n");
+        return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_SURFACE;
+     }
+
+   if (ec != e_comp_wl->ptr.ec)
+     {
+        DMDBG("Pointer is not on the given surface  !\n");
+        return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_SURFACE;
+     }
+
+   if (e_pointer_is_hidden(e_comp->pointer))
+     {
+        DMDBG("Pointer is hidden");
+        return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_POINTER_AVAILABLE;
+     }
+
+   new_x = wl_fixed_to_int(x);
+   new_y = wl_fixed_to_int(y);
+   if (e_client_transform_core_enable_get(ec))
+     e_client_transform_core_input_inv_rect_transform(ec, wl_fixed_to_int(x), wl_fixed_to_int(y), &new_x, &new_y);
+
+   ret = _e_devicemgr_input_pointer_warp(ec->client.x + new_x, ec->client.y + new_y);
+   return ret;
+}
+
+typedef struct _keycode_map{
+    xkb_keysym_t keysym;
+    xkb_keycode_t keycode;
+} keycode_map;
+
+static void
+find_keycode(struct xkb_keymap *keymap, xkb_keycode_t key, void *data)
+{
+   keycode_map *found_keycodes = (keycode_map *)data;
+   xkb_keysym_t keysym = found_keycodes->keysym;
+   int nsyms = 0;
+   const xkb_keysym_t *syms_out = NULL;
+
+   if (found_keycodes->keycode) return;
+
+   nsyms = xkb_keymap_key_get_syms_by_level(keymap, key, 0, 0, &syms_out);
+   if (nsyms && syms_out)
+     {
+        if (*syms_out == keysym)
+          {
+             found_keycodes->keycode = key;
+          }
+     }
+}
+
+static void
+_e_devicemgr_keycode_from_keysym(struct xkb_keymap *keymap, xkb_keysym_t keysym, xkb_keycode_t *keycode)
+{
+    keycode_map found_keycodes = {0,};
+    found_keycodes.keysym = keysym;
+    xkb_keymap_key_for_each(keymap, find_keycode, &found_keycodes);
+
+    *keycode = found_keycodes.keycode;
+}
+
+int
+e_devicemgr_keycode_from_string(const char *keyname)
+{
+   xkb_keysym_t keysym = 0x0;
+   xkb_keycode_t keycode = 0;
+
+   if (!strncmp(keyname, "Keycode-", sizeof("Keycode-")-1))
+     {
+        keycode = atoi(keyname+8);
+     }
+   else
+     {
+        keysym = xkb_keysym_from_name(keyname, XKB_KEYSYM_NO_FLAGS);
+        _e_devicemgr_keycode_from_keysym(e_comp_wl->xkb.keymap, keysym, &keycode);
+     }
+
+   return keycode;
+}
+
+static Eina_Bool
+_e_devicemgr_detent_is_detent(const char *name)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
+
+   if (!strncmp(name, DETENT_DEVICE_NAME, sizeof(DETENT_DEVICE_NAME)))
+     return EINA_TRUE;
+
+   return EINA_FALSE;
+}
+
+static void
+_e_devicemgr_detent_set_info(E_Devicemgr_Input_Device *dev)
+{
+   Eina_List *dev_list, *l, *ll, *lll;
+   E_Input_Device *device_data;
+   E_Input_Seat *seat;
+   E_Input_Evdev *edev;
+
+   if ((!e_devicemgr->detent.identifier) &&
+       (dev->name && !strncmp(dev->name, DETENT_DEVICE_NAME, sizeof(DETENT_DEVICE_NAME))))
+     {
+        e_devicemgr->detent.identifier = (char *)eina_stringshare_add(dev->identifier);
+        dev_list = (Eina_List *)e_input_devices_get();
+        EINA_LIST_FOREACH(dev_list, l, device_data)
+          {
+             EINA_LIST_FOREACH(device_data->seats, ll, seat)
+               {
+                  EINA_LIST_FOREACH(e_input_seat_evdev_list_get(seat), lll, edev)
+                    {
+                       if (!strncmp(e_input_evdev_name_get(edev), DETENT_DEVICE_NAME, sizeof(DETENT_DEVICE_NAME)))
+                         {
+                            e_devicemgr->detent.wheel_click_angle = e_input_evdev_wheel_click_angle_get(edev);
+                         }
+                    }
+               }
+          }
+     }
+}
+
+static void
+_e_devicemgr_detent_unset_info(E_Devicemgr_Input_Device *dev)
+{
+   if ((e_devicemgr->detent.identifier) &&
+       (dev->name && (!strncmp(dev->name, DETENT_DEVICE_NAME, sizeof(DETENT_DEVICE_NAME)))))
+     {
+        eina_stringshare_del(e_devicemgr->detent.identifier);
+     }
+}
+
+static void
+_e_devicemgr_input_keyevent_free(void *data EINA_UNUSED, void *ev)
+{
+   Ecore_Event_Key *e = ev;
+
+   eina_stringshare_del(e->keyname);
+   eina_stringshare_del(e->key);
+   eina_stringshare_del(e->compose);
+
+   E_FREE(e->data);
+   E_FREE(e);
+}
+
+static Eina_Bool
+_e_devicemgr_input_mouse_button_remap(Ecore_Event_Mouse_Button *ev, Eina_Bool pressed)
+{
+   Ecore_Event_Key *ev_key;
+   E_Keyrouter_Event_Data *key_data;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl->xkb.keymap, ECORE_CALLBACK_PASS_ON);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
+
+   if (ev->buttons != 3) return ECORE_CALLBACK_PASS_ON;
+
+   ev_key = E_NEW(Ecore_Event_Key, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ev_key, ECORE_CALLBACK_PASS_ON);
+
+   key_data = E_NEW(E_Keyrouter_Event_Data, 1);
+   EINA_SAFETY_ON_NULL_GOTO(key_data, failed);
+
+   ev_key->key = (char *)eina_stringshare_add("XF86Back");
+   ev_key->keyname = (char *)eina_stringshare_add(ev_key->key);
+   ev_key->compose = (char *)eina_stringshare_add(ev_key->key);
+   ev_key->timestamp = (int)(ecore_time_get()*1000);
+   ev_key->same_screen = 1;
+
+   ev_key->window = e_comp->ee_win;
+   ev_key->event_window = e_comp->ee_win;
+   ev_key->root_window = e_comp->ee_win;
+   ev_key->keycode = e_devicemgr->dconfig->conf->input.back_keycode;
+   ev_key->data = key_data;
+
+   if (pressed)
+     ecore_event_add(ECORE_EVENT_KEY_DOWN, ev_key, _e_devicemgr_input_keyevent_free, NULL);
+   else
+     ecore_event_add(ECORE_EVENT_KEY_UP, ev_key, _e_devicemgr_input_keyevent_free, NULL);
+
+   return ECORE_CALLBACK_DONE;
+
+failed:
+   E_FREE(ev_key);
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static void
+_e_devicemgr_input_device_add(const char *name, const char *identifier, const char *seatname, Ecore_Device_Class clas, Ecore_Device_Subclass subclas)
+{
+   E_Devicemgr_Input_Device *dev;
+   Eina_List *l;
+
+   EINA_LIST_FOREACH(e_devicemgr->device_list, l, dev)
+     {
+        if ((dev->clas == clas) && (!strcmp(dev->identifier, identifier)))
+          {
+             return;
+          }
+     }
+
+   if (!(dev = E_NEW(E_Devicemgr_Input_Device, 1))) return;
+   dev->name = eina_stringshare_add(name);
+   dev->identifier = eina_stringshare_add(identifier);
+   dev->clas = clas;
+   dev->subclas = subclas;
+
+   e_devicemgr->device_list = eina_list_append(e_devicemgr->device_list, dev);
+
+   e_devicemgr_wl_device_add(dev);
+   e_devicemgr_inputgen_get_device_info(dev);
+   _e_devicemgr_detent_set_info(dev);
+
+   if (dev->clas == ECORE_DEVICE_CLASS_MOUSE)
+     e_devicemgr->last_device_ptr = dev;
+
+   if (!e_devicemgr->last_device_touch && dev->clas == ECORE_DEVICE_CLASS_TOUCH)
+     e_devicemgr->last_device_touch = dev;
+
+   if (!e_devicemgr->last_device_kbd && dev->clas == ECORE_DEVICE_CLASS_KEYBOARD)
+     e_devicemgr->last_device_kbd = dev;
+}
+
+static void
+_e_devicemgr_input_device_del(const char *name, const char *identifier, const char *seatname, Ecore_Device_Class clas, Ecore_Device_Subclass subclas)
+{
+   E_Devicemgr_Input_Device *dev;
+   Eina_List *l;
+
+   EINA_LIST_FOREACH(e_devicemgr->device_list, l, dev)
+     {
+        if ((dev->clas == clas) && (dev->subclas == subclas) &&
+            (dev->name && (!strcmp(dev->name, name))) &&
+            (dev->identifier && (!strcmp(dev->identifier, identifier))))
+          break;
+     }
+   if (!dev)
+     {
+        return;
+     }
+
+   _e_devicemgr_detent_unset_info(dev);
+   e_devicemgr_wl_device_del(dev);
+
+   if (dev->name) eina_stringshare_del(dev->name);
+   if (dev->identifier) eina_stringshare_del(dev->identifier);
+
+   e_devicemgr->device_list = eina_list_remove(e_devicemgr->device_list, dev);
+
+   if (e_devicemgr->last_device_ptr == dev)
+     e_devicemgr->last_device_ptr = NULL;
+
+   if (e_devicemgr->last_device_touch == dev)
+     e_devicemgr->last_device_touch = NULL;
+
+   if (e_devicemgr->last_device_kbd == dev)
+     e_devicemgr->last_device_kbd = NULL;
+
+   E_FREE(dev);
+}
+
+static Eina_Bool
+_e_devicemgr_input_cb_mouse_button_down(void *data, int type, void *event)
+{
+   Ecore_Event_Mouse_Button *ev;
+   Eina_Bool res = ECORE_CALLBACK_PASS_ON;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(event, res);
+
+   ev = (Ecore_Event_Mouse_Button *)event;
+
+   if (e_devicemgr->dconfig->conf->input.button_remap_enable)
+     res = _e_devicemgr_input_mouse_button_remap(ev, EINA_TRUE);
+
+   return res;
+}
+
+static Eina_Bool
+_e_devicemgr_input_cb_mouse_button_up(void *data, int type, void *event)
+{
+   Ecore_Event_Mouse_Button *ev;
+   Eina_Bool res = ECORE_CALLBACK_PASS_ON;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(event, res);
+
+   ev = (Ecore_Event_Mouse_Button *)event;
+
+   if (e_devicemgr->dconfig->conf->input.button_remap_enable)
+     res = _e_devicemgr_input_mouse_button_remap(ev, EINA_FALSE);
+
+   return res;
+}
+
+static Eina_Bool
+_e_devicemgr_input_cb_device_add(void *data, int type, void *event)
+{
+   Ecore_Event_Device_Info *ev;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(event, ECORE_CALLBACK_PASS_ON);
+
+   ev = (Ecore_Event_Device_Info *)event;
+
+   _e_devicemgr_input_device_add(ev->name, ev->identifier, ev->seatname, ev->clas, ev->subclas);
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_devicemgr_input_cb_device_del(void *data, int type, void *event)
+{
+   Ecore_Event_Device_Info *ev;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(event, ECORE_CALLBACK_PASS_ON);
+
+   ev = (Ecore_Event_Device_Info *)event;
+
+   _e_devicemgr_input_device_del(ev->name, ev->identifier, ev->seatname, ev->clas, ev->subclas);
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_devicemgr_input_process_mouse_button_down(Ecore_Event_Mouse_Button *ev)
+{
+   Eina_Bool res = ECORE_CALLBACK_PASS_ON;
+
+   res = e_devicemgr_block_check_button(ev, EINA_TRUE);
+
+   return res;
+}
+
+static Eina_Bool
+_e_devicemgr_input_process_mouse_button_up(Ecore_Event_Mouse_Button *ev)
+{
+   Eina_Bool res = ECORE_CALLBACK_PASS_ON;
+
+   res = e_devicemgr_block_check_button(ev, EINA_FALSE);
+
+   return res;
+}
+
+static Eina_Bool
+_e_devicemgr_input_process_mouse_move(Ecore_Event_Mouse_Move *ev)
+{
+   Eina_Bool res = ECORE_CALLBACK_PASS_ON;
+
+   if (ev->dev && _e_devicemgr_detent_is_detent(ecore_device_name_get(ev->dev)))
+     return res;
+
+   res = e_devicemgr_block_check_move(ev);
+
+   return res;
+}
+
+static Eina_Bool
+_e_devicemgr_input_process_mouse_wheel(Ecore_Event_Mouse_Wheel *ev)
+{
+   int detent;
+
+   if (!ev->dev) return ECORE_CALLBACK_PASS_ON;
+
+   if (!_e_devicemgr_detent_is_detent(ecore_device_name_get(ev->dev)))
+     return ECORE_CALLBACK_PASS_ON;
+
+   detent = (int)(ev->z / (e_devicemgr->detent.wheel_click_angle
+                           ? e_devicemgr->detent.wheel_click_angle
+                           : 1));
+
+   if (detent == 2 || detent == -2)
+     {
+        detent = (detent / 2)*(-1);
+        e_devicemgr_wl_detent_send_event(detent);
+     }
+
+   return ECORE_CALLBACK_DONE;
+}
+
+static Eina_Bool
+_e_devicemgr_input_process_key_down(Ecore_Event_Key *ev)
+{
+   Eina_Bool res = ECORE_CALLBACK_PASS_ON;
+
+   res = e_devicemgr_block_check_keyboard(ev, EINA_TRUE);
+
+   return res;
+}
+
+static Eina_Bool
+_e_devicemgr_input_process_key_up(Ecore_Event_Key *ev)
+{
+   Eina_Bool res = ECORE_CALLBACK_PASS_ON;
+
+   res = e_devicemgr_block_check_keyboard(ev, EINA_FALSE);
+
+   return res;
+}
+
+static Eina_Bool
+_e_devicemgr_input_event_filter(void *data EINA_UNUSED, void *loop_data EINA_UNUSED, int type, void *event)
+{
+   Eina_Bool res = ECORE_CALLBACK_PASS_ON;
+
+   if (!event) return res;
+
+   if ((ECORE_EVENT_DEVICE_ADD == type) ||
+       (ECORE_EVENT_DEVICE_DEL == type))
+     {
+        Ecore_Event_Device_Info *ev;
+        ev = (Ecore_Event_Device_Info *)event;
+
+        /* Remove mouse class from tizen detent device */
+        if (_e_devicemgr_detent_is_detent(ev->name))
+          ev->clas &= ~ECORE_DEVICE_CLASS_MOUSE;
+     }
+   else if (E_INPUT_EVENT_INPUT_DEVICE_ADD == type)
+     {
+        E_Input_Event_Input_Device_Add *ev;
+        ev = (E_Input_Event_Input_Device_Add *)event;
+
+        /* Remove pointer capability from tizen detent device */
+        if (_e_devicemgr_detent_is_detent(ev->name))
+          ev->caps &= ~E_INPUT_SEAT_POINTER;
+     }
+   else if (E_INPUT_EVENT_INPUT_DEVICE_DEL == type)
+     {
+        E_Input_Event_Input_Device_Del *ev;
+        ev = (E_Input_Event_Input_Device_Del *)event;
+
+        /* Remove pointer capability from tizen detent device */
+        if (_e_devicemgr_detent_is_detent(ev->name))
+          ev->caps &= ~E_INPUT_SEAT_POINTER;
+     }
+   else if (ECORE_EVENT_KEY_DOWN == type)
+     {
+        Ecore_Event_Key *ev;
+        ev = (Ecore_Event_Key *)event;
+
+        res = _e_devicemgr_input_process_key_down(ev);
+     }
+   else if (ECORE_EVENT_KEY_UP == type)
+     {
+        Ecore_Event_Key *ev;
+        ev = (Ecore_Event_Key *)event;
+
+        res = _e_devicemgr_input_process_key_up(ev);
+     }
+   else if (ECORE_EVENT_MOUSE_BUTTON_DOWN == type)
+     {
+        Ecore_Event_Mouse_Button *ev;
+        ev = (Ecore_Event_Mouse_Button *)event;
+
+        res = _e_devicemgr_input_process_mouse_button_down(ev);
+     }
+   else if (ECORE_EVENT_MOUSE_BUTTON_UP == type)
+     {
+        Ecore_Event_Mouse_Button *ev;
+        ev = (Ecore_Event_Mouse_Button *)event;
+
+        res = _e_devicemgr_input_process_mouse_button_up(ev);
+     }
+   else if (ECORE_EVENT_MOUSE_MOVE == type)
+     {
+        Ecore_Event_Mouse_Move *ev;
+        ev = (Ecore_Event_Mouse_Move *)event;
+
+        res = _e_devicemgr_input_process_mouse_move(ev);
+     }
+   else if (ECORE_EVENT_MOUSE_WHEEL == type)
+     {
+        Ecore_Event_Mouse_Wheel *ev;
+        ev = (Ecore_Event_Mouse_Wheel *)event;
+
+        res = _e_devicemgr_input_process_mouse_wheel(ev);
+     }
+
+   return res;
+}
+
+static void
+_e_devicemgr_device_query(void)
+{
+   Eina_List *list, *l;
+   Ecore_Device *dev;
+
+   list = (Eina_List *)ecore_device_list();
+
+   EINA_LIST_FOREACH(list, l, dev)
+     {
+        _e_devicemgr_input_device_add(ecore_device_name_get(dev),
+                                      ecore_device_identifier_get(dev),
+                                      ecore_device_name_get(dev),
+                                      ecore_device_class_get(dev),
+                                      ecore_device_subclass_get(dev));
+     }
+}
+
+Eina_Bool
+e_devicemgr_input_init(void)
+{
+   e_devicemgr->ev_filter = ecore_event_filter_add(NULL, _e_devicemgr_input_event_filter, NULL, NULL);
+   E_LIST_HANDLER_APPEND(e_devicemgr->handlers, ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_devicemgr_input_cb_mouse_button_down, NULL);
+   E_LIST_HANDLER_APPEND(e_devicemgr->handlers, ECORE_EVENT_MOUSE_BUTTON_UP, _e_devicemgr_input_cb_mouse_button_up, NULL);
+   E_LIST_HANDLER_APPEND(e_devicemgr->handlers, ECORE_EVENT_DEVICE_ADD, _e_devicemgr_input_cb_device_add, NULL);
+   E_LIST_HANDLER_APPEND(e_devicemgr->handlers, ECORE_EVENT_DEVICE_DEL, _e_devicemgr_input_cb_device_del, NULL);
+
+   _e_devicemgr_device_query();
+
+   return EINA_TRUE;
+}
+
+void
+e_devicemgr_input_shutdown(void)
+{
+   Ecore_Event_Handler *h = NULL;
+
+   EINA_LIST_FREE(e_devicemgr->handlers, h)
+     ecore_event_handler_del(h);
+
+   ecore_event_filter_del(e_devicemgr->ev_filter);
+}
diff --git a/src/bin/e_devicemgr_inputgen.c b/src/bin/e_devicemgr_inputgen.c
new file mode 100644 (file)
index 0000000..f3c38c4
--- /dev/null
@@ -0,0 +1,900 @@
+#include "e_devicemgr_private.h"
+
+static Eina_List **
+_e_devicemgr_inputgen_list_get(Ecore_Device_Class clas)
+{
+   switch (clas)
+     {
+        case ECORE_DEVICE_CLASS_KEYBOARD:
+          return &e_devicemgr->inputgen.kbd_list;
+          break;
+        case ECORE_DEVICE_CLASS_MOUSE:
+          return &e_devicemgr->inputgen.ptr_list;
+          break;
+        case ECORE_DEVICE_CLASS_TOUCH:
+          return &e_devicemgr->inputgen.touch_list;
+          break;
+        default:
+          return NULL;
+     }
+}
+
+static char *
+_e_devicemgr_inputgen_name_get(struct wl_resource *resource)
+{
+   Eina_List *l;
+   E_Devicemgr_Inputgen_Resource_Data *rdata;
+
+   EINA_LIST_FOREACH(e_devicemgr->inputgen.resource_list, l, rdata)
+     {
+        if (rdata->resource == resource) return rdata->name;
+     }
+
+   return NULL;
+}
+
+static Eina_Bool
+_e_devicemgr_inputgen_device_check(char *name, Ecore_Device_Class clas)
+{
+   Eina_List **dev_list, *l;
+   E_Devicemgr_Inputgen_Device_Data *ddata;
+
+   if (!name) return EINA_FALSE;
+   dev_list = _e_devicemgr_inputgen_list_get(clas);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(dev_list, EINA_FALSE);
+
+   EINA_LIST_FOREACH(*dev_list, l, ddata)
+     {
+        if (!strncmp(ddata->name, name, UINPUT_MAX_NAME_SIZE))
+          return EINA_TRUE;
+     }
+
+   return EINA_FALSE;
+}
+
+static void
+_e_devicemgr_inputgen_remove_device(E_Devicemgr_Inputgen_Device_Data *device)
+{
+   if (!device || device->uinp_fd < 0)
+     {
+        DMWRN("There are no devices created for input generation.\n");
+        return;
+     }
+
+   e_devicemgr_destroy_virtual_device(device->uinp_fd);
+   device->uinp_fd = -1;
+   eina_stringshare_del(device->identifier);
+   device->identifier = NULL;
+}
+
+static void
+_e_devicemgr_inputgen_client_device_remove(struct wl_client *client, Ecore_Device_Class clas)
+{
+   Eina_List **dev_list, *l, *l_next, *ll, *ll_next;
+   E_Devicemgr_Inputgen_Device_Data *ddata;
+   E_Devicemgr_Inputgen_Client_Data *cdata;
+
+   dev_list = _e_devicemgr_inputgen_list_get(clas);
+   EINA_SAFETY_ON_NULL_RETURN(dev_list);
+
+   EINA_LIST_FOREACH_SAFE(*dev_list, l, l_next, ddata)
+     {
+        EINA_LIST_FOREACH_SAFE(ddata->clients, ll, ll_next, cdata)
+          {
+             if (cdata->client == client)
+               {
+                  ddata->clients = eina_list_remove_list(ddata->clients, ll);
+                  E_FREE(cdata);
+               }
+          }
+        if (eina_list_count(ddata->clients) == 0)
+          {
+             _e_devicemgr_inputgen_remove_device(ddata);
+             *dev_list = eina_list_remove_list(*dev_list, l);
+             E_FREE(ddata);
+          }
+     }
+}
+
+static void
+_e_devicemgr_inputgen_client_cb_destroy(struct wl_listener *l, void *data)
+{
+   struct wl_client *client = (struct wl_client *)data;
+   E_Devicemgr_Inputgen_Resource_Data *rdata;
+   E_Devicemgr_Inputgen_Client_Global_Data *gdata;
+   Eina_List *list, *l_next;
+
+   EINA_SAFETY_ON_NULL_RETURN(l);
+
+   wl_list_remove(&l->link);
+   E_FREE(l);
+
+   EINA_LIST_FOREACH_SAFE(e_devicemgr->watched_clients, list, l_next, gdata)
+     {
+        if (gdata->client == client)
+          {
+             e_devicemgr->watched_clients =
+               eina_list_remove_list(e_devicemgr->watched_clients, list);
+             E_FREE(gdata);
+
+             break;
+          }
+     }
+
+   _e_devicemgr_inputgen_client_device_remove(client, ECORE_DEVICE_CLASS_KEYBOARD);
+   _e_devicemgr_inputgen_client_device_remove(client, ECORE_DEVICE_CLASS_MOUSE);
+   _e_devicemgr_inputgen_client_device_remove(client, ECORE_DEVICE_CLASS_TOUCH);
+
+   EINA_LIST_FOREACH_SAFE(e_devicemgr->inputgen.resource_list, list, l_next, rdata)
+     {
+        if (wl_resource_get_client(rdata->resource) == client)
+          {
+             e_devicemgr->inputgen.resource_list =
+               eina_list_remove_list(e_devicemgr->inputgen.resource_list, list);
+             E_FREE(rdata);
+          }
+     }
+}
+
+static void
+_e_devicemgr_inputgen_client_add(struct wl_client *client, unsigned int clas)
+{
+   struct wl_listener *destroy_listener;
+   E_Devicemgr_Inputgen_Client_Global_Data *data;
+   Eina_List *l;
+
+   EINA_LIST_FOREACH(e_devicemgr->watched_clients, l, data)
+     {
+        if (data->client == client)
+          {
+             data->clas |= clas;
+             return;
+          }
+     }
+   data = NULL;
+
+   destroy_listener = E_NEW(struct wl_listener, 1);
+   EINA_SAFETY_ON_NULL_GOTO(destroy_listener, failed);
+   destroy_listener->notify = _e_devicemgr_inputgen_client_cb_destroy;
+   wl_client_add_destroy_listener(client, destroy_listener);
+
+   data = E_NEW(E_Devicemgr_Inputgen_Client_Global_Data, 1);
+   EINA_SAFETY_ON_NULL_GOTO(data, failed);
+
+   data->client = client;
+   data->clas = clas;
+
+   e_devicemgr->watched_clients =
+      eina_list_append(e_devicemgr->watched_clients, data);
+
+   return;
+
+failed:
+   if (destroy_listener)
+     {
+        wl_list_remove(&destroy_listener->link);
+        E_FREE(destroy_listener);
+     }
+}
+
+static void
+_e_devicemgr_inputgen_client_del(struct wl_client *client, unsigned int clas)
+{
+   E_Devicemgr_Inputgen_Client_Global_Data *data;
+   E_Devicemgr_Inputgen_Client_Data *cdata;
+   E_Devicemgr_Inputgen_Device_Data *ddata;
+   Eina_List *l, *ll, *l_next, *ll_next, **list;
+
+   list = _e_devicemgr_inputgen_list_get(clas);
+   EINA_SAFETY_ON_NULL_RETURN(list);
+
+   EINA_LIST_FOREACH_SAFE(*list, l, l_next, ddata)
+     {
+        EINA_LIST_FOREACH_SAFE(ddata->clients, ll, ll_next, cdata)
+          {
+             if (cdata->client == client)
+               {
+                  cdata->ref--;
+                  if (cdata->ref <= 0)
+                    {
+                       ddata->clients = eina_list_remove_list(ddata->clients, ll);
+                       E_FREE(cdata);
+                    }
+               }
+          }
+
+        if (eina_list_count(ddata->clients) == 0)
+          {
+             ddata->clients = NULL;
+             _e_devicemgr_inputgen_remove_device(ddata);
+             *list = eina_list_remove_list(*list, l);
+             E_FREE(ddata);
+          }
+     }
+
+   EINA_LIST_FOREACH(e_devicemgr->watched_clients, l, data)
+     {
+        if (data->client == client)
+          {
+             data->clas &= ~clas;
+          }
+     }
+}
+
+static void
+_e_devicemgr_inputgen_resource_add(struct wl_resource *resource, const char *name)
+{
+   E_Devicemgr_Inputgen_Resource_Data *rdata;
+   Eina_List *l;
+
+   EINA_LIST_FOREACH(e_devicemgr->inputgen.resource_list, l, rdata)
+     {
+        if (rdata->resource == resource) return;
+     }
+
+   rdata = NULL;
+   rdata = E_NEW(E_Devicemgr_Inputgen_Resource_Data, 1);
+   EINA_SAFETY_ON_NULL_RETURN(rdata);
+
+   rdata->resource = resource;
+   strncpy(rdata->name, name, UINPUT_MAX_NAME_SIZE - 1);
+
+   e_devicemgr->inputgen.resource_list = eina_list_append(e_devicemgr->inputgen.resource_list, rdata);
+}
+
+static void
+_e_devicemgr_inputgen_resource_del(struct wl_resource *resource)
+{
+   E_Devicemgr_Inputgen_Resource_Data *rdata;
+   Eina_List *l, *l_next;
+
+   EINA_LIST_FOREACH_SAFE(e_devicemgr->inputgen.resource_list, l, l_next, rdata)
+     {
+        if (rdata->resource == resource)
+          {
+             e_devicemgr->inputgen.resource_list =
+               eina_list_remove_list(e_devicemgr->inputgen.resource_list, l);
+             E_FREE(rdata);
+          }
+     }
+}
+
+int
+_e_devicemgr_inputgen_create_device(Ecore_Device_Class clas, struct wl_client *client, const char *device_name)
+{
+   int uinp_fd = -1;
+   Eina_List **dev_list, *l, *ll;
+   E_Devicemgr_Inputgen_Client_Data *cdata;
+   E_Devicemgr_Inputgen_Device_Data *ddata, *device = NULL;
+   Eina_Bool exist_device_flag = EINA_FALSE;
+
+   dev_list = _e_devicemgr_inputgen_list_get(clas);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(dev_list, EINA_FALSE);
+
+   EINA_LIST_FOREACH(*dev_list, l, ddata)
+     {
+        if (!strncmp(ddata->name, device_name, UINPUT_MAX_NAME_SIZE))
+          {
+             EINA_LIST_FOREACH(ddata->clients, ll, cdata)
+               {
+                  if (cdata->client == client)
+                    {
+                       cdata->ref++;
+                       return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+                    }
+               }
+
+             device = ddata;
+             exist_device_flag = EINA_TRUE;
+             break;
+          }
+     }
+
+   if (!device)
+     {
+        device = E_NEW(E_Devicemgr_Inputgen_Device_Data, 1);
+        EINA_SAFETY_ON_NULL_RETURN_VAL(device, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES);
+        strncpy(device->name, device_name, UINPUT_MAX_NAME_SIZE - 1);
+     }
+
+   cdata = E_NEW(E_Devicemgr_Inputgen_Client_Data, 1);
+   if(!cdata)
+     {
+        if (!exist_device_flag) E_FREE(device);
+        return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
+     }
+
+   cdata->ref = 1;
+   cdata->client = client;
+
+   device->clients = eina_list_append(device->clients, cdata);
+
+   if (exist_device_flag)
+     return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+
+   uinp_fd = e_devicemgr_create_virtual_device(clas, device_name);
+
+   if (uinp_fd < 0)
+     goto fail_create_device;
+
+   device->uinp_fd = uinp_fd;
+   *dev_list = eina_list_append(*dev_list, device);
+
+   return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+
+fail_create_device:
+   EINA_LIST_FREE(device->clients, cdata)
+     E_FREE(cdata);
+   E_FREE(device);
+   return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
+}
+
+static void
+_e_devicemgr_inputgen_key_event_free(void *data EINA_UNUSED, void *ev)
+{
+   Ecore_Event_Key *e = ev;
+
+   eina_stringshare_del(e->keyname);
+   eina_stringshare_del(e->key);
+   eina_stringshare_del(e->compose);
+
+   if (e->dev) ecore_device_unref(e->dev);
+   if (e->data) E_FREE(e->data);
+
+   free(e);
+}
+
+int
+_e_devicemgr_inputgen_key_event_add(const char *key, Eina_Bool pressed, char *identifier)
+{
+   Ecore_Event_Key *e;
+   unsigned int keycode;
+   E_Keyrouter_Event_Data *key_data;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(key, TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER);
+
+   e = E_NEW(Ecore_Event_Key, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES);
+
+   keycode = e_devicemgr_keycode_from_string(key);
+   if (keycode <= 0) goto finish;
+
+   e->keyname = eina_stringshare_add(key);
+   e->key = eina_stringshare_add(key);
+   e->compose = eina_stringshare_add(key);
+   e->string = e->compose;
+
+   e->window = e_comp->ee_win;
+   e->event_window = e_comp->ee_win;
+   e->root_window = e_comp->ee_win;
+   e->timestamp = (int)(ecore_time_get() * 1000);
+   e->same_screen = 1;
+   e->keycode = keycode;
+   key_data = E_NEW(E_Keyrouter_Event_Data, 1);
+   EINA_SAFETY_ON_NULL_GOTO(key_data, finish);
+   e->data = key_data;
+
+   e->modifiers = 0;
+   e->dev = ecore_device_ref(e_input_evdev_get_ecore_device(identifier, ECORE_DEVICE_CLASS_KEYBOARD));
+
+   DMDBG("Generate key event: key: %s, keycode: %d, iden: %s\n", e->key, e->keycode, identifier);
+
+   if (pressed)
+     ecore_event_add(ECORE_EVENT_KEY_DOWN, e, _e_devicemgr_inputgen_key_event_free, NULL);
+   else
+     ecore_event_add(ECORE_EVENT_KEY_UP, e, _e_devicemgr_inputgen_key_event_free, NULL);
+
+   return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+
+finish:
+    if(e) E_FREE(e);
+    return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
+}
+
+static void
+_e_devicemgr_inputgen_mouse_button_event_free(void *data EINA_UNUSED, void *ev)
+{
+   Ecore_Event_Mouse_Button *e = ev;
+
+   if (e->dev) ecore_device_unref(e->dev);
+
+   free(e);
+}
+
+int
+_e_devicemgr_inputgen_mouse_button_event(Eina_Bool state, int x, int y, int buttons, char *identifier)
+{
+   Ecore_Event_Mouse_Button *e;
+
+   e = calloc(1, sizeof(Ecore_Event_Mouse_Button));
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES);
+
+   e->window = e_comp->ee_win;
+   e->event_window = e_comp->ee_win;
+   e->root_window = e_comp->ee_win;
+   e->timestamp = (int)(ecore_time_get() * 1000);
+   e->same_screen = 1;
+
+   e->x = x;
+   e->y = y;
+   e->root.x = e->x;
+   e->root.y = e->y;
+
+   e->multi.device = 0;
+   e->multi.radius = 1;
+   e->multi.radius_x = 1;
+   e->multi.radius_y = 1;
+   e->multi.pressure = 1.0;
+   e->multi.angle = 0.0;
+
+   e->multi.x = e->x;
+   e->multi.y = e->y;
+   e->multi.root.x = e->x;
+   e->multi.root.y = e->y;
+   e->dev = ecore_device_ref(e_input_evdev_get_ecore_device(identifier, ECORE_DEVICE_CLASS_MOUSE));
+   e->buttons = buttons;
+
+   DMDBG("Generate mouse button event: button: %d (state: %d)\n", buttons, state);
+
+   if (state)
+     ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, e, _e_devicemgr_inputgen_mouse_button_event_free, NULL);
+   else
+     ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, e, _e_devicemgr_inputgen_mouse_button_event_free, NULL);
+
+   return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+}
+
+static void
+_e_devicemgr_inputgen_mouse_move_event_free(void *data EINA_UNUSED, void *ev)
+{
+   Ecore_Event_Mouse_Move *e = ev;
+
+   if (e->dev) ecore_device_unref(e->dev);
+
+   free(e);
+}
+
+int
+_e_devicemgr_inputgen_mouse_move_event(int x, int y, char *identifier)
+{
+   Ecore_Event_Mouse_Move *e;
+
+   DMERR("Try\n");
+
+   e = calloc(1, sizeof(Ecore_Event_Mouse_Move));
+   if (!e) return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
+
+   e->window = e_comp->ee_win;
+   e->event_window = e_comp->ee_win;
+   e->root_window = e_comp->ee_win;
+   e->timestamp = (int)(ecore_time_get() * 1000);
+   e->same_screen = 1;
+
+   e->x = x;
+   e->y = y;
+   e->root.x = e->x;
+   e->root.y = e->y;
+
+   e->multi.device = 0;
+   e->multi.radius = 1;
+   e->multi.radius_x = 1;
+   e->multi.radius_y = 1;
+   e->multi.pressure = 1.0;
+   e->multi.angle = 0.0;
+
+   e->multi.x = e->x;
+   e->multi.y = e->y;
+   e->multi.root.x = e->x;
+   e->multi.root.y = e->y;
+   e->dev = ecore_device_ref(e_input_evdev_get_ecore_device(identifier, ECORE_DEVICE_CLASS_MOUSE));
+
+   DMDBG("Generate mouse move event: (%d, %d)\n", e->x, e->y);
+
+   ecore_event_add(ECORE_EVENT_MOUSE_MOVE, e, _e_devicemgr_inputgen_mouse_move_event_free, NULL);
+
+   return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+}
+
+static int
+_e_devicemgr_inputgen_touch_event(uint32_t type, uint32_t x, uint32_t y, uint32_t finger, char *identifier)
+{
+   Ecore_Event_Mouse_Button *e;
+
+   e = calloc(1, sizeof(Ecore_Event_Mouse_Button));
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES);
+
+   e->window = e_comp->ee_win;
+   e->event_window = e_comp->ee_win;
+   e->root_window = e_comp->ee_win;
+   e->timestamp = (int)(ecore_time_get() * 1000);
+   e->same_screen = 1;
+
+   e->x = x;
+   e->y = y;
+   e->root.x = e->x;
+   e->root.y = e->y;
+
+   e->multi.device = finger;
+   e->multi.radius = 1;
+   e->multi.radius_x = 1;
+   e->multi.radius_y = 1;
+   e->multi.pressure = 1.0;
+   e->multi.angle = 0.0;
+
+   e->multi.x = e->x;
+   e->multi.y = e->y;
+   e->multi.root.x = e->x;
+   e->multi.root.y = e->y;
+   e->dev = ecore_device_ref(e_input_evdev_get_ecore_device(identifier, ECORE_DEVICE_CLASS_TOUCH));
+   e->buttons = 1;
+
+   DMDBG("Generate touch event: device: %d (%d, %d)\n", e->multi.device, e->x, e->y);
+
+   if (type == TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN)
+     ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, e, _e_devicemgr_inputgen_mouse_button_event_free, NULL);
+   else
+     ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, e, _e_devicemgr_inputgen_mouse_button_event_free, NULL);
+
+   return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+}
+
+static int
+_e_devicemgr_inputgen_touch_update_event(uint32_t x, uint32_t y, uint32_t finger, char *identifier)
+{
+   Ecore_Event_Mouse_Move *e;
+
+   e = calloc(1, sizeof(Ecore_Event_Mouse_Move));
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES);
+
+   e->window = e_comp->ee_win;
+   e->event_window = e_comp->ee_win;
+   e->root_window = e_comp->ee_win;
+   e->timestamp = (int)(ecore_time_get() * 1000);
+   e->same_screen = 1;
+
+   e->x = x;
+   e->y = y;
+   e->root.x = e->x;
+   e->root.y = e->y;
+
+   e->multi.device = finger;
+   e->multi.radius = 1;
+   e->multi.radius_x = 1;
+   e->multi.radius_y = 1;
+   e->multi.pressure = 1.0;
+   e->multi.angle = 0.0;
+
+   e->multi.x = e->x;
+   e->multi.y = e->y;
+   e->multi.root.x = e->x;
+   e->multi.root.y = e->y;
+   e->dev = ecore_device_ref(e_input_evdev_get_ecore_device(identifier, ECORE_DEVICE_CLASS_TOUCH));
+
+   DMDBG("Generate touch move event: device: %d (%d, %d)\n", e->multi.device, e->x, e->y);
+
+   ecore_event_add(ECORE_EVENT_MOUSE_MOVE, e, _e_devicemgr_inputgen_mouse_move_event_free, NULL);
+
+   return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+}
+
+int
+e_devicemgr_inputgen_add(struct wl_client *client, struct wl_resource *resource, uint32_t clas, const char *name)
+{
+   int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+
+   if (clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD)
+     ret = _e_devicemgr_inputgen_create_device(ECORE_DEVICE_CLASS_KEYBOARD, client, name);
+   if (clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_MOUSE)
+     ret = _e_devicemgr_inputgen_create_device(ECORE_DEVICE_CLASS_MOUSE, client, name);
+   if (clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_TOUCHSCREEN)
+     ret = _e_devicemgr_inputgen_create_device(ECORE_DEVICE_CLASS_TOUCH, client, name);
+
+   if (ret == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE)
+     {
+        _e_devicemgr_inputgen_client_add(client, clas);
+        _e_devicemgr_inputgen_resource_add(resource, name);
+     }
+
+   return ret;
+}
+
+void
+e_devicemgr_inputgen_remove(struct wl_client *client, struct wl_resource *resource, uint32_t clas)
+{
+   Eina_List *l, *l_next;
+   E_Devicemgr_Inputgen_Client_Global_Data *data;
+   struct wl_listener *listener;
+
+   if (clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD)
+     _e_devicemgr_inputgen_client_del(client, TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD);
+   if (clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_MOUSE)
+     _e_devicemgr_inputgen_client_del(client, TIZEN_INPUT_DEVICE_MANAGER_CLAS_MOUSE);
+   if (clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_TOUCHSCREEN)
+     _e_devicemgr_inputgen_client_del(client, TIZEN_INPUT_DEVICE_MANAGER_CLAS_TOUCHSCREEN);
+
+   EINA_LIST_FOREACH_SAFE(e_devicemgr->watched_clients, l, l_next, data)
+     {
+        if (data && data->client == client && !data->clas)
+          {
+             listener = wl_client_get_destroy_listener(client,
+                        _e_devicemgr_inputgen_client_cb_destroy);
+             if (listener)
+               {
+                  wl_list_remove(&listener->link);
+                  E_FREE(listener);
+               }
+
+             e_devicemgr->watched_clients =
+                eina_list_remove_list(e_devicemgr->watched_clients, l);
+             E_FREE(data);
+
+             break;
+          }
+     }
+
+   _e_devicemgr_inputgen_resource_del(resource);
+}
+
+
+int
+e_devicemgr_inputgen_generate_key(struct wl_client *client, struct wl_resource *resource, const char *keyname, Eina_Bool pressed)
+{
+   Eina_List *l;
+   E_Devicemgr_Inputgen_Device_Data *ddata;
+   char *name, *identifier = NULL;
+   int ret;
+
+   name = _e_devicemgr_inputgen_name_get(resource);
+
+   if (!_e_devicemgr_inputgen_device_check(name, ECORE_DEVICE_CLASS_KEYBOARD))
+     {
+        DMWRN("generate is not init\n");
+        return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
+     }
+   if (!e_comp_wl->xkb.keymap)
+     {
+        DMWRN("keymap is not ready\n");
+        return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
+     }
+
+   EINA_LIST_FOREACH(e_devicemgr->inputgen.kbd_list, l, ddata)
+     {
+        if (!strncmp(ddata->name, name, UINPUT_MAX_NAME_SIZE))
+          {
+             identifier = ddata->identifier;
+             break;
+          }
+     }
+
+   ret = _e_devicemgr_inputgen_key_event_add(keyname, pressed, identifier);
+   return ret;
+}
+
+int
+e_devicemgr_inputgen_generate_pointer(struct wl_client *client, struct wl_resource *resource, uint32_t type, uint32_t x, uint32_t y, uint32_t button)
+{
+   int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+   Eina_Bool state;
+   Eina_List *l;
+   E_Devicemgr_Inputgen_Device_Data *ddata;
+   char *name, *identifier = NULL;
+
+   name = _e_devicemgr_inputgen_name_get(resource);
+
+   if (!_e_devicemgr_inputgen_device_check(name, ECORE_DEVICE_CLASS_MOUSE))
+     {
+        DMWRN("generate is not init\n");
+        return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
+     }
+
+   EINA_LIST_FOREACH(e_devicemgr->inputgen.ptr_list, l, ddata)
+     {
+        if (!strncmp(ddata->name, name, UINPUT_MAX_NAME_SIZE))
+          {
+             identifier = ddata->identifier;
+             break;
+          }
+     }
+
+   if (type == TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE)
+      ret = _e_devicemgr_inputgen_mouse_move_event(x, y, identifier);
+   else
+     {
+        state = (type == TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN) ?
+                EINA_TRUE : EINA_FALSE;
+        ret = _e_devicemgr_inputgen_mouse_button_event(state, x, y, button, identifier);
+     }
+
+   return ret;
+}
+
+int
+e_devicemgr_inputgen_generate_touch(struct wl_client *client, struct wl_resource *resource, uint32_t type, uint32_t x, uint32_t y, uint32_t finger)
+{
+   int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+   Eina_List *l;
+   E_Devicemgr_Inputgen_Device_Data *ddata;
+   char *name, *identifier = NULL;
+
+   name = _e_devicemgr_inputgen_name_get(resource);
+
+   if (!_e_devicemgr_inputgen_device_check(name, ECORE_DEVICE_CLASS_TOUCH))
+     {
+        DMWRN("generate is not init\n");
+        return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
+     }
+
+   EINA_LIST_FOREACH(e_devicemgr->inputgen.touch_list, l, ddata)
+     {
+        if (!strncmp(ddata->name, name, UINPUT_MAX_NAME_SIZE))
+          {
+             identifier = ddata->identifier;
+             break;
+          }
+     }
+
+   switch(type)
+     {
+        case TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN:
+           ret = _e_devicemgr_inputgen_touch_update_event(x, y, finger, identifier);
+           ret = _e_devicemgr_inputgen_touch_event(type, x, y, finger, identifier);
+           break;
+        case TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END:
+           ret = _e_devicemgr_inputgen_touch_event(type, x, y, finger, identifier);
+           break;
+        case TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE:
+           ret = _e_devicemgr_inputgen_touch_update_event(x, y, finger, identifier);
+           break;
+     }
+
+   return ret;
+}
+
+
+void
+e_devicemgr_inputgen_get_device_info(E_Devicemgr_Input_Device *dev)
+{
+   E_Devicemgr_Inputgen_Device_Data *ddata;
+   Eina_List **dev_list, *l;
+
+   if (dev->clas == ECORE_DEVICE_CLASS_NONE ||
+       dev->clas == ECORE_DEVICE_CLASS_SEAT)
+     return;
+
+   dev_list = _e_devicemgr_inputgen_list_get(dev->clas);
+   EINA_LIST_FOREACH(*dev_list, l, ddata)
+     {
+        if (!strncmp(ddata->name, dev->name, strlen(dev->name)))
+          {
+             if (!ddata->identifier)
+               {
+                  ddata->identifier = (char *)eina_stringshare_add(dev->identifier);
+               }
+          }
+     }
+}
+
+
+#define DM_IOCTL_SET_BIT(fd, bit, val) \
+    ret = ioctl(fd, bit, val); \
+    if (ret) DMWRN("Failed to set %s to fd(%d) (ret: %d)\n", #val, fd, ret)
+
+int
+e_devicemgr_create_virtual_device(Ecore_Device_Class clas, const char *name)
+{
+   int ret;
+   int uinp_fd = -1;
+   struct uinput_user_dev uinp;
+
+   memset(&uinp, 0, sizeof(uinp));
+   strncpy(uinp.name, name, UINPUT_MAX_NAME_SIZE - 1);
+   uinp.id.version = 4;
+   uinp.id.bustype = BUS_VIRTUAL;
+
+   uinp_fd = open("/dev/uinput", O_WRONLY | O_NDELAY);
+   if (uinp_fd < 0)
+     {
+        DMWRN("Failed to open /dev/uinput: (%d)\n", uinp_fd);
+        goto fail_create_device;
+     }
+
+   if (ECORE_DEVICE_CLASS_KEYBOARD == clas)
+     {
+       /* key device setup */
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_EVBIT, EV_KEY);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_EVBIT, EV_SYN);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_EVBIT, EV_MSC);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_MSCBIT, MSC_SCAN);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_KEYBIT, KEY_ESC);
+     }
+   else if (ECORE_DEVICE_CLASS_MOUSE == clas)
+     {
+       /* mouse device setup */
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_EVBIT, EV_KEY);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_EVBIT, EV_SYN);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_EVBIT, EV_MSC);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_EVBIT, EV_REL);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_MSCBIT, MSC_SCAN);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_KEYBIT, BTN_LEFT);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_RELBIT, BTN_RIGHT);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_RELBIT, BTN_MIDDLE);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_RELBIT, REL_X);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_RELBIT, REL_Y);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_RELBIT, REL_WHEEL);
+     }
+   else if (ECORE_DEVICE_CLASS_TOUCH == clas)
+     {
+       /* touch device setup */
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_EVBIT, EV_KEY);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_EVBIT, EV_SYN);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_EVBIT, EV_MSC);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_EVBIT, EV_ABS);
+
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_KEYBIT, BTN_TOUCH);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_ABSBIT, ABS_X);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_ABSBIT, ABS_Y);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_ABSBIT, ABS_MT_SLOT);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_ABSBIT, ABS_MT_TOUCH_MAJOR);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_ABSBIT, ABS_MT_TOUCH_MINOR);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_ABSBIT, ABS_MT_WIDTH_MAJOR);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_ABSBIT, ABS_MT_POSITION_X);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_ABSBIT, ABS_MT_POSITION_Y);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_ABSBIT, ABS_MT_TRACKING_ID);
+       DM_IOCTL_SET_BIT(uinp_fd, UI_SET_MSCBIT, MSC_SCAN);
+
+       uinp.absmin[ABS_X] = 0;
+       uinp.absmax[ABS_X] = 1000;
+       uinp.absmin[ABS_Y] = 0;
+       uinp.absmax[ABS_Y] = 1000;
+       uinp.absmin[ABS_MT_SLOT] = 0;
+       uinp.absmax[ABS_MT_SLOT] = 9;
+       uinp.absmin[ABS_MT_TOUCH_MAJOR] = 0;
+       uinp.absmax[ABS_MT_TOUCH_MAJOR] = 255;
+       uinp.absmin[ABS_MT_TOUCH_MINOR] = 0;
+       uinp.absmax[ABS_MT_TOUCH_MINOR] = 255;
+       uinp.absmin[ABS_MT_WIDTH_MAJOR] = 0;
+       uinp.absmax[ABS_MT_WIDTH_MAJOR] = 255;
+       uinp.absmin[ABS_MT_POSITION_X] = 0;
+       uinp.absmax[ABS_MT_POSITION_X] = 1000;
+       uinp.absmin[ABS_MT_POSITION_Y] = 0;
+       uinp.absmax[ABS_MT_POSITION_Y] = 1000;
+       uinp.absmin[ABS_MT_TRACKING_ID] = 0;
+       uinp.absmax[ABS_MT_TRACKING_ID] = 65535;
+       uinp.absmin[ABS_MT_ORIENTATION] = 0;
+       uinp.absmax[ABS_MT_ORIENTATION] = 2;
+     }
+   else
+     goto fail_create_device;
+
+   ret = write(uinp_fd, &uinp, sizeof(struct uinput_user_dev));
+
+   if (ret < 0)
+     {
+        DMWRN("Failed to write to uinput fd ! (fd:%d, type:%d, name:%s)\n", uinp_fd, clas, name);
+        goto fail_create_device;
+     }
+
+   if (ioctl(uinp_fd, UI_DEV_CREATE))
+     {
+       DMWRN("Failed to create a virtual device ! (type:%d, name:%s)\n", clas, name);
+       goto fail_create_device;
+     }
+
+   return uinp_fd;
+
+fail_create_device:
+
+   if (uinp_fd >= 0)
+     close(uinp_fd);
+
+   return -1;
+}
+
+void
+e_devicemgr_destroy_virtual_device(int uinp_fd)
+{
+   int ret;
+   ret = ioctl(uinp_fd, UI_DEV_DESTROY, NULL);
+   if (ret) DMWRN("Failed destroy fd: %d (ret: %d)\n", uinp_fd, ret);
+   close(uinp_fd);
+}
diff --git a/src/bin/e_devicemgr_private.h b/src/bin/e_devicemgr_private.h
new file mode 100644 (file)
index 0000000..61e34dc
--- /dev/null
@@ -0,0 +1,140 @@
+#include "e.h"
+#include "e_devicemgr.h"
+#ifdef HAVE_CYNARA
+#include <cynara-session.h>
+#include <cynara-client.h>
+#include <cynara-creds-socket.h>
+#include <sys/smack.h>
+#endif
+#include <tizen-extension-server-protocol.h>
+#include <linux/uinput.h>
+
+#ifdef TRACE_INPUT_BEGIN
+#undef TRACE_INPUT_BEGIN
+#endif
+#ifdef TRACE_INPUT_END
+#undef TRACE_INPUT_END
+#endif
+
+#ifdef ENABLE_TTRACE
+#include <ttrace.h>
+
+#define TRACE_INPUT_BEGIN(NAME) traceBegin(TTRACE_TAG_INPUT, "INPUT:DEVMGR:"#NAME)
+#define TRACE_INPUT_END() traceEnd(TTRACE_TAG_INPUT)
+#else
+#define TRACE_INPUT_BEGIN(NAME)
+#define TRACE_INPUT_END()
+#endif
+
+#define DMERR(msg, ARG...) ERR("[%s:%d] "msg, __FUNCTION__, __LINE__, ##ARG)
+#define DMWRN(msg, ARG...) WRN("[%s:%d] "msg, __FUNCTION__, __LINE__, ##ARG)
+#define DMINF(msg, ARG...) INF("[%s:%d] "msg, __FUNCTION__, __LINE__, ##ARG)
+#define DMDBG(msg, ARG...) DBG("[%s:%d] "msg, __FUNCTION__, __LINE__, ##ARG)
+
+#ifdef HAVE_CYNARA
+#include <cynara-session.h>
+#include <cynara-client.h>
+#include <cynara-creds-socket.h>
+#endif
+
+#define INPUT_GENERATOR_DEVICE "Input Generator"
+#define DETENT_DEVICE_NAME "tizen_detent"
+
+typedef struct _E_Devicemgr_Input_Device_User_Data E_Devicemgr_Input_Device_User_Data;
+typedef struct _E_Devicemgr_Inputgen_Client_Data E_Devicemgr_Inputgen_Client_Data;
+typedef struct _E_Devicemgr_Inputgen_Client_Global_Data E_Devicemgr_Inputgen_Client_Global_Data;
+typedef struct _E_Devicemgr_Inputgen_Device_Data E_Devicemgr_Inputgen_Device_Data;
+typedef struct _E_Devicemgr_Inputgen_Resource_Data E_Devicemgr_Inputgen_Resource_Data;
+
+struct _E_Devicemgr_Input_Device_User_Data
+{
+   E_Devicemgr_Input_Device *dev;
+   struct wl_resource *dev_mgr_res;
+   struct wl_resource *seat_res;
+};
+
+struct _E_Devicemgr_Inputgen_Client_Data
+{
+   struct wl_client *client;
+   int ref;
+};
+
+struct _E_Devicemgr_Inputgen_Client_Global_Data
+{
+   struct wl_client *client;
+   unsigned int clas;
+};
+
+struct _E_Devicemgr_Inputgen_Device_Data
+{
+   int uinp_fd;
+   char *identifier;
+   char name[UINPUT_MAX_NAME_SIZE];
+   Eina_List *clients;
+};
+
+struct _E_Devicemgr_Inputgen_Resource_Data
+{
+   struct wl_resource *resource;
+   char name[UINPUT_MAX_NAME_SIZE];
+};
+
+struct _E_Devicemgr_Conf_Edd
+{
+   struct
+   {
+      Eina_Bool button_remap_enable;          // enable feature of remap mouse right button to back key
+      Eina_Bool virtual_key_device_enable;    // create a virtual keyboard device
+      Eina_Bool virtual_mouse_device_enable;  // create a virtual mouse device
+      int back_keycode;                       // keycode of back key
+   } input;
+};
+
+struct _E_Devicemgr_Config_Data
+{
+   E_Config_DD *conf_edd;
+   E_Devicemgr_Conf_Edd *conf;
+};
+
+struct _E_Devicemgr_Wl_Data
+{
+   struct wl_global *global;
+   Eina_List *resources;
+
+#ifdef HAVE_CYNARA
+   cynara *p_cynara;
+   Eina_Bool cynara_initialized;
+#endif
+};
+
+void e_devicemgr_conf_init(E_Devicemgr_Config_Data *dconfig);
+void e_devicemgr_conf_fini(E_Devicemgr_Config_Data *dconfig);
+
+Eina_Bool e_devicemgr_wl_init(void);
+void e_devicemgr_wl_shutdown(void);
+void e_devicemgr_wl_device_add(E_Devicemgr_Input_Device *dev);
+void e_devicemgr_wl_device_del(E_Devicemgr_Input_Device *dev);
+
+Eina_Bool e_devicemgr_block_check_keyboard(Ecore_Event_Key *ev, Eina_Bool pressed);
+Eina_Bool e_devicemgr_block_check_move(Ecore_Event_Mouse_Move *ev);
+Eina_Bool e_devicemgr_block_check_button(Ecore_Event_Mouse_Button *ev, Eina_Bool pressed);
+void e_devicemgr_wl_block_send_expired(struct wl_resource *resource);
+int e_devicemgr_block_add(struct wl_client *client, struct wl_resource *resource, uint32_t clas, uint32_t duration);
+int e_devicemgr_block_remove(struct wl_client *client);
+
+int e_devicemgr_inputgen_add(struct wl_client *client, struct wl_resource *resource, uint32_t clas, const char *name);
+void e_devicemgr_inputgen_remove(struct wl_client *client, struct wl_resource *resource, uint32_t clas);
+int e_devicemgr_inputgen_generate_key(struct wl_client *client, struct wl_resource *resource, const char *keyname, Eina_Bool pressed);
+int e_devicemgr_inputgen_generate_pointer(struct wl_client *client, struct wl_resource *resource, uint32_t type, uint32_t x, uint32_t y, uint32_t button);
+int e_devicemgr_inputgen_generate_touch(struct wl_client *client, struct wl_resource *resource, uint32_t type, uint32_t x, uint32_t y, uint32_t finger);
+void e_devicemgr_inputgen_get_device_info(E_Devicemgr_Input_Device *dev);
+
+int e_devicemgr_create_virtual_device(Ecore_Device_Class clas, const char *name);
+void e_devicemgr_destroy_virtual_device(int uinp_fd);
+
+int e_devicemgr_keycode_from_string(const char *keyname);
+int e_devicemgr_input_pointer_warp(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, wl_fixed_t x, wl_fixed_t y);
+void e_devicemgr_wl_detent_send_event(int detent);
+Eina_Bool e_devicemgr_input_init(void);
+void e_devicemgr_input_shutdown(void);
+
diff --git a/src/bin/e_devicemgr_wl.c b/src/bin/e_devicemgr_wl.c
new file mode 100644 (file)
index 0000000..22d73c0
--- /dev/null
@@ -0,0 +1,540 @@
+#include "e_devicemgr_private.h"
+
+#ifdef HAVE_CYNARA
+#define E_DEVMGR_CYNARA_ERROR_CHECK_GOTO(func_name, ret, label) \
+  do \
+    { \
+       if (EINA_UNLIKELY(CYNARA_API_SUCCESS != ret)) \
+          { \
+             _e_devicemgr_util_cynara_log(func_name, ret); \
+             goto label; \
+          } \
+    } \
+  while (0)
+
+static void
+_e_devicemgr_util_cynara_log(const char *func_name, int err)
+{
+#define CYNARA_BUFSIZE 128
+   char buf[CYNARA_BUFSIZE] = "\0";
+   int ret;
+
+   ret = cynara_strerror(err, buf, CYNARA_BUFSIZE);
+   if (ret != CYNARA_API_SUCCESS)
+     {
+        DMDBG("Failed to cynara_strerror: %d (error log about %s: %d)\n", ret, func_name, err);
+        return;
+     }
+   DMDBG("%s is failed: %s\n", func_name, buf);
+}
+
+static Eina_Bool
+_e_devicemgr_util_do_privilege_check(struct wl_client *client, int socket_fd, const char *rule)
+{
+   int ret, pid;
+   char *clientSmack=NULL, *uid=NULL, *client_session=NULL;
+   Eina_Bool res = EINA_FALSE;
+
+   /* If initialization of cynara has been failed, let's not to do further permission checks. */
+   if (e_devicemgr->wl_data->p_cynara == NULL && e_devicemgr->wl_data->cynara_initialized) return EINA_TRUE;
+
+   ret = cynara_creds_socket_get_client(socket_fd, CLIENT_METHOD_SMACK, &clientSmack);
+   E_DEVMGR_CYNARA_ERROR_CHECK_GOTO("cynara_creds_socket_get_client", ret, finish);
+
+   ret = cynara_creds_socket_get_user(socket_fd, USER_METHOD_UID, &uid);
+   E_DEVMGR_CYNARA_ERROR_CHECK_GOTO("cynara_creds_socket_get_user", ret, finish);
+
+   ret = cynara_creds_socket_get_pid(socket_fd, &pid);
+   E_DEVMGR_CYNARA_ERROR_CHECK_GOTO("cynara_creds_socket_get_pid", ret, finish);
+
+   client_session = cynara_session_from_pid(pid);
+
+   ret = cynara_check(e_devicemgr->wl_data->p_cynara, clientSmack, client_session, uid, rule);
+
+   if (CYNARA_API_ACCESS_ALLOWED == ret)
+        res = EINA_TRUE;
+
+finish:
+   E_FREE(client_session);
+   E_FREE(clientSmack);
+   E_FREE(uid);
+
+   return res;
+}
+#endif
+
+static void
+_e_devicemgr_wl_device_cb_axes_select(struct wl_client *client, struct wl_resource *resource, struct wl_array *axes)
+{
+   return;
+}
+
+static void
+_e_devicemgr_wl_device_cb_release(struct wl_client *client, struct wl_resource *resource)
+{
+   wl_resource_destroy(resource);
+}
+
+static const struct tizen_input_device_interface _e_devicemgr_wl_device_interface =
+{
+   _e_devicemgr_wl_device_cb_axes_select,
+   _e_devicemgr_wl_device_cb_release,
+};
+
+static void
+_e_devicemgr_wl_device_cb_unbind(struct wl_resource *resource)
+{
+   E_Devicemgr_Input_Device *dev;
+   E_Devicemgr_Input_Device_User_Data *device_user_data;
+
+   if (!(device_user_data = wl_resource_get_user_data(resource))) return;
+
+   dev = device_user_data->dev;
+
+   device_user_data->dev = NULL;
+   device_user_data->dev_mgr_res = NULL;
+   device_user_data->seat_res = NULL;
+   E_FREE(device_user_data);
+
+   if (!dev) return;
+
+   dev->resources = eina_list_remove(dev->resources, resource);
+}
+
+void
+e_devicemgr_wl_device_add(E_Devicemgr_Input_Device *dev)
+{
+   struct wl_resource *res, *seat_res, *dev_mgr_res;
+   Eina_List *l, *ll;
+   uint32_t serial;
+   struct wl_client *wc;
+   E_Devicemgr_Input_Device_User_Data *device_user_data;
+   struct wl_array axes;
+
+   /* TODO: find the seat corresponding to event */
+   serial = wl_display_next_serial(e_comp_wl->wl.disp);
+   wl_array_init(&axes);
+
+   EINA_LIST_FOREACH(e_comp_wl->seat.resources, l, seat_res)
+     {
+        wc = wl_resource_get_client(seat_res);
+
+        EINA_LIST_FOREACH(e_devicemgr->wl_data->resources, ll, dev_mgr_res)
+          {
+             if (wl_resource_get_client(dev_mgr_res) != wc) continue;
+             res = wl_resource_create(wc, &tizen_input_device_interface, 1, 0);
+             if (!res)
+                 {
+                  DMERR("Could not create tizen_input_device resource");
+                  break;
+                }
+
+             device_user_data = E_NEW(E_Devicemgr_Input_Device_User_Data, 1);
+             if (!device_user_data)
+               {
+                  DMERR("Failed to allocate memory for input device user data\n");
+                  break;
+               }
+             device_user_data->dev = dev;
+             device_user_data->dev_mgr_res = dev_mgr_res;
+             device_user_data->seat_res = seat_res;
+
+             dev->resources = eina_list_append(dev->resources, res);
+             wl_resource_set_implementation(res, &_e_devicemgr_wl_device_interface, device_user_data,
+                                            _e_devicemgr_wl_device_cb_unbind);
+             tizen_input_device_manager_send_device_add(dev_mgr_res, serial, dev->identifier, res, seat_res);
+             tizen_input_device_send_device_info(res, dev->name, dev->clas, dev->subclas, &axes);
+          }
+     }
+}
+
+void
+e_devicemgr_wl_device_del(E_Devicemgr_Input_Device *dev)
+{
+   struct wl_client *wc;
+   Eina_List *l, *ll, *lll;
+   struct wl_resource *res, *seat_res, *dev_mgr_res;
+   uint32_t serial;
+   E_Devicemgr_Input_Device_User_Data *device_user_data;
+
+   serial = wl_display_next_serial(e_comp_wl->wl.disp);
+
+   /* TODO: find the seat corresponding to event */
+   EINA_LIST_FOREACH(e_comp_wl->seat.resources, l, seat_res)
+     {
+        wc = wl_resource_get_client(seat_res);
+        EINA_LIST_FOREACH(e_devicemgr->wl_data->resources, ll, dev_mgr_res)
+          {
+             if (wl_resource_get_client(dev_mgr_res) != wc) continue;
+             EINA_LIST_FOREACH(dev->resources, lll, res)
+               {
+                  if (wl_resource_get_client(res) != wc) continue;
+                  device_user_data = wl_resource_get_user_data(res);
+                  if (!device_user_data) continue;
+                  if (device_user_data->dev_mgr_res != dev_mgr_res)
+                    continue;
+                  if (device_user_data->seat_res != seat_res)
+                    continue;
+
+                  tizen_input_device_manager_send_device_remove(dev_mgr_res, serial, dev->identifier, res, seat_res);
+               }
+          }
+     }
+
+   EINA_LIST_FREE(dev->resources, res)
+     {
+        device_user_data = wl_resource_get_user_data(res);
+        if (device_user_data)
+          {
+             device_user_data->dev = NULL;
+             device_user_data->dev_mgr_res = NULL;
+             device_user_data->seat_res = NULL;
+             E_FREE(device_user_data);
+          }
+
+        wl_resource_set_user_data(res, NULL);
+     }
+}
+
+void
+e_devicemgr_wl_detent_send_event(int detent)
+{
+   E_Devicemgr_Input_Device *input_dev;
+   struct wl_resource *dev_res;
+   struct wl_client *wc;
+   Eina_List *l, *ll;
+   wl_fixed_t f_value;
+   E_Client *ec;
+
+   ec = e_client_focused_get();
+
+   if (!ec) return;
+   if (e_object_is_del(E_OBJECT(ec))) return;
+   if (ec->ignored) return;
+   if (!ec->comp_data || !ec->comp_data->surface) return;
+
+   f_value = wl_fixed_from_double(detent * 1.0);
+   wc = wl_resource_get_client(ec->comp_data->surface);
+
+   EINA_LIST_FOREACH(e_devicemgr->device_list, l, input_dev)
+     {
+        if (!strncmp(input_dev->name, DETENT_DEVICE_NAME, sizeof(DETENT_DEVICE_NAME)))
+          {
+             EINA_LIST_FOREACH(input_dev->resources, ll, dev_res)
+               {
+                  if (wl_resource_get_client(dev_res) != wc) continue;
+                  tizen_input_device_send_axis(dev_res, TIZEN_INPUT_DEVICE_AXIS_TYPE_DETENT, f_value);
+               }
+          }
+     }
+}
+
+void
+e_devicemgr_wl_block_send_expired(struct wl_resource *resource)
+{
+   if (!resource) return;
+   tizen_input_device_manager_send_block_expired(resource);
+}
+
+static void
+_e_devicemgr_wl_cb_block_events(struct wl_client *client, struct wl_resource *resource, uint32_t serial, uint32_t clas, uint32_t duration)
+{
+   int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+
+#ifdef HAVE_CYNARA
+   if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
+                                                          "http://tizen.org/privilege/internal/inputdevice.block"))
+     {
+        DMERR("block_events request:priv check failed");
+        tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
+        return;
+     }
+#endif
+
+   ret = e_devicemgr_block_add(client, resource, clas, duration);
+   tizen_input_device_manager_send_error(resource, ret);
+}
+
+static void
+_e_devicemgr_wl_cb_unblock_events(struct wl_client *client, struct wl_resource *resource, uint32_t serial)
+{
+   int ret;
+
+#ifdef HAVE_CYNARA
+   if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
+                                                          "http://tizen.org/privilege/internal/inputdevice.block"))
+     {
+        DMERR("unblock_events request:priv check failed");
+        tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
+        return;
+     }
+#endif
+
+   ret = e_devicemgr_block_remove(client);
+   tizen_input_device_manager_send_error(resource, ret);
+}
+
+static void
+_e_devicemgr_wl_cb_init_generator(struct wl_client *client, struct wl_resource *resource, uint32_t clas)
+{
+   int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+
+#ifdef HAVE_CYNARA
+   if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
+                                                          "http://tizen.org/privilege/inputgenerator"))
+     {
+        DMERR("init_generator request:priv check failed");
+        tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
+        return;
+     }
+#endif
+
+   ret = e_devicemgr_inputgen_add(client, resource, clas, INPUT_GENERATOR_DEVICE);
+   tizen_input_device_manager_send_error(resource, ret);
+}
+
+static void
+_e_devicemgr_wl_cb_init_generator_with_name(struct wl_client *client, struct wl_resource *resource, uint32_t clas, const char *name)
+{
+   int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+
+#ifdef HAVE_CYNARA
+   if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
+                                                          "http://tizen.org/privilege/inputgenerator"))
+     {
+        DMERR("init_generator_with_name request:priv check failed");
+        tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
+        return;
+     }
+#endif
+
+   ret = e_devicemgr_inputgen_add(client, resource, clas, name);
+   tizen_input_device_manager_send_error(resource, ret);
+}
+
+static void
+_e_devicemgr_wl_cb_deinit_generator(struct wl_client *client, struct wl_resource *resource, uint32_t clas)
+{
+   int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+
+#ifdef HAVE_CYNARA
+   if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
+                                                          "http://tizen.org/privilege/inputgenerator"))
+     {
+        DMERR("deinit_generator request:priv check failed");
+        tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
+        return;
+     }
+#endif
+
+   e_devicemgr_inputgen_remove(client, resource, clas);
+   tizen_input_device_manager_send_error(resource, ret);
+}
+
+static void
+_e_devicemgr_wl_cb_generate_key(struct wl_client *client, struct wl_resource *resource, const char *keyname, uint32_t pressed)
+{
+   int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+
+#ifdef HAVE_CYNARA
+   if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
+                                                          "http://tizen.org/privilege/inputgenerator"))
+     {
+        DMERR("generate_key request:priv check failed");
+        tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
+        return;
+     }
+#endif
+
+   ret = e_devicemgr_inputgen_generate_key(client, resource, keyname, (Eina_Bool)!!pressed);
+   tizen_input_device_manager_send_error(resource, ret);
+}
+
+static void
+_e_devicemgr_wl_cb_generate_pointer(struct wl_client *client, struct wl_resource *resource, uint32_t type, uint32_t x, uint32_t y, uint32_t button)
+{
+   int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+
+#ifdef HAVE_CYNARA
+   if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
+                                                          "http://tizen.org/privilege/inputgenerator"))
+     {
+        DMERR("_generate_pointer request:priv check failed");
+        tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
+        return;
+     }
+#endif
+
+   ret = e_devicemgr_inputgen_generate_pointer(client, resource, type, x, y, button);
+   tizen_input_device_manager_send_error(resource, ret);
+}
+
+static void
+_e_devicemgr_wl_cb_generate_touch(struct wl_client *client, struct wl_resource *resource, uint32_t type, uint32_t x, uint32_t y, uint32_t finger)
+{
+   int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+
+#ifdef HAVE_CYNARA
+   if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client), "http://tizen.org/privilege/inputgenerator"))
+     {
+        DMERR("_e_input_devmgr_cb_generate_touch:priv check failed");
+        tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
+        return;
+     }
+#endif
+
+   ret = e_devicemgr_inputgen_generate_touch(client, resource, type, x, y, finger);
+   tizen_input_device_manager_send_error(resource, ret);
+}
+
+static void
+_e_devicemgr_wl_cb_pointer_warp(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, wl_fixed_t x, wl_fixed_t y)
+{
+   int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+
+   ret = e_devicemgr_input_pointer_warp(client, resource, surface, x, y);
+
+   tizen_input_device_manager_send_error(resource, ret);
+}
+
+static void
+_e_devicemgr_wl_cb_destroy(struct wl_client *client, struct wl_resource *resource)
+{
+   wl_resource_destroy(resource);
+}
+
+static const struct tizen_input_device_manager_interface _e_devicemgr_wl_implementation = {
+   _e_devicemgr_wl_cb_block_events,
+   _e_devicemgr_wl_cb_unblock_events,
+   _e_devicemgr_wl_cb_init_generator,
+   _e_devicemgr_wl_cb_deinit_generator,
+   _e_devicemgr_wl_cb_generate_key,
+   _e_devicemgr_wl_cb_generate_pointer,
+   _e_devicemgr_wl_cb_generate_touch,
+   _e_devicemgr_wl_cb_pointer_warp,
+   _e_devicemgr_wl_cb_init_generator_with_name,
+   _e_devicemgr_wl_cb_destroy,
+};
+
+static void
+_e_devicemgr_wl_cb_unbind(struct wl_resource *resource)
+{
+   if(!e_comp_wl) return;
+
+   e_devicemgr->wl_data->resources = eina_list_remove(e_devicemgr->wl_data->resources, resource);
+}
+
+static void
+_e_devicemgr_wl_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
+{
+   struct wl_resource *res, *seat_res, *device_res;
+   Eina_List *l;
+   uint32_t serial;
+   E_Devicemgr_Input_Device *dev;
+   struct wl_array axes;
+   E_Devicemgr_Input_Device_User_Data *device_user_data;
+
+   if (!(res = wl_resource_create(client, &tizen_input_device_manager_interface, version, id)))
+     {
+        DMERR("Could not create tizen_input_device_manager_interface resource: %m");
+        wl_client_post_no_memory(client);
+        return;
+     }
+
+   e_devicemgr->wl_data->resources = eina_list_append(e_devicemgr->wl_data->resources, res);
+
+   wl_resource_set_implementation(res, &_e_devicemgr_wl_implementation, NULL,
+                                  _e_devicemgr_wl_cb_unbind);
+
+   EINA_LIST_FOREACH(e_comp_wl->seat.resources, l, seat_res)
+     {
+        if (wl_resource_get_client(seat_res) != client) continue;
+
+        wl_array_init(&axes);
+        serial = wl_display_next_serial(e_comp_wl->wl.disp);
+
+        EINA_LIST_FOREACH(e_devicemgr->device_list, l, dev)
+          {
+             device_res = wl_resource_create(client, &tizen_input_device_interface, 1, 0);
+             if (!device_res)
+               {
+                  DMERR("Could not create tizen_input_device resource: %m");
+                  return;
+               }
+             device_user_data = E_NEW(E_Devicemgr_Input_Device_User_Data, 1);
+             if (!device_user_data)
+               {
+                  DMERR("Failed to allocate memory for input device user data\n");
+                  return;
+               }
+             device_user_data->dev = dev;
+             device_user_data->dev_mgr_res = res;
+             device_user_data->seat_res = seat_res;
+
+             dev->resources = eina_list_append(dev->resources, device_res);
+
+             wl_resource_set_implementation(device_res, &_e_devicemgr_wl_device_interface, device_user_data,
+                                            _e_devicemgr_wl_device_cb_unbind);
+
+             tizen_input_device_manager_send_device_add(res, serial, dev->identifier, device_res, seat_res);
+             tizen_input_device_send_device_info(device_res, dev->name, dev->clas, dev->subclas, &axes);
+          }
+     }
+}
+
+Eina_Bool
+e_devicemgr_wl_init(void)
+{
+   if (!e_comp_wl) return EINA_FALSE;
+   if (!e_comp_wl->wl.disp) return EINA_FALSE;
+
+   if (e_devicemgr->wl_data) return EINA_TRUE;
+
+   e_devicemgr->wl_data = E_NEW(E_Devicemgr_Wl_Data, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e_devicemgr->wl_data, EINA_FALSE);
+
+   /* try to add tizen_input_device_manager to wayland globals */
+   e_devicemgr->wl_data->global = wl_global_create(e_comp_wl->wl.disp,
+                                                   &tizen_input_device_manager_interface, 2,
+                                                   NULL, _e_devicemgr_wl_cb_bind);
+   if (!e_devicemgr->wl_data->global)
+     {
+        DMERR("Could not add tizen_input_device_manager to wayland globals");
+        return EINA_FALSE;
+     }
+   e_devicemgr->wl_data->resources = NULL;
+
+   /* initialization of cynara for checking privilege */
+#ifdef HAVE_CYNARA
+   int ret;
+
+   ret = cynara_initialize(&e_devicemgr->wl_data->p_cynara, NULL);
+   if (EINA_UNLIKELY(CYNARA_API_SUCCESS != ret))
+     {
+        _e_devicemgr_util_cynara_log("cynara_initialize", ret);
+        e_devicemgr->wl_data->p_cynara = NULL;
+     }
+   e_devicemgr->wl_data->cynara_initialized = EINA_TRUE;
+#endif
+
+   return EINA_TRUE;
+}
+
+void
+e_devicemgr_wl_shutdown(void)
+{
+   if (!e_devicemgr->wl_data) return;
+   /* destroy the global seat resource */
+   if (e_devicemgr->wl_data->global)
+     wl_global_destroy(e_devicemgr->wl_data->global);
+   e_devicemgr->wl_data->global = NULL;
+
+   /* deinitialization of cynara if it has been initialized */
+#ifdef HAVE_CYNARA
+   if (e_devicemgr->wl_data->p_cynara) cynara_finish(e_devicemgr->wl_data->p_cynara);
+   e_devicemgr->wl_data->cynara_initialized = EINA_FALSE;
+#endif
+
+   E_FREE(e_devicemgr->wl_data);
+}
+
index e61559b..939754e 100644 (file)
@@ -83,3 +83,4 @@
 #include "e_input.h"
 #include "e_dbus_conn.h"
 #include "e_xdg_shell_v6.h"
+#include "e_devicemgr.h"
index 454adfc..0bbd9fe 100644 (file)
@@ -725,7 +725,7 @@ _cb_input_device_info_get(const Eldbus_Message *msg)
    const char *name = NULL, *text = NULL;
    Eldbus_Message_Iter *array, *eldbus_msg;
    Eina_Bool res;
-   E_Comp_Wl_Input_Device *dev = NULL;
+   E_Devicemgr_Input_Device *dev = NULL;
 
    res = eldbus_message_error_get(msg, &name, &text);
    EINA_SAFETY_ON_TRUE_GOTO(res, finish);
@@ -749,7 +749,7 @@ _cb_input_device_info_get(const Eldbus_Message *msg)
              continue;
           }
 
-        dev = E_NEW(E_Comp_Wl_Input_Device, 1);
+        dev = E_NEW(E_Devicemgr_Input_Device, 1);
         EINA_SAFETY_ON_NULL_GOTO(dev, finish);
 
         dev->name = strdup(dev_name);
@@ -1164,7 +1164,7 @@ _e_info_client_proc_compobjs_info(int argc, char **argv)
 static void
 _e_info_client_proc_input_device_info(int argc, char **argv)
 {
-   E_Comp_Wl_Input_Device *dev;
+   E_Devicemgr_Input_Device *dev;
    Eina_List *l;
    int i = 0;
 
index 8c12a00..5aa755f 100644 (file)
@@ -698,13 +698,11 @@ _input_msg_clients_append(Eldbus_Message_Iter *iter)
 {
    Eldbus_Message_Iter *array_of_input;
    Eina_List *l;
-   E_Comp_Wl_Data *cdata;
-   E_Comp_Wl_Input_Device *dev;
+   E_Devicemgr_Input_Device *dev;
 
    eldbus_message_iter_arguments_append(iter, "a("VALUE_TYPE_FOR_INPUTDEV")", &array_of_input);
 
-   cdata = e_comp->wl_comp_data;
-   EINA_LIST_FOREACH(cdata->input_device_manager.device_list, l, dev)
+   EINA_LIST_FOREACH(e_devicemgr->device_list, l, dev)
      {
         Eldbus_Message_Iter *struct_of_input;
 
index 8516a91..de33d66 100644 (file)
@@ -622,6 +622,15 @@ main(int argc, char **argv)
    _e_main_shutdown_push(_e_main_screens_shutdown);
    TRACE_DS_END();
 
+   TSB("E_Devicemgr Init");
+   if (!e_devicemgr_init())
+     {
+        e_error_message_show(_("Enlightenment cannot set up its device_manager system.\n"));
+        goto failed;
+     }
+   TSE("E_Devicemgr Init Done");
+   _e_main_shutdown_push(e_devicemgr_shutdown);
+
    TSB("E_Keyrouter Init");
    if (!e_keyrouter_init())
      {