From 788720dde31116cf4bf55f38aa9cd3521c18a264 Mon Sep 17 00:00:00 2001 From: JengHyun Kang Date: Mon, 16 Jul 2018 17:09:00 +0900 Subject: [PATCH] input_generator: add a new initialize API work synchronously Change-Id: I96636390549cbd3dce008b97b2e8f3f8082f6e3c --- include/efl_util.h.in | 25 +++++ src/efl_util.c | 302 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 321 insertions(+), 6 deletions(-) diff --git a/include/efl_util.h.in b/include/efl_util.h.in index e8c82d9..6b72fb7 100644 --- a/include/efl_util.h.in +++ b/include/efl_util.h.in @@ -303,6 +303,31 @@ API efl_util_inputgen_h efl_util_input_initialize_generator_with_name(unsigned i /** * @platform + * @brief Initializes the system, checks if input generated functions are supported and then open events generator devices synchronously. + * @since_tizen 5.0 + * @privlevel platform + * @privilege %http://tizen.org/privilege/inputgenerator + * @remarks The specific error code can be obtained using the get_last_result() method. Error codes are described in Exception section. + * @remarks @a dev_type is changed into the unsigned int to perform bitwise operations. + * @remarks If the @a name is NULL, it will be set to "Input Generator" + * @remarks The returned object should be released with efl_util_input_deinitialize_generator(). + * @param[in] dev_type The device type to generate events, values of #efl_util_input_device_type_e combined with bitwise 'or'\n + * Example: #EFL_UTIL_INPUT_DEVTYPE_TOUCHSCREEN | #EFL_UTIL_INPUT_DEVTYPE_KEYBOARD + * @param[in] name The device name (maximum 31 characters, can be NULL) + * @return #efl_util_inputgen_h on success, otherwise @c NULL + * @retval #efl_util_inputgen_h The input generator handle + * @exception #EFL_UTIL_ERROR_NONE Successful + * @exception #EFL_UTIL_ERROR_INVALID_PARAMETER Invalid parameter + * @exception #EFL_UTIL_ERROR_NO_SUCH_DEVICE No such device or address + * @exception #EFL_UTIL_ERROR_INVALID_OPERATION Function not implemented + * @exception #EFL_UTIL_ERROR_OUT_OF_MEMORY Memory allocation failure + * @exception #EFL_UTIL_ERROR_PERMISSION_DENIED Has no permission to initialize input generator + * @see efl_util_input_deinitialize_generator() + */ +API efl_util_inputgen_h efl_util_input_initialize_generator_with_sync(unsigned int dev_type, const char *name); + +/** + * @platform * @brief Deinitializes system and close opened devices. * @since_tizen $TZ_CFG_VER_24_OR_30$ * @privlevel platform diff --git a/src/efl_util.c b/src/efl_util.c index ae65099..af5f479 100644 --- a/src/efl_util.c +++ b/src/efl_util.c @@ -93,6 +93,8 @@ static inline tizen_profile_t get_tizen_profile() #define LOG_TAG "TIZEN_N_EFL_UTIL" +#define EFL_UTIL_INPUT_GENERATOR_DEFAULT_TIME_OUT 1000 +#define EFL_UTIL_INPUT_GENERATOR_DEFAULT_DISPATCH_TIME_OUT 10 typedef struct _Efl_Util_Wl_Surface_Lv_Info { @@ -164,6 +166,13 @@ typedef struct _Efl_Util_Gesture_Palm_Cover_Grab_Data Efl_Util_Gesture_Common_Grab_Data base; } Efl_Util_Gesture_Palm_Cover_Grab_Data; +typedef struct _Efl_Util_Device_Info +{ + struct tizen_input_device *device; + Ecore_Device_Class clas; + Eina_Stringshare *name; +} Efl_Util_Device_Info; + typedef struct _Efl_Util_Data { /* wayland related stuffs */ @@ -196,6 +205,9 @@ typedef struct _Efl_Util_Data { struct tizen_input_device_manager *devicemgr; int request_notified; + Eina_List *devices; + Eina_List *wait_devices; + struct wl_event_source *wait_timer; } devmgr; struct { @@ -244,6 +256,10 @@ static void _cb_wl_conformant_region(void *data, struct tizen static void _cb_wl_tz_display_policy_brightness_done(void *data, struct tizen_display_policy *tizen_display_policy, struct wl_surface *surface_resource, int32_t brightness, uint32_t state); +static void _cb_device_info(void *data, struct tizen_input_device *tizen_input_device EINA_UNUSED, const char *name, uint32_t clas, uint32_t subclas EINA_UNUSED, struct wl_array *axes EINA_UNUSED); +static void _cb_event_device(void *data EINA_UNUSED, struct tizen_input_device *tizen_input_device EINA_UNUSED, unsigned int serial EINA_UNUSED, const char *name EINA_UNUSED, uint32_t time EINA_UNUSED); +static void _cb_axis(void *data EINA_UNUSED, struct tizen_input_device *tizen_input_device EINA_UNUSED, uint32_t axis_type EINA_UNUSED, wl_fixed_t value EINA_UNUSED); + static void _cb_device_add(void *data EINA_UNUSED, struct tizen_input_device_manager *tizen_input_device_manager EINA_UNUSED, uint32_t serial EINA_UNUSED, const char *identifier EINA_UNUSED, struct tizen_input_device *device EINA_UNUSED, struct wl_seat *seat EINA_UNUSED); static void _cb_device_remove(void *data EINA_UNUSED, struct tizen_input_device_manager *tizen_input_device_manager EINA_UNUSED, uint32_t serial EINA_UNUSED, const char *identifier EINA_UNUSED, struct tizen_input_device *device EINA_UNUSED, struct wl_seat *seat EINA_UNUSED); static void _cb_error(void *data EINA_UNUSED, struct tizen_input_device_manager *tizen_input_device_manager EINA_UNUSED, uint32_t errorcode); @@ -286,6 +302,13 @@ struct tizen_policy_listener _wl_tz_policy_listener = _cb_wl_conformant_region, }; +static const struct tizen_input_device_listener _wl_tz_input_device_listener = +{ + _cb_device_info, + _cb_event_device, + _cb_axis, +}; + struct tizen_input_device_manager_listener _wl_tz_devmgr_listener = { _cb_device_add, @@ -1119,29 +1142,144 @@ struct _efl_util_inputgen_h char name[32]; }; +static Eina_Bool +_efl_util_input_check_wait_device_full(void) +{ + Eina_List *l, *ll, *l_next; + Efl_Util_Device_Info *dev, *wait_dev; + int wait_cnt = 0; + + wait_cnt = eina_list_count(_eflutil.wl.devmgr.wait_devices); + if (wait_cnt <= 0) return EINA_TRUE; + + EINA_LIST_FOREACH(_eflutil.wl.devmgr.devices, l, dev) + { + EINA_LIST_FOREACH_SAFE(_eflutil.wl.devmgr.wait_devices, ll, l_next, wait_dev) + { + if ((dev->clas == wait_dev->clas) && + (!strncmp(dev->name, wait_dev->name, eina_stringshare_strlen(wait_dev->name)))) + { + eina_stringshare_del(wait_dev->name); + _eflutil.wl.devmgr.wait_devices = eina_list_remove_list(_eflutil.wl.devmgr.wait_devices, ll); + free(wait_dev); + + wait_cnt--; + if (wait_cnt <= 0) return EINA_TRUE; + + break; + } + } + } + + return EINA_FALSE; +} + +static Eina_Bool +_efl_util_input_check_wait_device(const char *name, unsigned int type) +{ + Eina_List *l, *l_next; + Efl_Util_Device_Info *wait_dev; + int wait_cnt = 0; + + wait_cnt = eina_list_count(_eflutil.wl.devmgr.wait_devices); + if (wait_cnt <= 0) return EINA_TRUE; + + EINA_LIST_FOREACH_SAFE(_eflutil.wl.devmgr.wait_devices, l, l_next, wait_dev) + { + if ((type == wait_dev->clas) && + (!strncmp(name, wait_dev->name, eina_stringshare_strlen(wait_dev->name)))) + { + eina_stringshare_del(wait_dev->name); + _eflutil.wl.devmgr.wait_devices = eina_list_remove_list(_eflutil.wl.devmgr.wait_devices, l); + free(wait_dev); + + wait_cnt--; + if (wait_cnt <= 0) return EINA_TRUE; + + break; + } + } + + return EINA_FALSE; +} + +static void +_cb_device_info(void *data, struct tizen_input_device *tizen_input_device EINA_UNUSED, const char *name, uint32_t clas, uint32_t subclas EINA_UNUSED, struct wl_array *axes EINA_UNUSED) +{ + Efl_Util_Device_Info *dev; + + if (!(dev = data)) return; + dev->clas = (Ecore_Device_Class)clas; + dev->name = eina_stringshare_add(name); + + if (_eflutil.wl.devmgr.wait_timer && + _efl_util_input_check_wait_device(name, clas)) + { + wl_event_source_remove(_eflutil.wl.devmgr.wait_timer); + _eflutil.wl.devmgr.wait_timer = NULL; + } +} + +/* LCOV_EXCL_START */ +static void +_cb_event_device(void *data EINA_UNUSED, struct tizen_input_device *tizen_input_device EINA_UNUSED, unsigned int serial EINA_UNUSED, const char *name EINA_UNUSED, uint32_t time EINA_UNUSED) +{ + ; +} + +static void +_cb_axis(void *data EINA_UNUSED, struct tizen_input_device *tizen_input_device EINA_UNUSED, uint32_t axis_type EINA_UNUSED, wl_fixed_t value EINA_UNUSED) +{ + ; +} +/* LCOV_EXCL_STOP */ + static void _cb_device_add(void *data EINA_UNUSED, struct tizen_input_device_manager *tizen_input_device_manager EINA_UNUSED, uint32_t serial EINA_UNUSED, const char *identifier EINA_UNUSED, - struct tizen_input_device *device EINA_UNUSED, + struct tizen_input_device *device, struct wl_seat *seat EINA_UNUSED) { - ; + Efl_Util_Device_Info *dev; + + EINA_SAFETY_ON_NULL_RETURN(device); + + dev = (Efl_Util_Device_Info *)calloc(1, sizeof(Efl_Util_Device_Info)); + EINA_SAFETY_ON_NULL_RETURN(dev); + + dev->device = device; + tizen_input_device_add_listener(device, &_wl_tz_input_device_listener, dev); + + _eflutil.wl.devmgr.devices = eina_list_append(_eflutil.wl.devmgr.devices, dev); } -/* LCOV_EXCL_START */ static void _cb_device_remove(void *data EINA_UNUSED, struct tizen_input_device_manager *tizen_input_device_manager EINA_UNUSED, uint32_t serial EINA_UNUSED, const char *identifier EINA_UNUSED, - struct tizen_input_device *device EINA_UNUSED, + struct tizen_input_device *device, struct wl_seat *seat EINA_UNUSED) { - ; + Eina_List *l, *l_next; + Efl_Util_Device_Info *dev; + + EINA_LIST_FOREACH_SAFE(_eflutil.wl.devmgr.devices, l, l_next, dev) + { + if (dev->device == device) + { + if (dev->name) eina_stringshare_del(dev->name); + tizen_input_device_release(dev->device); + + _eflutil.wl.devmgr.devices = eina_list_remove_list(_eflutil.wl.devmgr.devices, l); + free(dev); + + break; + } + } } -/* LCOV_EXCL_STOP */ static void _cb_error(void *data EINA_UNUSED, @@ -1178,6 +1316,81 @@ _efl_util_input_convert_input_generator_error(int ret) } } +/* LCOV_EXCL_START */ +static int +_timer_wait(void *data) +{ + Efl_Util_Device_Info *dev; + + _eflutil.wl.devmgr.request_notified = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES; + + if (eina_list_count(_eflutil.wl.devmgr.wait_devices) > 0) + { + EINA_LIST_FREE(_eflutil.wl.devmgr.wait_devices, dev) + { + eina_stringshare_del(dev->name); + dev->name = NULL; + } + } + + wl_event_source_remove(_eflutil.wl.devmgr.wait_timer); + _eflutil.wl.devmgr.wait_timer = NULL; + + return 1; +} +/* LCOV_EXCL_STOP */ + +static void +_efl_util_input_initialize_wait_device(void) +{ + struct wl_event_loop *loop; + int ret = -1; + + if (_efl_util_input_check_wait_device_full()) return; + + loop = wl_event_loop_create(); + _eflutil.wl.devmgr.wait_timer = wl_event_loop_add_timer(loop, _timer_wait, NULL); + if (_eflutil.wl.devmgr.wait_timer) + ret = wl_event_source_timer_update(_eflutil.wl.devmgr.wait_timer, + EFL_UTIL_INPUT_GENERATOR_DEFAULT_TIME_OUT); + + while (_eflutil.wl.devmgr.wait_timer) + { + wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue); + ret = wl_event_loop_dispatch(loop, EFL_UTIL_INPUT_GENERATOR_DEFAULT_DISPATCH_TIME_OUT); + if (ret != 0) _timer_wait(NULL); + } +} + +static void +_efl_util_input_initialize_append_device(const char *name, Ecore_Device_Class clas) +{ + Efl_Util_Device_Info *dev; + + dev = (Efl_Util_Device_Info *)calloc(1, sizeof(Efl_Util_Device_Info)); + EINA_SAFETY_ON_NULL_RETURN(dev); + + dev->name = eina_stringshare_add(name); + dev->clas = clas; + + _eflutil.wl.devmgr.wait_devices = eina_list_append(_eflutil.wl.devmgr.wait_devices, dev); +} + +static void +_efl_util_input_initialize_add_wait_device(const char *name, unsigned int dev_type) +{ + EINA_SAFETY_ON_NULL_RETURN(name); + + if (dev_type & EFL_UTIL_INPUT_DEVTYPE_TOUCHSCREEN) + _efl_util_input_initialize_append_device(name, ECORE_DEVICE_CLASS_TOUCH); + + if (dev_type & EFL_UTIL_INPUT_DEVTYPE_KEYBOARD) + _efl_util_input_initialize_append_device(name, ECORE_DEVICE_CLASS_KEYBOARD); + + if (dev_type & EFL_UTIL_INPUT_DEVTYPE_POINTER) + _efl_util_input_initialize_append_device(name, ECORE_DEVICE_CLASS_MOUSE); +} + API efl_util_inputgen_h efl_util_input_initialize_generator(unsigned int dev_type) { @@ -1309,6 +1522,83 @@ out: return NULL; } +API efl_util_inputgen_h +efl_util_input_initialize_generator_with_sync(unsigned int dev_type, const char *name) +{ + int ret = EFL_UTIL_ERROR_NONE; + efl_util_inputgen_h inputgen_h = NULL; + unsigned int clas = 0x0; + + if (!dev_type || + dev_type & ~(EFL_UTIL_INPUT_DEVTYPE_TOUCHSCREEN + | EFL_UTIL_INPUT_DEVTYPE_KEYBOARD + | EFL_UTIL_INPUT_DEVTYPE_POINTER)) + { + set_last_result(EFL_UTIL_ERROR_NO_SUCH_DEVICE); + goto out; + } + + inputgen_h = (efl_util_inputgen_h)calloc(1, sizeof(struct _efl_util_inputgen_h)); + if (!inputgen_h) + { + set_last_result(EFL_UTIL_ERROR_OUT_OF_MEMORY); + goto out; + } + + inputgen_h->init_type |= dev_type; + if (name) strncpy(inputgen_h->name, name, 31); + else strncpy(inputgen_h->name, "Input Generator", 31); + + ret = _wl_init(); + if (ret == (int)EINA_FALSE) + { + set_last_result(EFL_UTIL_ERROR_INVALID_PARAMETER); + goto out; + } + + if (dev_type & EFL_UTIL_INPUT_DEVTYPE_TOUCHSCREEN) + clas |= TIZEN_INPUT_DEVICE_MANAGER_CLAS_TOUCHSCREEN; + if (dev_type & EFL_UTIL_INPUT_DEVTYPE_KEYBOARD) + clas |= TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD; + if (dev_type & EFL_UTIL_INPUT_DEVTYPE_POINTER) + clas |= TIZEN_INPUT_DEVICE_MANAGER_CLAS_MOUSE; + + while (!_eflutil.wl.devmgr.devicemgr) + wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue); + + tizen_input_device_manager_init_generator_with_name(_eflutil.wl.devmgr.devicemgr, clas, inputgen_h->name); + + while (_eflutil.wl.devmgr.request_notified == -1) + wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue); + + ret = _efl_util_input_convert_input_generator_error(_eflutil.wl.devmgr.request_notified); + _eflutil.wl.devmgr.request_notified = -1; + + if (ret == EFL_UTIL_ERROR_NONE) + { + _efl_util_input_initialize_add_wait_device(inputgen_h->name, dev_type); + _efl_util_input_initialize_wait_device(); + if (_eflutil.wl.devmgr.request_notified != -1) + { + ret = _efl_util_input_convert_input_generator_error(_eflutil.wl.devmgr.request_notified); + _eflutil.wl.devmgr.request_notified = -1; + } + } + + set_last_result(ret); + if (ret != TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) + goto out; + + return inputgen_h; + +out: + if (inputgen_h) + { + free(inputgen_h); + inputgen_h = NULL; + } + return NULL; +} API int efl_util_input_deinitialize_generator(efl_util_inputgen_h inputgen_h) -- 2.7.4