From bf7e174824d517126b8159e26eec09baab82ff10 Mon Sep 17 00:00:00 2001 From: Jihoon Kim Date: Tue, 8 Mar 2016 20:54:20 +0900 Subject: [PATCH 01/16] Support executable type of IME Change-Id: Ia7e8a69324e457e11bfd9bf49ece7f86811cc46f --- CMakeLists.txt | 1 + packaging/libscl-core.spec | 1 + src/sclcoreimpl.cpp | 23 +++++++++++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index e065ab3..18d7cea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,7 @@ SET(PKGS_CHECK_MODULES isf vconf libscl-common + capi-appfw-application ) IF (with_wayland) diff --git a/packaging/libscl-core.spec b/packaging/libscl-core.spec index 45ae01d..8f50dde 100644 --- a/packaging/libscl-core.spec +++ b/packaging/libscl-core.spec @@ -26,6 +26,7 @@ BuildRequires: pkgconfig(ecore-x) BuildRequires: pkgconfig(x11) %endif BuildRequires: pkgconfig(libscl-common) +BuildRequires: pkgconfig(capi-appfw-application) %description diff --git a/src/sclcoreimpl.cpp b/src/sclcoreimpl.cpp index 66b20a3..84a6935 100644 --- a/src/sclcoreimpl.cpp +++ b/src/sclcoreimpl.cpp @@ -16,6 +16,8 @@ */ #include "sclcoreimpl.h" +#include +#include using namespace scl; @@ -284,6 +286,27 @@ void CSCLCoreImpl::on_run(const sclchar *uuid, const sclchar *display) void CSCLCoreImpl::run() { + m_core_ui.init(); + m_connection.init(); + + if (!m_uuid) { + char *appid = NULL; + app_get_id(&appid); + + LOGD("appid : '%s'\n", appid); + + if (appid) { + m_uuid = strdup(appid); + free(appid); + } + } + + if (!m_display) { + const char *display = getenv("DISPLAY"); + LOGD("display env : '%s'\n", display); + m_display = display ? strdup(display) : strdup(":0"); + } + m_core_ui.run(m_display); m_connection.fini(); -- 2.7.4 From 9987fd786a84130026bdaff935bf670a17b9d2de Mon Sep 17 00:00:00 2001 From: Jihoon Kim Date: Thu, 10 Mar 2016 10:39:10 +0900 Subject: [PATCH 02/16] Remove unused code Change-Id: I9ae56b2f1288d0ec5ea27bdf1e7dc2734fc59ef7 --- src/sclcoreui-efl.cpp | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/src/sclcoreui-efl.cpp b/src/sclcoreui-efl.cpp index 39a50c3..c2ea36b 100644 --- a/src/sclcoreui-efl.cpp +++ b/src/sclcoreui-efl.cpp @@ -50,7 +50,6 @@ struct WaylandKeyboard wlkb = {0}; using namespace scl; - CSCLCoreUIEFL::CSCLCoreUIEFL() { m_initialized = FALSE; @@ -111,36 +110,6 @@ void CSCLCoreUIEFL::set_keyboard_size_hints(SclSize portrait, SclSize landscape) #endif } -const char * extract_themename_from_theme_file_path(const char *filepath) { - static char themename[_POSIX_PATH_MAX] = {0}; - memset(themename, 0x00, sizeof(themename)); - - if (filepath) { - /* There could be more than 1 theme filepath, separated by : */ - char pathstr[_POSIX_PATH_MAX] = {0}; - strncpy(pathstr, filepath, _POSIX_PATH_MAX - 1); - for (int loop = 0;loop < _POSIX_PATH_MAX;loop++) { - if (pathstr[loop] == ':') { - /* FIXME : Let's consider the 1st theme filepath only for now */ - pathstr[loop] = '\0'; - } - } - - if (pathstr[0]) { - const char *filename = ecore_file_file_get(pathstr); - if (filename) { - char *stripname = ecore_file_strip_ext(filename); - if (stripname) { - strncpy(themename, stripname, _POSIX_PATH_MAX - 1); - free(stripname); - } - } - } - } - - return themename; -} - static void language_changed_cb(keynode_t *key, void* data) { char clang[_POSIX_PATH_MAX] = {0}; -- 2.7.4 From e7a366f088fee89c53b9a6110915506931e43d67 Mon Sep 17 00:00:00 2001 From: Jihoon Kim Date: Mon, 14 Mar 2016 07:43:33 +0900 Subject: [PATCH 03/16] Add -Werror build option Change-Id: Idc3e06fe2211c79fbc3f84de8df39978a98cb20f --- packaging/libscl-core.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packaging/libscl-core.spec b/packaging/libscl-core.spec index 8f50dde..a6f470c 100644 --- a/packaging/libscl-core.spec +++ b/packaging/libscl-core.spec @@ -45,8 +45,8 @@ A devel package of libscl-core library that helps developing S/W Keyboard %build -export CFLAGS+=" -DTIZEN_DEBUG_ENABLE" -export CXXFLAGS+=" -DTIZEN_DEBUG_ENABLE" +export CFLAGS+=" -DTIZEN_DEBUG_ENABLE -Werror" +export CXXFLAGS+=" -DTIZEN_DEBUG_ENABLE -Werror" export FFLAGS+=" -DTIZEN_DEBUG_ENABLE" rm -rf CMakeFiles -- 2.7.4 From 6559f718bbca9da5588d5880596ab79d07aa4996 Mon Sep 17 00:00:00 2001 From: Jihoon Kim Date: Tue, 15 Mar 2016 17:34:03 +0900 Subject: [PATCH 04/16] Update package version to 0.4.14 Change-Id: I9720a3fc5a90193e5f0fa131806121fb5c341455 --- packaging/libscl-core.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libscl-core.spec b/packaging/libscl-core.spec index a6f470c..dc29117 100644 --- a/packaging/libscl-core.spec +++ b/packaging/libscl-core.spec @@ -6,7 +6,7 @@ Name: libscl-core Summary: A library for developing software keyboards -Version: 0.4.13 +Version: 0.4.14 Release: 1 Group: Graphics & UI Framework/Input License: Apache-2.0 -- 2.7.4 From e9baabf32b4612127381beba73c9c316a11813c3 Mon Sep 17 00:00:00 2001 From: Jihoon Kim Date: Fri, 8 Apr 2016 09:27:52 +0900 Subject: [PATCH 05/16] Use %license to create license file Change-Id: I79271d76be50155c2619a19915f876bc4b8268de --- packaging/libscl-core.spec | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packaging/libscl-core.spec b/packaging/libscl-core.spec index dc29117..3b02946 100644 --- a/packaging/libscl-core.spec +++ b/packaging/libscl-core.spec @@ -61,8 +61,6 @@ make %{?jobs:-j%jobs} %install rm -rf %{buildroot} -mkdir -p %{buildroot}/usr/share/license -cp LICENSE %{buildroot}/usr/share/license/%{name} %make_install @@ -76,7 +74,7 @@ cp LICENSE %{buildroot}/usr/share/license/%{name} %manifest %{name}.manifest %defattr(-,root,root,-) %{_libdir}/libscl-core.so -/usr/share/license/%{name} +%license LICENSE %files devel %defattr(-,root,root,-) -- 2.7.4 From 31858d998a762c1985478c2cb4ad345d9b10fc22 Mon Sep 17 00:00:00 2001 From: Jihoon Kim Date: Wed, 20 Apr 2016 08:46:12 +0900 Subject: [PATCH 06/16] Add ldconfig in %post and %postun Share library package should call ldconfig in %post and %postun. https://wiki.tizen.org/wiki/Packaging/Guidelines Change-Id: I1f296215ca3fbb7e90ad28a4b340050e63a499ce --- packaging/libscl-core.spec | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packaging/libscl-core.spec b/packaging/libscl-core.spec index 3b02946..f6674d2 100644 --- a/packaging/libscl-core.spec +++ b/packaging/libscl-core.spec @@ -57,7 +57,7 @@ cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DLIB_INSTALL_DIR:PATH=%{_libdir} -Dwi %else cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DLIB_INSTALL_DIR:PATH=%{_libdir} %endif -make %{?jobs:-j%jobs} +make %{?_smp_mflags} %install rm -rf %{buildroot} @@ -66,9 +66,9 @@ rm -rf %{buildroot} -%post +%post -p /sbin/ldconfig -%postun +%postun -p /sbin/ldconfig %files %manifest %{name}.manifest -- 2.7.4 From 4f07df27e4b079bd04b803fdf216747a853e528f Mon Sep 17 00:00:00 2001 From: Jihoon Kim Date: Mon, 25 Apr 2016 16:36:36 +0900 Subject: [PATCH 07/16] Fix indentation Change-Id: I964306dedd066528cbb0f20ea0a4ffd24c083930 --- src/sclconnection.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sclconnection.cpp b/src/sclconnection.cpp index f12daca..fba5e8f 100644 --- a/src/sclconnection.cpp +++ b/src/sclconnection.cpp @@ -269,15 +269,15 @@ void CSCLConnection::update_geometry(sclint x, sclint y, sclint width, sclint he void CSCLConnection::get_surrounding_text(const sclchar *ic_uuid, sclint maxlen_before, sclint maxlen_after) const { if (m_impl) { - m_impl->get_surrounding_text(ic_uuid, maxlen_before, maxlen_after); - } + m_impl->get_surrounding_text(ic_uuid, maxlen_before, maxlen_after); + } } void CSCLConnection::delete_surrounding_text(sclint offset, sclint len) const { if (m_impl) { - m_impl->delete_surrounding_text(offset, len); - } + m_impl->delete_surrounding_text(offset, len); + } } void CSCLConnection::set_candidate_position(sclint left, sclint top) -- 2.7.4 From d91cb5c3f6decef774a789232603afb4e8dc7094 Mon Sep 17 00:00:00 2001 From: Jihoon Kim Date: Tue, 26 Apr 2016 08:48:20 +0900 Subject: [PATCH 08/16] Fix doxygen in header Change-Id: I84cec62269bb2678ca2066ce1c5ef0c84915b6f4 --- src/sclcore.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/sclcore.h b/src/sclcore.h index 6119381..7669d40 100644 --- a/src/sclcore.h +++ b/src/sclcore.h @@ -229,7 +229,7 @@ public: void update_associate_string(const SclCandidateTable &table) const; /** - * @ brief When the input context of ISE is changed, + * @brief When the input context of ISE is changed, * ISE can call this function to notify application * * @param[in] type type of event. @@ -238,7 +238,7 @@ public: void update_input_context(sclu32 type, sclu32 value); /** - * @ brief When the geometry of ISE is changed, + * @brief When the geometry of ISE is changed, * ISE can call this function to notify application * * @param[in] x x position of ISE geometry. @@ -249,7 +249,7 @@ public: void update_geometry(sclint x, sclint y, sclint width, sclint height); /** - * @ brief Request to get surrounding text. + * @brief Request to get surrounding text. * * @param[in] ic_uuid The helper ISE UUID. * @param[in] maxlen_before The max length of before. @@ -258,7 +258,7 @@ public: void get_surrounding_text(const sclchar *ic_uuid, sclint maxlen_before, sclint maxlen_after) const; /** - * @ brief Request to delete surrounding text. + * @brief Request to delete surrounding text. * * @param[in] offset The offset for cursor position. * @param[in] len The length for delete text. @@ -266,7 +266,7 @@ public: void delete_surrounding_text(sclint offset, sclint len) const; /** - * @ brief Set candidate position in screen. + * @brief Set candidate position in screen. * * @param[in] left The x position in screen. * @param[in] top The y position in screen. @@ -274,40 +274,40 @@ public: void set_candidate_position(sclint left, sclint top); /** - * @ brief Set soft candidate style. + * @brief Set soft candidate style. * * @param[in] enable The flag for soft candidate style. */ void enable_soft_candidate(sclboolean enable); /** - * @ brief Request to hide candidate window. + * @brief Request to hide candidate window. */ void candidate_hide(void); /** - * @ brief Request to get candidate window size and position. + * @brief Request to get candidate window size and position. * * @param[in] uuid The helper ISE UUID. */ //void get_candidate_window_geometry (const String &uuid) const; /** - * @ brief Set current keyboard ISE. + * @brief Set current keyboard ISE. * * @param[in] uuid The keyboard ISE UUID. */ void set_keyboard_ise_by_uuid(const sclchar *uuid); /** - * @ brief Request to get current keyboard ISE information. + * @brief Request to get current keyboard ISE information. * * @param[in] uuid The helper ISE UUID. */ void get_keyboard_ise(const sclchar *uuid); /** - * @ brief Request to get uuid list of all keyboard ISEs. + * @brief Request to get uuid list of all keyboard ISEs. * * @param[in] uuid The helper ISE UUID. */ @@ -334,7 +334,7 @@ public: void destroy_option_window(sclwindow window); /** - * @ brief Request to select text. + * @brief Request to select text. * * @param[in] start The start cursor position in text. * @param[in] end The end cursor position in text. -- 2.7.4 From cff9627c6b0cb424e8f7dc5b70403379d856a259 Mon Sep 17 00:00:00 2001 From: Jihoon Kim Date: Tue, 26 Apr 2016 09:54:13 +0900 Subject: [PATCH 09/16] Remove unused define in spec file Change-Id: I8f9a1e6aee55b30730eaccf5bab4eba858fb1e2b --- packaging/libscl-core.spec | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/packaging/libscl-core.spec b/packaging/libscl-core.spec index f6674d2..b828b6b 100644 --- a/packaging/libscl-core.spec +++ b/packaging/libscl-core.spec @@ -1,17 +1,13 @@ %bcond_with x %bcond_with wayland -%define _optdir /opt -%define _appdir %{_optdir}/apps - Name: libscl-core Summary: A library for developing software keyboards Version: 0.4.14 Release: 1 Group: Graphics & UI Framework/Input License: Apache-2.0 -Source0: libscl-core-%{version}.tar.gz -BuildRequires: gettext-tools +Source0: %{name}-%{version}.tar.gz BuildRequires: cmake BuildRequires: pkgconfig(elementary) BuildRequires: pkgconfig(vconf) @@ -73,10 +69,10 @@ rm -rf %{buildroot} %files %manifest %{name}.manifest %defattr(-,root,root,-) -%{_libdir}/libscl-core.so +%{_libdir}/%{name}.so %license LICENSE %files devel %defattr(-,root,root,-) %{_includedir}/* -%{_libdir}/pkgconfig/libscl-core.pc +%{_libdir}/pkgconfig/%{name}.pc -- 2.7.4 From 5698366bc58852662f4d3db24832c993221fe426 Mon Sep 17 00:00:00 2001 From: Jihoon Kim Date: Tue, 26 Apr 2016 11:29:11 +0900 Subject: [PATCH 10/16] Add synchronous API to get surrounding text Change-Id: I4f83a0b96a65584bdf180b74d31464fcb0868501 --- src/sclconnection-isf.cpp | 11 +++++++++++ src/sclconnection-isf.h | 1 + src/sclconnection.cpp | 7 +++++++ src/sclconnection.h | 1 + src/sclcore.cpp | 7 +++++++ src/sclcore.h | 11 ++++++++++- src/sclcoreimpl.cpp | 5 +++++ src/sclcoreimpl.h | 1 + 8 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/sclconnection-isf.cpp b/src/sclconnection-isf.cpp index 5d2f74c..f4dbdfe 100644 --- a/src/sclconnection-isf.cpp +++ b/src/sclconnection-isf.cpp @@ -949,6 +949,17 @@ void CSCLConnectionISF::get_surrounding_text(const sclchar *ic_uuid, sclint maxl } } +void CSCLConnectionISF::get_surrounding_text(sclint maxlen_before, sclint maxlen_after, sclchar **text, int &cursor) +{ + if (m_initialized) { + scim::String surrounding_text; + m_helper_agent.get_surrounding_text(maxlen_before, maxlen_after, surrounding_text, cursor); + + if (text) + *text = strdup(surrounding_text.c_str()); + } +} + void CSCLConnectionISF::delete_surrounding_text(sclint offset, sclint len) const { if (m_initialized) { diff --git a/src/sclconnection-isf.h b/src/sclconnection-isf.h index 26781a5..bdce63e 100644 --- a/src/sclconnection-isf.h +++ b/src/sclconnection-isf.h @@ -83,6 +83,7 @@ public: void get_keyboard_ise(const sclchar *uuid); void set_selection(sclint start, sclint end); void send_private_command(const char *command); + void get_surrounding_text(sclint maxlen_before, sclint maxlen_after, sclchar **text, int &cursor); private: sclboolean m_initialized; diff --git a/src/sclconnection.cpp b/src/sclconnection.cpp index fba5e8f..2ab7aa1 100644 --- a/src/sclconnection.cpp +++ b/src/sclconnection.cpp @@ -273,6 +273,13 @@ void CSCLConnection::get_surrounding_text(const sclchar *ic_uuid, sclint maxlen_ } } +void CSCLConnection::get_surrounding_text(sclint maxlen_before, sclint maxlen_after, sclchar **text, int &cursor) +{ + if (m_impl) { + m_impl->get_surrounding_text(maxlen_before, maxlen_after, text, cursor); + } +} + void CSCLConnection::delete_surrounding_text(sclint offset, sclint len) const { if (m_impl) { diff --git a/src/sclconnection.h b/src/sclconnection.h index c6cb71e..a8a6388 100644 --- a/src/sclconnection.h +++ b/src/sclconnection.h @@ -83,6 +83,7 @@ public: virtual void get_keyboard_ise(const sclchar *uuid); virtual void set_selection(sclint start, sclint end); virtual void send_private_command(const sclchar *command); + virtual void get_surrounding_text(sclint maxlen_before, sclint maxlen_after, sclchar **text, int &cursor); protected: std::string m_backend_identifier; diff --git a/src/sclcore.cpp b/src/sclcore.cpp index 7fa21c2..001488c 100644 --- a/src/sclcore.cpp +++ b/src/sclcore.cpp @@ -242,6 +242,13 @@ void CSCLCore::get_surrounding_text(const sclchar *ic_uuid, sclint maxlen_before } } +void CSCLCore::get_surrounding_text(sclint maxlen_before, sclint maxlen_after, sclchar **text, int &cursor) const +{ + if (m_impl) { + m_impl->get_surrounding_text(maxlen_before, maxlen_after, text, cursor); + } +} + void CSCLCore::delete_surrounding_text(sclint offset, sclint len) const { if (m_impl) { diff --git a/src/sclcore.h b/src/sclcore.h index 7669d40..d560553 100644 --- a/src/sclcore.h +++ b/src/sclcore.h @@ -249,7 +249,7 @@ public: void update_geometry(sclint x, sclint y, sclint width, sclint height); /** - * @brief Request to get surrounding text. + * @brief Request to get surrounding text asynchronously. * * @param[in] ic_uuid The helper ISE UUID. * @param[in] maxlen_before The max length of before. @@ -343,6 +343,15 @@ public: void send_private_command(const sclchar *command); + /** + * @brief Request to get surrounding text synchronously. + * + * @param[in] maxlen_before The max length of before. + * @param[in] maxlen_after The max length of after. + * @param[out] text The surrounding text. + * @param[out] cursor The cursor position. + */ + void get_surrounding_text(sclint maxlen_before, sclint maxlen_after, sclchar **text, int &cursor) const; private: CSCLCoreImpl *m_impl; }; diff --git a/src/sclcoreimpl.cpp b/src/sclcoreimpl.cpp index 84a6935..8c2da0c 100644 --- a/src/sclcoreimpl.cpp +++ b/src/sclcoreimpl.cpp @@ -232,6 +232,11 @@ void CSCLCoreImpl::get_surrounding_text(const sclchar* ic_uuid, sclint maxlen_be m_connection.get_surrounding_text(ic_uuid, maxlen_before, maxlen_after); } +void CSCLCoreImpl::get_surrounding_text(sclint maxlen_before, sclint maxlen_after, sclchar **text, int &cursor) +{ + m_connection.get_surrounding_text(maxlen_before, maxlen_after, text, cursor); +} + void CSCLCoreImpl::delete_surrounding_text(sclint offset, sclint len) const { m_connection.delete_surrounding_text(offset, len); diff --git a/src/sclcoreimpl.h b/src/sclcoreimpl.h index 40d774a..4df0782 100644 --- a/src/sclcoreimpl.h +++ b/src/sclcoreimpl.h @@ -101,6 +101,7 @@ public: void set_selection(sclint start, sclint end); void send_private_command(const sclchar *command); + void get_surrounding_text(sclint maxlen_before, sclint maxlen_after, sclchar **text, int &cursor); private: ISCLCoreEventCallback *m_event_callback; -- 2.7.4 From fe5c6e269509f18b9497c2b66d096b0fe3d0a453 Mon Sep 17 00:00:00 2001 From: Jihoon Kim Date: Tue, 26 Apr 2016 14:48:57 +0900 Subject: [PATCH 11/16] Update package version to 0.4.15 Change-Id: Ia1aaa55ee6a3e9074060742648c9724b385ce6ae --- packaging/libscl-core.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libscl-core.spec b/packaging/libscl-core.spec index b828b6b..0f3a8c8 100644 --- a/packaging/libscl-core.spec +++ b/packaging/libscl-core.spec @@ -3,7 +3,7 @@ Name: libscl-core Summary: A library for developing software keyboards -Version: 0.4.14 +Version: 0.4.15 Release: 1 Group: Graphics & UI Framework/Input License: Apache-2.0 -- 2.7.4 From 4646d5118eff5b0bb99598f44f7601dbfc80ac43 Mon Sep 17 00:00:00 2001 From: Jihoon Kim Date: Wed, 27 Apr 2016 15:29:23 +0900 Subject: [PATCH 12/16] Replace focus out handler with evas function Using evas callback is more appropriate than using ecore_wl function. Change-Id: Ib06a95ff3ec8747ef88472c79715033efae06151 --- src/sclcoreui-efl.cpp | 22 +++------------------- src/sclcoreui-efl.h | 1 - 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/src/sclcoreui-efl.cpp b/src/sclcoreui-efl.cpp index c2ea36b..364c4ce 100644 --- a/src/sclcoreui-efl.cpp +++ b/src/sclcoreui-efl.cpp @@ -71,7 +71,6 @@ sclboolean CSCLCoreUIEFL::init() for (int loop = 0;loop < OPTION_WINDOW_TYPE_MAX;loop++) { m_option_window_info[loop].window = SCLWINDOW_INVALID; - m_option_window_info[loop].handler = NULL; } return TRUE; @@ -485,7 +484,7 @@ void CSCLCoreUIEFL::run(const sclchar *display) } } -static Eina_Bool focus_out_cb(void *data, int type, void *event) +static void focus_out_cb(void *data, Evas *e, void *event) { OptionWindowInfo *info = static_cast(data); if (info) { @@ -502,13 +501,7 @@ static Eina_Bool focus_out_cb(void *data, int type, void *event) evas_object_del(NATIVE_WINDOW_CAST(info->window)); info->window = NULL; } - if (info->handler) { - ecore_event_handler_del(info->handler); - info->handler = NULL; - } } - - return ECORE_CALLBACK_CANCEL; } static void @@ -634,13 +627,9 @@ sclwindow CSCLCoreUIEFL::create_option_window(SCLOptionWindowType type) callback->on_create_option_window(window, type); } - Ecore_Event_Handler *handler = NULL; if (type == OPTION_WINDOW_TYPE_NORMAL) { -#ifdef WAYLAND - handler = ecore_event_handler_add(ECORE_WL_EVENT_FOCUS_OUT, focus_out_cb, &m_option_window_info[type]); -#else - handler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_OUT, focus_out_cb, &m_option_window_info[type]); -#endif + Evas *evas = evas_object_evas_get(window); + evas_event_callback_add(evas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, focus_out_cb, &m_option_window_info[type]); set_transient_for_app_window(window); } else if (type == OPTION_WINDOW_TYPE_SETTING_APPLICATION) { set_transient_for_isf_setting_window(window); @@ -648,7 +637,6 @@ sclwindow CSCLCoreUIEFL::create_option_window(SCLOptionWindowType type) } m_option_window_info[type].window = window; - m_option_window_info[type].handler = handler; return window; } @@ -667,10 +655,6 @@ void CSCLCoreUIEFL::destroy_option_window(sclwindow window) if (m_option_window_info[loop].window == window) { evas_object_del(NATIVE_WINDOW_CAST(window)); m_option_window_info[loop].window = SCLWINDOW_INVALID; - if (m_option_window_info[loop].handler) { - ecore_event_handler_del(m_option_window_info[loop].handler); - m_option_window_info[loop].handler = NULL; - } } } } diff --git a/src/sclcoreui-efl.h b/src/sclcoreui-efl.h index a2e5c4b..fbef76d 100644 --- a/src/sclcoreui-efl.h +++ b/src/sclcoreui-efl.h @@ -29,7 +29,6 @@ namespace scl typedef struct { sclwindow window; - Ecore_Event_Handler *handler; } OptionWindowInfo; class CSCLCoreUIEFL : public CSCLCoreUI -- 2.7.4 From 4191bb6cf55e91aa7e07cec1ae8aa663a1504efe Mon Sep 17 00:00:00 2001 From: Jihoon Kim Date: Wed, 27 Apr 2016 15:46:04 +0900 Subject: [PATCH 13/16] Add synchronous API to get selection text Change-Id: I1732b11a8d53911126f421a399e11275a7b40d3c --- src/sclconnection-isf.cpp | 15 +++++++++++++-- src/sclconnection-isf.h | 1 + src/sclconnection.cpp | 7 +++++++ src/sclconnection.h | 1 + src/sclcore.cpp | 7 +++++++ src/sclcore.h | 7 +++++++ src/sclcoreimpl.cpp | 5 +++++ src/sclcoreimpl.h | 1 + 8 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/sclconnection-isf.cpp b/src/sclconnection-isf.cpp index f4dbdfe..5bb30a3 100644 --- a/src/sclconnection-isf.cpp +++ b/src/sclconnection-isf.cpp @@ -1008,14 +1008,25 @@ void CSCLConnectionISF::get_keyboard_ise(const sclchar *uuid) void CSCLConnectionISF::set_selection(sclint start, sclint end) { if (m_initialized) { - m_helper_agent.set_selection(start, end); + m_helper_agent.set_selection(start, end); } } void CSCLConnectionISF::send_private_command(const sclchar *command) { if (m_initialized) { - m_helper_agent.send_private_command(command); + m_helper_agent.send_private_command(command); + } +} + +void CSCLConnectionISF::get_selection_text(sclchar **text) +{ + if (m_initialized) { + scim::String selection_text; + m_helper_agent.get_selection(selection_text); + + if (text) + *text = strdup(selection_text.c_str()); } } diff --git a/src/sclconnection-isf.h b/src/sclconnection-isf.h index bdce63e..0d8bd5b 100644 --- a/src/sclconnection-isf.h +++ b/src/sclconnection-isf.h @@ -84,6 +84,7 @@ public: void set_selection(sclint start, sclint end); void send_private_command(const char *command); void get_surrounding_text(sclint maxlen_before, sclint maxlen_after, sclchar **text, int &cursor); + void get_selection_text(sclchar **text); private: sclboolean m_initialized; diff --git a/src/sclconnection.cpp b/src/sclconnection.cpp index 2ab7aa1..6a7b6e2 100644 --- a/src/sclconnection.cpp +++ b/src/sclconnection.cpp @@ -335,3 +335,10 @@ void CSCLConnection::send_private_command(const sclchar *command) m_impl->send_private_command(command); } } + +void CSCLConnection::get_selection_text(sclchar **text) +{ + if (m_impl) { + m_impl->get_selection_text(text); + } +} diff --git a/src/sclconnection.h b/src/sclconnection.h index a8a6388..806c4da 100644 --- a/src/sclconnection.h +++ b/src/sclconnection.h @@ -84,6 +84,7 @@ public: virtual void set_selection(sclint start, sclint end); virtual void send_private_command(const sclchar *command); virtual void get_surrounding_text(sclint maxlen_before, sclint maxlen_after, sclchar **text, int &cursor); + virtual void get_selection_text(sclchar **text); protected: std::string m_backend_identifier; diff --git a/src/sclcore.cpp b/src/sclcore.cpp index 001488c..2749ee2 100644 --- a/src/sclcore.cpp +++ b/src/sclcore.cpp @@ -336,3 +336,10 @@ void CSCLCore::send_private_command(const sclchar *command) m_impl->send_private_command(command); } } + +void CSCLCore::get_selection_text(sclchar **text) const +{ + if (m_impl) { + m_impl->get_selection_text(text); + } +} diff --git a/src/sclcore.h b/src/sclcore.h index d560553..3a5d909 100644 --- a/src/sclcore.h +++ b/src/sclcore.h @@ -352,6 +352,13 @@ public: * @param[out] cursor The cursor position. */ void get_surrounding_text(sclint maxlen_before, sclint maxlen_after, sclchar **text, int &cursor) const; + + /** + * @brief Get the selected text. + * + * @param[out] text The surrounding text. + */ + void get_selection_text(sclchar **text) const; private: CSCLCoreImpl *m_impl; }; diff --git a/src/sclcoreimpl.cpp b/src/sclcoreimpl.cpp index 8c2da0c..f5d5591 100644 --- a/src/sclcoreimpl.cpp +++ b/src/sclcoreimpl.cpp @@ -352,3 +352,8 @@ void CSCLCoreImpl::send_private_command(const sclchar *command) { m_connection.send_private_command(command); } + +void CSCLCoreImpl::get_selection_text(sclchar **text) +{ + m_connection.get_selection_text(text); +} \ No newline at end of file diff --git a/src/sclcoreimpl.h b/src/sclcoreimpl.h index 4df0782..78c84be 100644 --- a/src/sclcoreimpl.h +++ b/src/sclcoreimpl.h @@ -102,6 +102,7 @@ public: void set_selection(sclint start, sclint end); void send_private_command(const sclchar *command); void get_surrounding_text(sclint maxlen_before, sclint maxlen_after, sclchar **text, int &cursor); + void get_selection_text(sclchar **text); private: ISCLCoreEventCallback *m_event_callback; -- 2.7.4 From 1ba26398af790175973d00d334395574aa67dc48 Mon Sep 17 00:00:00 2001 From: Jihoon Kim Date: Wed, 27 Apr 2016 20:44:33 +0900 Subject: [PATCH 14/16] Update package version to 0.4.16 Change-Id: I4f8adc198b019e8e741024e1ff2bba50e328740e --- packaging/libscl-core.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libscl-core.spec b/packaging/libscl-core.spec index 0f3a8c8..f1e851e 100644 --- a/packaging/libscl-core.spec +++ b/packaging/libscl-core.spec @@ -3,7 +3,7 @@ Name: libscl-core Summary: A library for developing software keyboards -Version: 0.4.15 +Version: 0.4.16 Release: 1 Group: Graphics & UI Framework/Input License: Apache-2.0 -- 2.7.4 From 6d5d7e205f2bda9cd10bee95aff93f1a9827a4e9 Mon Sep 17 00:00:00 2001 From: Ji-hoon Lee Date: Tue, 3 May 2016 17:23:25 +0900 Subject: [PATCH 15/16] Added websocket server for supporting legacy Web IMEs Change-Id: Iac56faf666ae861699c824fbb93cfff9855f84a9 --- CMakeLists.txt | 4 + packaging/libscl-core.spec | 1 + src/legacy_support/web_helper_agent.cpp | 194 ++++++ src/legacy_support/web_helper_agent.h | 128 ++++ src/legacy_support/websocket.cpp | 1029 +++++++++++++++++++++++++++++++ src/legacy_support/websocket.h | 263 ++++++++ src/sclcoreui-efl.cpp | 4 + src/sclcoreui-efl.h | 5 + src/sclcoreui.cpp | 8 +- 9 files changed, 1633 insertions(+), 3 deletions(-) create mode 100644 src/legacy_support/web_helper_agent.cpp create mode 100644 src/legacy_support/web_helper_agent.h create mode 100644 src/legacy_support/websocket.cpp create mode 100644 src/legacy_support/websocket.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 18d7cea..5d92453 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,8 @@ SET(SRCS src/sclconnection.cpp src/sclconnection-isf.cpp src/sclcore.cpp + src/legacy_support/websocket.cpp + src/legacy_support/web_helper_agent.cpp ) SET(PACKAGE ${PROJECT_NAME}) @@ -22,6 +24,7 @@ MESSAGE(STATUS "Build type: ${CMAKE_BUILD_TYPE}") INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/include + ${CMAKE_SOURCE_DIR}/src/legacy_support ) INCLUDE(FindPkgConfig) @@ -32,6 +35,7 @@ SET(PKGS_CHECK_MODULES isf vconf libscl-common + libwebsockets capi-appfw-application ) diff --git a/packaging/libscl-core.spec b/packaging/libscl-core.spec index 0f3a8c8..292705d 100644 --- a/packaging/libscl-core.spec +++ b/packaging/libscl-core.spec @@ -23,6 +23,7 @@ BuildRequires: pkgconfig(x11) %endif BuildRequires: pkgconfig(libscl-common) BuildRequires: pkgconfig(capi-appfw-application) +BuildRequires: pkgconfig(libwebsockets) %description diff --git a/src/legacy_support/web_helper_agent.cpp b/src/legacy_support/web_helper_agent.cpp new file mode 100644 index 0000000..cb81d35 --- /dev/null +++ b/src/legacy_support/web_helper_agent.cpp @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include "web_helper_agent.h" + +#include "websocket.h" +#include "sclcoreimpl.h" + +using namespace scl; + +typedef struct { + int major_version; + WEB_HELPER_AGENT_TYPE agent_type; +} WEB_HELPER_AGENT_TYPES_FOR_VERSIONS; + +static WEB_HELPER_AGENT_TYPES_FOR_VERSIONS web_helper_agent_types_for_versions[] = { + {1, WEB_HELPER_AGENT_WEBSOCKET}, /* Major version 1 indicates that it uses websocket for communication */ +}; + +static int WEB_HELPER_AGENT_TYPES_FOR_VERSIONS_NUM = \ + sizeof(web_helper_agent_types_for_versions) / sizeof(WEB_HELPER_AGENT_TYPES_FOR_VERSIONS); + +WEB_HELPER_AGENT_TYPE CWebHelperAgent::get_web_helper_agent_type_from_major_version(int version) +{ + for (int loop = 0;loop < WEB_HELPER_AGENT_TYPES_FOR_VERSIONS_NUM;loop++) { + if (web_helper_agent_types_for_versions[loop].major_version == version) { + return web_helper_agent_types_for_versions[loop].agent_type; + } + } + return WEB_HELPER_AGENT_UNKNOWN; +} + +CWebHelperAgent* CWebHelperAgent::create_web_helper_agent(WEB_HELPER_AGENT_TYPE type) +{ + CWebHelperAgent *ret = NULL; + if (type == WEB_HELPER_AGENT_WEBSOCKET) { + ret = new CWebHelperAgentWebSocket; + } + return ret; +} + +void CWebHelperAgent::destroy_web_helper_agent(CWebHelperAgent* agent) +{ + if (agent) delete agent; +} + +CWebHelperAgent::CWebHelperAgent() +{ +} + +CWebHelperAgent::~CWebHelperAgent() +{ + +} + +bool CWebHelperAgent::init() +{ + return true; +} + +bool CWebHelperAgent::exit() +{ + return true; +} + +void CWebHelperAgent::signal(int sig) +{ + +} + +void CWebHelperAgent::log(const char *str) +{ + CSCLCoreImpl *impl = CSCLCoreImpl::get_instance(); + if (impl) { + //impl->logise_log(str); + } +} + +void CWebHelperAgent::commit_string(const char *str) +{ + CSCLCoreImpl *impl = CSCLCoreImpl::get_instance(); + if (impl) { + impl->commit_string(-1, "", str); + } +} + +void CWebHelperAgent::update_preedit_string(const char *str) +{ + CSCLCoreImpl *impl = CSCLCoreImpl::get_instance(); + if (impl) { + impl->update_preedit_string(-1, "", str); + } +} + +void CWebHelperAgent::send_key_event(unsigned int key, unsigned int key_mask) +{ + CSCLCoreImpl *impl = CSCLCoreImpl::get_instance(); + if (impl) { + impl->send_key_event(-1, "", key, key_mask); + } +} + +void CWebHelperAgent::forward_key_event(unsigned int key) +{ + CSCLCoreImpl *impl = CSCLCoreImpl::get_instance(); + if (impl) { + impl->forward_key_event(-1, "", key, scim::SCIM_KEY_NullMask); + } +} + +void CWebHelperAgent::set_keyboard_sizes(int portrait_width, int portrait_height, int landscape_width, int landscape_height) +{ + CSCLCoreImpl *impl = CSCLCoreImpl::get_instance(); + if (impl) { + SclSize portrait, landscape; + portrait.width = portrait_width; + portrait.height = portrait_height; + landscape.width = landscape_width; + landscape.height = landscape_height; + impl->set_keyboard_size_hints(portrait, landscape); + } +} + +void CWebHelperAgent::set_selection(int start_index, int end_index) +{ + CSCLCoreImpl *impl = CSCLCoreImpl::get_instance(); + if (impl) { + impl->set_selection(start_index, end_index); + } +} + +void CWebHelperAgent::get_selection() +{ + CSCLCoreImpl *impl = CSCLCoreImpl::get_instance(); + if (impl) { + //impl->get_selection(-1, "", ); + } +} + +void CWebHelperAgent::get_surrounding_text(int maxlen_before, int maxlen_after) +{ + CSCLCoreImpl *impl = CSCLCoreImpl::get_instance(); + if (impl) { + impl->get_surrounding_text("", maxlen_before, maxlen_after); + } +} + +void CWebHelperAgent::delete_surrounding_text(int offset, int len) +{ + CSCLCoreImpl *impl = CSCLCoreImpl::get_instance(); + if (impl) { + impl->delete_surrounding_text(offset, len); + } +} + +std::string CMagicKeyManager::get_magic_key() +{ + static std::string current_magic_key; + + /* If we don't have magic key generated yet */ + if (current_magic_key.length() != MAGIC_KEY_LENGTH) { + char magic_key[MAGIC_KEY_LENGTH + 1]; + /* We are going to generate a magic key that contains ascii characters in the range of '0' to 'z' */ + const char magic_key_range_lower = '0'; + const char magic_key_range_upper = 'Z'; + + srand(time(NULL)); + for(int loop = 0;loop < MAGIC_KEY_LENGTH;loop++) { + magic_key[loop] = (rand() % (magic_key_range_upper - magic_key_range_lower)) + magic_key_range_lower; + } + magic_key[MAGIC_KEY_LENGTH] = '\0'; + + current_magic_key = magic_key; + } + + return current_magic_key; +} diff --git a/src/legacy_support/web_helper_agent.h b/src/legacy_support/web_helper_agent.h new file mode 100644 index 0000000..408c9d3 --- /dev/null +++ b/src/legacy_support/web_helper_agent.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _WEB_HELPER_AGENT_H_ +#define _WEB_HELPER_AGENT_H_ + +#define MAGIC_KEY_LENGTH 32 +#define VERSION_DELIMITER '.' +#define VERSION_TOKEN_NUM 2 // We are expecting 2 version tokens : MAJOR and MINOR + +#include +#include +#include + +class CStringTokenizer +{ +public: + static std::vector &split(const std::string &s, char delim, std::vector &elems) { + unsigned int loop = 0; + unsigned int start = 0; + for (loop = 0;loop < s.length();loop++) { + if (s.at(loop) == delim) { + std::string item = s.substr(start, loop - start); + elems.push_back(item); + start = loop + 1; + } + } + std::string item = s.substr(start, loop - start); + elems.push_back(item); + return elems; + } + + static std::vector split(const std::string &s, char delim) { + std::vector elems; + split(s, delim, elems); + return elems; + } +}; + +typedef enum { + WEB_HELPER_AGENT_UNKNOWN, + WEB_HELPER_AGENT_WEBSOCKET, + WEB_HELPER_AGENT_DIRECT, +} WEB_HELPER_AGENT_TYPE; + +class CMagicKeyManager +{ +public: + static std::string get_magic_key(); +}; + +class CWebHelperAgent +{ +public: + CWebHelperAgent(); + virtual ~CWebHelperAgent(); + + virtual bool init(); + virtual bool exit(); + + virtual void signal(int sig); + + virtual void on_init() {} + virtual void on_exit() {} + + virtual void on_focus_in(int ic) {} + virtual void on_focus_out(int ic) {} + + virtual void on_show(int ic) {} + virtual void on_hide(int ic) {} + + virtual void on_set_rotation(int degree) {} + + virtual void on_update_cursor_position(int ic, int cursor_pos) {} + virtual void on_update_surrounding_text(int ic, const char *text, int cursor) {} + virtual void on_update_selection(int ic, const char *text) {} + + virtual void on_set_language(unsigned int language) {} + + virtual void on_set_imdata(char *buf, unsigned int len) {} + virtual void on_get_imdata(char **buf, unsigned int *len) {} + + virtual void on_set_return_key_type(unsigned int type) {} + virtual void on_get_return_key_type(unsigned int *type) {} + + virtual void on_set_return_key_disable(unsigned int disabled) {} + virtual void on_get_return_key_disable(unsigned int *disabled) {} + + virtual void on_set_layout(unsigned int layout) {} + virtual void on_get_layout(unsigned int *layout) {} + + virtual void on_reset_input_context(int ic) {} + + virtual void on_process_key_event(unsigned int code, unsigned int mask, unsigned int layout, unsigned int *ret) {} + + + virtual void log(const char *str); + virtual void commit_string(const char *str); + virtual void update_preedit_string(const char *str); + virtual void send_key_event(unsigned int key, unsigned int key_mask); + virtual void forward_key_event(unsigned int key); + virtual void set_keyboard_sizes(int portrait_width, int portrait_height, int landscape_width, int landscape_height); + virtual void set_selection(int start_index, int end_index); + virtual void get_selection(); + virtual void get_surrounding_text(int maxlen_before, int maxlen_after); + virtual void delete_surrounding_text(int offset, int len); + +public: + static WEB_HELPER_AGENT_TYPE get_web_helper_agent_type_from_major_version(int version); + static CWebHelperAgent* create_web_helper_agent(WEB_HELPER_AGENT_TYPE type); + static void destroy_web_helper_agent(CWebHelperAgent* agent); +}; + +#endif // _WEB_HELPER_AGENT_H_ \ No newline at end of file diff --git a/src/legacy_support/websocket.cpp b/src/legacy_support/websocket.cpp new file mode 100644 index 0000000..2725d79 --- /dev/null +++ b/src/legacy_support/websocket.cpp @@ -0,0 +1,1029 @@ +/* + * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "websocket.h" + +#include +#include + +#include + +pthread_t g_ws_server_thread = (pthread_t)NULL; +pthread_mutex_t g_ws_server_mutex = PTHREAD_MUTEX_INITIALIZER; + +pthread_cond_t g_ws_query_condition = PTHREAD_COND_INITIALIZER; +pthread_mutex_t g_ws_query_mutex = PTHREAD_MUTEX_INITIALIZER; + +bool g_ws_server_exit = false; +struct lws_context *g_ws_server_context = NULL; + +CWebHelperAgentWebSocket* CWebHelperAgentWebSocket::m_current_instance = NULL; + +int force_exit = 0; + +enum protocols { + /* always first */ + PROTOCOL_HTTP = 0, + + PROTOCOL_KEYBOARD, + + /* always last */ + MAX_PROTOCOL_COUNT +}; + +struct per_session_data__http { + int fd; +}; + +static int callback_http(struct lws *wsi, + enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + return 0; +} + +struct per_session_data__keyboard { + int session_id; + int valid; +}; + +static int callback_keyboard(struct lws *wsi, + enum lws_callback_reasons reason, + void *user, void *in, size_t len); + +static struct lws_protocols protocols[] = { + { + "http-only", + callback_http, + sizeof(struct per_session_data__http), + 0, + }, + { + "keyboard-protocol", + callback_keyboard, + sizeof(struct per_session_data__keyboard), + 32, + }, + { NULL, NULL, 0, 0 } +}; + +static int callback_keyboard(struct lws *wsi, + enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + static int last_session_id = 0; + const int bufsize = 512; + int n = 0; + unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + bufsize + + LWS_SEND_BUFFER_POST_PADDING]; + unsigned char *p = &buf[LWS_SEND_BUFFER_PRE_PADDING]; + struct per_session_data__keyboard *pss = (struct per_session_data__keyboard *)user; + CWebHelperAgentWebSocket *agent = CWebHelperAgentWebSocket::get_current_instance(); + + switch (reason) { + + case LWS_CALLBACK_ESTABLISHED: + pss->session_id = ++last_session_id; + LOGD("LWS_CALLBACK_ESTABLISHED : %p %d", g_ws_server_context, pss->session_id); + pss->valid = false; + if (g_ws_server_context) { + lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]); + } + break; + + case LWS_CALLBACK_CLOSED: + LOGD("LWS_CALLBACK_CLOSED : %d", pss->session_id); + break; + + case LWS_CALLBACK_SERVER_WRITEABLE: + if (agent) { + /* We allow data tranmission only if this client is guaranteed to be valid */ + if (pss->valid) { + pthread_mutex_lock(&g_ws_server_mutex); + std::queue& messages = agent->get_send_message_queue(); + while (messages.size() > 0) { + ISE_MESSAGE &message = messages.front(); + std::string str = CISEMessageSerializer::serialize(message); + LOGD("SEND_WEBSOCKET_MESSAGE : %s", str.c_str()); + n = snprintf((char *)p, bufsize, "%s", str.c_str()); + /* too small for partial */ + n = lws_write(wsi, p, n, LWS_WRITE_TEXT); + messages.pop(); + } + pthread_mutex_unlock(&g_ws_server_mutex); + + if (n < 0) { + lwsl_err("ERROR %d writing to di socket\n", n); + return -1; + } + } else { + LOGD("Rejecting data transmission since client is not valid"); + } + } + break; + + case LWS_CALLBACK_RECEIVE: + if (in) { + std::string str = (const char *)in; + ISE_MESSAGE message = CISEMessageSerializer::deserialize(str); + + if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_LOGIN]) == 0) { + /* + if (message.values.at(0).compare(CMagicKeyManager::get_magic_key()) == 0) { + LOGD("LOGIN successful, validating client"); + pss->valid = true; + } else { + LOGD("LOGIN failed, invalidating client"); + pss->valid = false; + } + */ + pss->valid = true; + } + + if (pss->valid) { + pthread_mutex_lock(&g_ws_server_mutex); + std::queue& messages = agent->get_recv_message_queue(); + messages.push(message); + pthread_mutex_unlock(&g_ws_server_mutex); + + const char *recved_message = "recved"; + ecore_pipe_write(agent->get_recv_message_pipe(), recved_message, strlen(recved_message)); + + /* If we received reply message, let's send signal to wake up our main thread */ + if (message.type.compare(ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_REPLY]) == 0) { + pthread_mutex_lock(&g_ws_query_mutex); + pthread_cond_signal(&g_ws_query_condition); + pthread_mutex_unlock(&g_ws_query_mutex); + } + } else { + LOGD("Ignoring data received since client is not valid"); + } + } + + break; + default: + break; + } + + return 0; +} + +void *process_ws_server(void *data) +{ + while (!force_exit && !g_ws_server_exit) { + struct timeval tv; + gettimeofday(&tv, NULL); + + if (g_ws_server_context) { + lws_service(g_ws_server_context, 50); + } else { + LOGD("WARNING : g_ws_server_context is NULL"); + } + } + return NULL; +} + +void log_func(int level, const char *line) +{ + if (line) { + LOGD("LEVEL : %d , %s", level, line); + } +} + +CWebHelperAgentWebSocket::CWebHelperAgentWebSocket() +{ + if (m_current_instance != NULL) { + LOGD("WARNING : m_current_instance is NOT NULL"); + } + m_current_instance = this; + m_recv_message_pipe = NULL; +} + +CWebHelperAgentWebSocket::~CWebHelperAgentWebSocket() +{ + if (m_current_instance == this) { + m_current_instance = NULL; + } + + if (m_recv_message_pipe) { + ecore_pipe_del(m_recv_message_pipe); + m_recv_message_pipe = NULL; + } +} + +static void recv_message_pipe_handler(void *data, void *buffer, unsigned int nbyte) +{ + CWebHelperAgentWebSocket *agent = CWebHelperAgentWebSocket::get_current_instance(); + if (agent) { + agent->process_recved_messages(); + } +} + +bool CWebHelperAgentWebSocket::init() +{ + bool ret = true; + + struct lws_context_creation_info info; + + memset(&info, 0, sizeof info); + info.port = 7681; + + int debug_level = LLL_DEBUG; + lws_set_log_level(debug_level, log_func); + + info.iface = NULL; + info.protocols = protocols; + info.extensions = NULL; + info.ssl_cert_filepath = NULL; + info.ssl_private_key_filepath = NULL; + info.gid = -1; + info.uid = -1; + info.options = 0; + + ecore_init(); + + /* The WebSocket server is running on a separate thread, and let the thread send a message + through this pipe to guarantee thread safety */ + m_recv_message_pipe = ecore_pipe_add(recv_message_pipe_handler, NULL); + + /* Let's retry creating server context for a certain number of times */ + const int max_retry_num = 10; + int retry_num = 0; + + do { + g_ws_server_context = lws_create_context(&info); + LOGD("libwebsocket context : %p", g_ws_server_context); + sleep(1); + } while (g_ws_server_context == NULL && retry_num++ < max_retry_num); + + pthread_mutex_init(&g_ws_server_mutex, NULL); + + pthread_mutex_init(&g_ws_query_mutex, NULL); + pthread_cond_init(&g_ws_query_condition, NULL); + + if (g_ws_server_context) { + if (pthread_create(&g_ws_server_thread, NULL, &process_ws_server, NULL) != 0) { + g_ws_server_thread = (pthread_t)NULL; + ret = false; + } + } else { + ret = false; + } + + on_init(); + + return ret; +} + +bool CWebHelperAgentWebSocket::exit() +{ + on_exit(); + + g_ws_server_exit = true; + + if (m_recv_message_pipe) { + ecore_pipe_del(m_recv_message_pipe); + m_recv_message_pipe = NULL; + } + + if (g_ws_server_thread) { + pthread_join(g_ws_server_thread, NULL); + } + + pthread_cond_destroy(&g_ws_query_condition); + pthread_mutex_destroy(&g_ws_query_mutex); + + pthread_mutex_destroy(&g_ws_server_mutex); + + if (g_ws_server_context) { + lws_context_destroy(g_ws_server_context); + g_ws_server_context = NULL; + } + + ecore_shutdown(); + + return true; +} + +void CWebHelperAgentWebSocket::signal(int sig) +{ + force_exit = 1; +} + +template +std::string to_string(T i) +{ + std::stringstream ss; + std::string s; + ss << i; + s = ss.str(); + + return s; +} + +void CWebHelperAgentWebSocket::on_init() +{ + ISE_MESSAGE message; + message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN]; + message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_INIT]; + + pthread_mutex_lock(&g_ws_server_mutex); + m_send_message_queue.push(message); + pthread_mutex_unlock(&g_ws_server_mutex); + + if (g_ws_server_context) { + lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]); + } else { + LOGD("WARNING : g_ws_server_context is NULL"); + } +} + +void CWebHelperAgentWebSocket::on_exit() +{ + ISE_MESSAGE message; + message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN]; + message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_EXIT]; + + pthread_mutex_lock(&g_ws_server_mutex); + m_send_message_queue.push(message); + pthread_mutex_unlock(&g_ws_server_mutex); + + if (g_ws_server_context) { + lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]); + } else { + LOGD("WARNING : g_ws_server_context is NULL"); + } +} + +void CWebHelperAgentWebSocket::on_focus_in(int ic) +{ + ISE_MESSAGE message; + message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN]; + message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_FOCUS_IN]; + message.values.push_back(to_string(ic)); + + pthread_mutex_lock(&g_ws_server_mutex); + m_send_message_queue.push(message); + pthread_mutex_unlock(&g_ws_server_mutex); + + if (g_ws_server_context) { + lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]); + } else { + LOGD("WARNING : g_ws_server_context is NULL"); + } +} + +void CWebHelperAgentWebSocket::on_focus_out(int ic) +{ + ISE_MESSAGE message; + message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN]; + message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_FOCUS_OUT]; + message.values.push_back(to_string(ic)); + + pthread_mutex_lock(&g_ws_server_mutex); + m_send_message_queue.push(message); + pthread_mutex_unlock(&g_ws_server_mutex); + + if (g_ws_server_context) { + lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]); + } else { + LOGD("WARNING : g_ws_server_context is NULL"); + } +} + +void CWebHelperAgentWebSocket::on_show(int ic) +{ + ISE_MESSAGE message; + message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN]; + message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SHOW]; + message.values.push_back(to_string(ic)); + + pthread_mutex_lock(&g_ws_server_mutex); + m_send_message_queue.push(message); + pthread_mutex_unlock(&g_ws_server_mutex); + + if (g_ws_server_context) { + lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]); + } else { + LOGD("WARNING : g_ws_server_context is NULL"); + } + + LOGD("put into send message buffer"); +} + +void CWebHelperAgentWebSocket::on_hide(int ic) +{ + ISE_MESSAGE message; + message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN]; + message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_HIDE]; + message.values.push_back(to_string(ic)); + + pthread_mutex_lock(&g_ws_server_mutex); + m_send_message_queue.push(message); + pthread_mutex_unlock(&g_ws_server_mutex); + + if (g_ws_server_context) { + lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]); + } else { + LOGD("WARNING : g_ws_server_context is NULL"); + } +} + +void CWebHelperAgentWebSocket::on_set_rotation(int degree) +{ + ISE_MESSAGE message; + message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN]; + message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_ROTATION]; + message.values.push_back(to_string(degree)); + + pthread_mutex_lock(&g_ws_server_mutex); + m_send_message_queue.push(message); + pthread_mutex_unlock(&g_ws_server_mutex); + + if (g_ws_server_context) { + lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]); + } else { + LOGD("WARNING : g_ws_server_context is NULL"); + } +} + +void CWebHelperAgentWebSocket::on_update_cursor_position(int ic, int cursor_pos) +{ + ISE_MESSAGE message; + message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN]; + message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_UPDATE_CURSOR_POSITION]; + message.values.push_back(to_string(ic)); + message.values.push_back(to_string(cursor_pos)); + + pthread_mutex_lock(&g_ws_server_mutex); + m_send_message_queue.push(message); + pthread_mutex_unlock(&g_ws_server_mutex); + + if (g_ws_server_context) { + lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]); + } else { + LOGD("WARNING : g_ws_server_context is NULL"); + } +} + +void CWebHelperAgentWebSocket::on_update_surrounding_text(int ic, const char *text, int cursor) +{ + ISE_MESSAGE message; + message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_REPLY]; + message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_UPDATE_SURROUNDING_TEXT]; + message.values.push_back(to_string(cursor)); + message.values.push_back(text); + + pthread_mutex_lock(&g_ws_server_mutex); + m_send_message_queue.push(message); + pthread_mutex_unlock(&g_ws_server_mutex); + + if (g_ws_server_context) { + lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]); + } else { + LOGD("WARNING : g_ws_server_context is NULL"); + } +} + +void CWebHelperAgentWebSocket::on_update_selection(int ic, const char *text) +{ + ISE_MESSAGE message; + message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_REPLY]; + message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_UPDATE_SELECTION]; + message.values.push_back(text); + + pthread_mutex_lock(&g_ws_server_mutex); + m_send_message_queue.push(message); + pthread_mutex_unlock(&g_ws_server_mutex); + + if (g_ws_server_context) { + lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]); + } else { + LOGD("WARNING : g_ws_server_context is NULL"); + } +} + +void CWebHelperAgentWebSocket::on_set_language(unsigned int language) +{ + ISE_MESSAGE message; + message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN]; + message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_LANGUAGE]; + + bool found = false; + for (unsigned int loop = 0;loop < sizeof(ISE_LANGUAGE_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) { + if (language == (unsigned int)ISE_LANGUAGE_TYPES[loop].type_value) { + message.values.push_back(ISE_LANGUAGE_TYPES[loop].type_string); + found = true; + } + } + + if (found) { + pthread_mutex_lock(&g_ws_server_mutex); + m_send_message_queue.push(message); + pthread_mutex_unlock(&g_ws_server_mutex); + + if (g_ws_server_context) { + lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]); + } else { + LOGD("WARNING : g_ws_server_context is NULL"); + } + } +} + +void CWebHelperAgentWebSocket::on_set_imdata(char *buf, unsigned int len) +{ + ISE_MESSAGE message; + message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN]; + message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_IMDATA]; + message.values.push_back(buf); + + pthread_mutex_lock(&g_ws_server_mutex); + m_send_message_queue.push(message); + pthread_mutex_unlock(&g_ws_server_mutex); + + if (g_ws_server_context) { + lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]); + } else { + LOGD("WARNING : g_ws_server_context is NULL"); + } +} + +void CWebHelperAgentWebSocket::on_get_imdata(char **buf, unsigned int *len) +{ + ISE_MESSAGE message; + message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_QUERY]; + message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_IMDATA]; + + pthread_mutex_lock(&g_ws_server_mutex); + m_send_message_queue.push(message); + pthread_mutex_unlock(&g_ws_server_mutex); + + if (g_ws_server_context) { + lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]); + } else { + LOGD("WARNING : g_ws_server_context is NULL"); + } + + wait_for_reply_message(); + + std::vector values; + /* Check if we received reply for GET_IMDATA message */ + if (process_recved_messages_until_reply_found( + ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_IMDATA], values)) { + if (values.size() > 0 && buf && len) { + int string_length = values.at(0).length(); + (*buf) = new char[string_length + 1]; + if (*buf) { + strncpy(*buf, values.at(0).c_str(), string_length); + /* Make sure this is a null-terminated string */ + *(*buf + string_length) = '\0'; + *len = string_length; + } + } + } else { + LOGD("process_recved_messages_until_reply_found returned FALSE"); + } + /* Now process the rest in the recv buffer */ + process_recved_messages(); +} + +void CWebHelperAgentWebSocket::on_set_return_key_type(unsigned int type) +{ + ISE_MESSAGE message; + message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN]; + message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_RETURN_KEY_TYPE]; + + bool found = false; + for (unsigned int loop = 0;loop < sizeof(ISE_RETURN_KEY_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) { + if (type == (unsigned int)ISE_RETURN_KEY_TYPES[loop].type_value) { + message.values.push_back(ISE_RETURN_KEY_TYPES[loop].type_string); + found = true; + } + } + + if (found) { + pthread_mutex_lock(&g_ws_server_mutex); + m_send_message_queue.push(message); + pthread_mutex_unlock(&g_ws_server_mutex); + + if (g_ws_server_context) { + lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]); + } else { + LOGD("WARNING : g_ws_server_context is NULL"); + } + } +} + +void CWebHelperAgentWebSocket::on_get_return_key_type(unsigned int *type) +{ + ISE_MESSAGE message; + message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_QUERY]; + message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_RETURN_KEY_TYPE]; + + pthread_mutex_lock(&g_ws_server_mutex); + m_send_message_queue.push(message); + pthread_mutex_unlock(&g_ws_server_mutex); + + if (g_ws_server_context) { + lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]); + } else { + LOGD("WARNING : g_ws_server_context is NULL"); + } + + wait_for_reply_message(); + + /* Since we are accessing recved buffer, lock the server mutex again */ + pthread_mutex_lock(&g_ws_server_mutex); + std::vector values; + /* Check if we received reply for GET_RETURN_KEY_TYPE message */ + if (process_recved_messages_until_reply_found( + ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_RETURN_KEY_TYPE], values)) { + if (type) { + for (unsigned int loop = 0;loop < sizeof(ISE_RETURN_KEY_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) { + if (values.at(0).compare(ISE_RETURN_KEY_TYPES[loop].type_string) == 0) { + *type = ISE_RETURN_KEY_TYPES[loop].type_value; + } + } + } + } + /* Now process the rest in the recv buffer */ + process_recved_messages(); + pthread_mutex_unlock(&g_ws_server_mutex); +} + +void CWebHelperAgentWebSocket::on_set_return_key_disable(unsigned int disabled) +{ + ISE_MESSAGE message; + message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN]; + message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_RETURN_KEY_DISABLE]; + + bool found = false; + for (unsigned int loop = 0;loop < sizeof(ISE_TRUEFALSE_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) { + if (disabled == (unsigned int)ISE_TRUEFALSE_TYPES[loop].type_value) { + message.values.push_back(ISE_TRUEFALSE_TYPES[loop].type_string); + found = true; + } + } + + if (found) { + pthread_mutex_lock(&g_ws_server_mutex); + m_send_message_queue.push(message); + pthread_mutex_unlock(&g_ws_server_mutex); + + if (g_ws_server_context) { + lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]); + } else { + LOGD("WARNING : g_ws_server_context is NULL"); + } + } +} + +void CWebHelperAgentWebSocket::on_get_return_key_disable(unsigned int *disabled) +{ + ISE_MESSAGE message; + message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_QUERY]; + message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_RETURN_KEY_DISABLE]; + + pthread_mutex_lock(&g_ws_server_mutex); + m_send_message_queue.push(message); + pthread_mutex_unlock(&g_ws_server_mutex); + + if (g_ws_server_context) { + lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]); + } else { + LOGD("WARNING : g_ws_server_context is NULL"); + } + + wait_for_reply_message(); + + /* Since we are accessing recved buffer, lock the server mutex again */ + pthread_mutex_lock(&g_ws_server_mutex); + std::vector values; + /* Check if we received reply for GET_RETURN_KEY_DISABLE message */ + if (process_recved_messages_until_reply_found( + ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_RETURN_KEY_DISABLE], values)) { + if (disabled) { + for (unsigned int loop = 0;loop < sizeof(ISE_TRUEFALSE_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) { + if (values.at(0).compare(ISE_TRUEFALSE_TYPES[loop].type_string) == 0) { + *disabled = ISE_TRUEFALSE_TYPES[loop].type_value; + } + } + } + } + /* Now process the rest in the recv buffer */ + process_recved_messages(); + pthread_mutex_unlock(&g_ws_server_mutex); +} + +void CWebHelperAgentWebSocket::on_set_layout(unsigned int layout) +{ + ISE_MESSAGE message; + message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN]; + message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_LAYOUT]; + + bool found = false; + for (unsigned int loop = 0;loop < sizeof(ISE_LAYOUT_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) { + if (layout == (unsigned int)ISE_LAYOUT_TYPES[loop].type_value) { + message.values.push_back(ISE_LAYOUT_TYPES[loop].type_string); + found = true; + } + } + + if (found) { + pthread_mutex_lock(&g_ws_server_mutex); + m_send_message_queue.push(message); + pthread_mutex_unlock(&g_ws_server_mutex); + + if (g_ws_server_context) { + lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]); + } else { + LOGD("WARNING : g_ws_server_context is NULL"); + } + } +} + +void CWebHelperAgentWebSocket::on_get_layout(unsigned int *layout) +{ + ISE_MESSAGE message; + message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_QUERY]; + message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_LAYOUT]; + + pthread_mutex_lock(&g_ws_server_mutex); + m_send_message_queue.push(message); + pthread_mutex_unlock(&g_ws_server_mutex); + + if (g_ws_server_context) { + lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]); + } else { + LOGD("WARNING : g_ws_server_context is NULL"); + } + + wait_for_reply_message(); + + /* Since we are accessing recved buffer, lock the server mutex again */ + pthread_mutex_lock(&g_ws_server_mutex); + std::vector values; + /* Check if we received reply for GET_LAYOUT message */ + if (process_recved_messages_until_reply_found( + ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_LAYOUT], values)) { + if (layout) { + for (unsigned int loop = 0;loop < sizeof(ISE_LAYOUT_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) { + if (values.at(0).compare(ISE_LAYOUT_TYPES[loop].type_string) == 0) { + *layout = ISE_LAYOUT_TYPES[loop].type_value; + } + } + } + } + /* Now process the rest in the recv buffer */ + process_recved_messages(); + pthread_mutex_unlock(&g_ws_server_mutex); +} + +void CWebHelperAgentWebSocket::on_reset_input_context(int ic) +{ + ISE_MESSAGE message; + message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN]; + message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_RESET_INPUT_CONTEXT]; + message.values.push_back(to_string(ic)); + + pthread_mutex_lock(&g_ws_server_mutex); + m_send_message_queue.push(message); + pthread_mutex_unlock(&g_ws_server_mutex); + + if (g_ws_server_context) { + lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]); + } else { + LOGD("WARNING : g_ws_server_context is NULL"); + } +} + +void CWebHelperAgentWebSocket::on_process_key_event(unsigned int code, unsigned int mask, unsigned int layout, unsigned int *ret) +{ + ISE_MESSAGE message; + message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_QUERY]; + message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_PROCESS_KEY_EVENT]; + message.values.push_back(to_string(code)); + message.values.push_back(to_string(mask)); + message.values.push_back(to_string(layout)); + + pthread_mutex_lock(&g_ws_server_mutex); + m_send_message_queue.push(message); + pthread_mutex_unlock(&g_ws_server_mutex); + + if (g_ws_server_context) { + lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]); + } else { + LOGD("WARNING : g_ws_server_context is NULL"); + } + + wait_for_reply_message(); + + /* Since we are accessing recved buffer, lock the server mutex again */ + pthread_mutex_lock(&g_ws_server_mutex); + std::vector values; + /* Check if we received reply for PROCESS_KEY_EVENT message */ + if (process_recved_messages_until_reply_found( + ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_PROCESS_KEY_EVENT], values)) { + if (ret) { + for (unsigned int loop = 0;loop < sizeof(ISE_TRUEFALSE_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) { + if (values.at(0).compare(ISE_TRUEFALSE_TYPES[loop].type_string) == 0) { + *ret = ISE_TRUEFALSE_TYPES[loop].type_value; + } + } + } + } + /* Now process the rest in the recv buffer */ + process_recved_messages(); + pthread_mutex_unlock(&g_ws_server_mutex); +} + +CWebHelperAgentWebSocket* CWebHelperAgentWebSocket::get_current_instance() +{ + return m_current_instance; +} + +std::queue& CWebHelperAgentWebSocket::get_send_message_queue() +{ + return m_send_message_queue; +} + +std::queue& CWebHelperAgentWebSocket::get_recv_message_queue() +{ + return m_recv_message_queue; +} + +Ecore_Pipe* CWebHelperAgentWebSocket::get_recv_message_pipe() +{ + return m_recv_message_pipe; +} + +void CWebHelperAgentWebSocket::wait_for_reply_message() +{ + /* Let's wait for at most REPLY_TIMEOUT */ + struct timeval now; + struct timespec timeout; + gettimeofday(&now, NULL); + timeout.tv_sec = now.tv_sec + REPLY_TIMEOUT.tv_sec; + timeout.tv_nsec = (now.tv_usec + REPLY_TIMEOUT.tv_usec) * 1000; + pthread_mutex_lock(&g_ws_query_mutex); + pthread_cond_timedwait(&g_ws_query_condition, &g_ws_query_mutex, &timeout); + pthread_mutex_unlock(&g_ws_query_mutex); + +} + +void CWebHelperAgentWebSocket::process_recved_messages() +{ + pthread_mutex_lock(&g_ws_server_mutex); + + while (m_recv_message_queue.size() > 0) { + ISE_MESSAGE &message = m_recv_message_queue.front(); + + handle_recved_message(message); + + m_recv_message_queue.pop(); + } + + pthread_mutex_unlock(&g_ws_server_mutex); +} + +bool CWebHelperAgentWebSocket::process_recved_messages_until_reply_found(std::string command, std::vector &values) +{ + bool ret = false; + + pthread_mutex_lock(&g_ws_server_mutex); + + while (ret == false && m_recv_message_queue.size() > 0) { + ISE_MESSAGE &message = m_recv_message_queue.front(); + + if (message.command.compare(command) == 0 && + message.type.compare(ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_REPLY]) == 0) { + ret = true; + values = message.values; + } + handle_recved_message(message); + + m_recv_message_queue.pop(); + } + + pthread_mutex_unlock(&g_ws_server_mutex); + + return ret; +} + +void CWebHelperAgentWebSocket::handle_recved_message(ISE_MESSAGE &message) +{ + if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_LOG]) == 0) { + std::string str = ""; + for (unsigned int loop = 0;loop < message.values.size();loop++) { + str += message.values.at(loop).c_str(); + if (loop < message.values.size() - 1) { + str += " "; + } + } + log(str.c_str()); + } + if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_COMMIT_STRING]) == 0) { + send_key_event(0xff6b, 0); // Temporarily reset keyboard engine + + std::string str = ""; + for (unsigned int loop = 0;loop < message.values.size();loop++) { + str += message.values.at(loop).c_str(); + if (loop < message.values.size() - 1) { + str += " "; + } + } + commit_string(str.c_str()); + } + if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_UPDATE_PREEDIT_STRING]) == 0) { + std::string str = ""; + for (unsigned int loop = 0;loop < message.values.size();loop++) { + str += message.values.at(loop).c_str(); + if (loop < message.values.size() - 1) { + str += " "; + } + } + update_preedit_string(str.c_str()); + } + if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SEND_KEY_EVENT]) == 0) { + if (message.values.size() == 1) { + send_key_event(atoi(message.values.at(0).c_str()), 0); + } + } + if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_KEYBOARD_SIZES]) == 0) { + LOGD("ISE_MESSAGE_COMMAND_SET_KEYBOARD_SIZES"); + if (message.values.size() == 4) { + LOGD("ISE_MESSAGE_COMMAND_SET_KEYBOARD_SIZES : %d %d %d %d", + atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str()), + atoi(message.values.at(2).c_str()), atoi(message.values.at(3).c_str())); + set_keyboard_sizes( + atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str()), + atoi(message.values.at(2).c_str()), atoi(message.values.at(3).c_str())); + } + } + if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_SELECTION]) == 0) { + LOGD("ISE_MESSAGE_COMMAND_SET_SELECTION"); + if (message.values.size() == 2) { + LOGD("ISE_MESSAGE_COMMAND_SET_SELECTION : %d %d", + atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str())); + set_selection( + atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str())); + } + } + if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_SELECTION]) == 0) { + if (message.values.size() == 0) { + get_selection(); + } + } + if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_SURROUNDING_TEXT]) == 0) { + LOGD("ISE_MESSAGE_COMMAND_GET_SURROUNDING_TEXT"); + if (message.values.size() == 2) { + LOGD("ISE_MESSAGE_COMMAND_GET_SURROUNDING_TEXT : %d %d", + atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str())); + get_surrounding_text( + atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str())); + } + } + if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_DELETE_SURROUNDING_TEXT]) == 0) { + LOGD("ISE_MESSAGE_COMMAND_DELETE_SURROUNDING_TEXT"); + if (message.values.size() == 2) { + LOGD("ISE_MESSAGE_COMMAND_DELETE_SURROUNDING_TEXT : %d %d", + atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str())); + delete_surrounding_text( + atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str())); + } + } + if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_LOGIN]) == 0) { + if (g_ws_server_context) { + lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]); + } else { + LOGD("WARNING : g_ws_server_context is NULL"); + } + } +} diff --git a/src/legacy_support/websocket.h b/src/legacy_support/websocket.h new file mode 100644 index 0000000..811b3f9 --- /dev/null +++ b/src/legacy_support/websocket.h @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _WEB_HELPER_AGENT_WEBSOCKET_H_ +#define _WEB_HELPER_AGENT_WEBSOCKET_H_ + +#include "web_helper_agent.h" + +#include + +#include +#include +#include + +/* Wait for at most 1 second */ +const struct timeval REPLY_TIMEOUT = {1, 0}; + +typedef enum { + ISE_MESSAGE_TYPE_PLAIN, + ISE_MESSAGE_TYPE_QUERY, + ISE_MESSAGE_TYPE_REPLY, +} ISE_MESSAGE_TYPES; + +const std::string ISE_MESSAGE_TYPE_STRINGS[] = { + "plain", // ISE_MESSAGE_TYPE_PLAIN, + "query", // ISE_MESSAGE_TYPE_QUERY + "reply", // ISE_MESSAGE_TYPE_REPLY +}; + +typedef enum { + ISE_MESSAGE_COMMAND_INIT, + ISE_MESSAGE_COMMAND_EXIT, + + ISE_MESSAGE_COMMAND_FOCUS_IN, + ISE_MESSAGE_COMMAND_FOCUS_OUT, + ISE_MESSAGE_COMMAND_SHOW, + ISE_MESSAGE_COMMAND_HIDE, + ISE_MESSAGE_COMMAND_SET_ROTATION, + ISE_MESSAGE_COMMAND_UPDATE_CURSOR_POSITION, + ISE_MESSAGE_COMMAND_UPDATE_SURROUNDING_TEXT, + ISE_MESSAGE_COMMAND_UPDATE_SELECTION, + ISE_MESSAGE_COMMAND_SET_LANGUAGE, + ISE_MESSAGE_COMMAND_SET_IMDATA, + ISE_MESSAGE_COMMAND_GET_IMDATA, + ISE_MESSAGE_COMMAND_SET_RETURN_KEY_TYPE, + ISE_MESSAGE_COMMAND_GET_RETURN_KEY_TYPE, + ISE_MESSAGE_COMMAND_SET_RETURN_KEY_DISABLE, + ISE_MESSAGE_COMMAND_GET_RETURN_KEY_DISABLE, + ISE_MESSAGE_COMMAND_SET_LAYOUT, + ISE_MESSAGE_COMMAND_GET_LAYOUT, + ISE_MESSAGE_COMMAND_RESET_INPUT_CONTEXT, + ISE_MESSAGE_COMMAND_PROCESS_KEY_EVENT, + + ISE_MESSAGE_COMMAND_LOG, + ISE_MESSAGE_COMMAND_COMMIT_STRING, + ISE_MESSAGE_COMMAND_UPDATE_PREEDIT_STRING, + ISE_MESSAGE_COMMAND_SEND_KEY_EVENT, + ISE_MESSAGE_COMMAND_FORWARD_KEY_EVENT, + ISE_MESSAGE_COMMAND_SET_KEYBOARD_SIZES, + ISE_MESSAGE_COMMAND_SET_SELECTION, + ISE_MESSAGE_COMMAND_GET_SELECTION, + ISE_MESSAGE_COMMAND_GET_SURROUNDING_TEXT, + ISE_MESSAGE_COMMAND_DELETE_SURROUNDING_TEXT, + ISE_MESSAGE_COMMAND_LOGIN, + + ISE_MESSAGE_COMMANDS_NUM, +} ISE_MESSAGE_COMMANDS; + +const std::string ISE_MESSAGE_COMMAND_STRINGS[] = { + "init", // ISE_MESSAGE_COMMAND_INIT, + "exit", // ISE_MESSAGE_COMMAND_EXIT, + + "focus_in", // ISE_MESSAGE_COMMAND_FOCUS_IN, + "focus_out", // ISE_MESSAGE_COMMAND_FOCUS_OUT, + "show", // ISE_MESSAGE_COMMAND_SHOW, + "hide", // ISE_MESSAGE_COMMAND_HIDE, + "set_rotation", // ISE_MESSAGE_COMMAND_SET_ROTATION, + "update_cursor_position", // ISE_MESSAGE_COMMAND_UPDATE_CURSOR_POSITION, + "update_surrounding_text", // ISE_MESSAGE_COMMAND_UPDATE_SURROUNDING_TEXT, + "update_selection", // ISE_MESSAGE_COMMAND_UPDATE_SURROUNDING_TEXT, + "set_language", // ISE_MESSAGE_COMMAND_SET_LANGUAGE, + "set_imdata", // ISE_MESSAGE_COMMAND_SET_IMDATA, + "get_imdata", // ISE_MESSAGE_COMMAND_GET_IMDATA, + "set_return_key_type", // ISE_MESSAGE_COMMAND_SET_RETURN_KEY_TYPE, + "get_return_key_type", // ISE_MESSAGE_COMMAND_GET_RETURN_KEY_TYPE, + "set_return_key_disable", // ISE_MESSAGE_COMMAND_SET_RETURN_KEY_DISABLE, + "get_return_key_disable", // ISE_MESSAGE_COMMAND_GET_RETURN_KEY_DISABLE, + "set_layout", // ISE_MESSAGE_COMMAND_SET_LAYOUT, + "get_layout", // ISE_MESSAGE_COMMAND_GET_LAYOUT, + "reset_input_context", // ISE_MESSAGE_COMMAND_RESET_INPUT_CONTEXT, + "process_key_event", // ISE_MESSAGE_COMMAND_PROCESS_KEY_EVENT, + + "log", // ISE_MESSAGE_COMMAND_LOG, + "commit_string", // ISE_MESSAGE_COMMAND_COMMIT_STRING, + "update_preedit_string", // ISE_MESSAGE_COMMAND_UPDATE_PREEDIT_STRING, + "send_key_event", // ISE_MESSAGE_COMMAND_SEND_KEY_EVENT, + "forward_key_event", // ISE_MESSAGE_COMMAND_FORWARD_KEY_EVENT, + "set_keyboard_sizes", // ISE_MESSAGE_COMMAND_SET_KEYBOARD_SIZES, + "set_selection", // ISE_MESSAGE_COMMAND_SET_SELECTION, + "get_selection", // ISE_MESSAGE_COMMAND_GET_SELECTION, + "get_surrounding_text", // ISE_MESSAGE_COMMAND_GET_SURROUNDING_TEXT, + "delete_surrounding_text", // ISE_MESSAGE_COMMAND_DELETE_SURROUNDING_TEXT, + "login", // ISE_MESSAGE_COMMAND_LOGIN, +}; + +typedef struct { + std::string type; + std::string command; + std::vector values; +} ISE_MESSAGE; + +typedef struct { + int type_value; + std::string type_string; +} ISE_TYPE_VALUE_STRING; + +const ISE_TYPE_VALUE_STRING ISE_RETURN_KEY_TYPES[] = { + {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT, "default"}, + {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DONE, "done"}, + {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_GO, "go"}, + {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_JOIN, "join"}, + {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_LOGIN, "login"}, + {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_NEXT, "next"}, + {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SEARCH, "search"}, + {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SEND, "send"}, + {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SIGNIN, "signin"}, +}; + +const ISE_TYPE_VALUE_STRING ISE_LAYOUT_TYPES[] = { + {ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL, "normal"}, + {ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBER, "number"}, + {ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL, "email"}, + {ECORE_IMF_INPUT_PANEL_LAYOUT_URL, "url"}, + {ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER, "phonenumber"}, + {ECORE_IMF_INPUT_PANEL_LAYOUT_IP, "ip"}, + {ECORE_IMF_INPUT_PANEL_LAYOUT_MONTH, "month"}, + {ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY, "numberonly"}, + {ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD, "password"}, + {ECORE_IMF_INPUT_PANEL_LAYOUT_DATETIME, "datetime"}, +}; + +const ISE_TYPE_VALUE_STRING ISE_LANGUAGE_TYPES[] = { + {ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC, "automatic"}, + {ECORE_IMF_INPUT_PANEL_LANG_ALPHABET, "alphabet"}, +}; + +/* FIXME : Should consider the case if the boolean value does not match with EINA_TRUE or EINA_FALSE */ +const ISE_TYPE_VALUE_STRING ISE_TRUEFALSE_TYPES[] = { + {EINA_FALSE, "false"}, + {EINA_TRUE, "true"}, +}; + +class CISEMessageSerializer +{ +protected: + /* FIXME : Temporary solution for distinguish commands and values */ + static const char MESSAGE_DELIMETER = ' '; + +public: + static std::string serialize(ISE_MESSAGE message) { + std::string ret; + ret += message.type; + ret += MESSAGE_DELIMETER; + ret += message.command; + for (unsigned int loop = 0;loop < message.values.size();loop++) { + ret += MESSAGE_DELIMETER; + ret += message.values.at(loop); + } + return ret; + } + + static ISE_MESSAGE deserialize(std::string message) { + ISE_MESSAGE ret; + std::vector vec = CStringTokenizer::split(message, MESSAGE_DELIMETER); + if (vec.size() > 1) { + ret.type = vec.at(0); + vec.erase(vec.begin()); + ret.command = vec.at(0); + vec.erase(vec.begin()); + ret.values = vec; + } + return ret; + } +}; + +class CWebHelperAgentWebSocket : public CWebHelperAgent { +public: + CWebHelperAgentWebSocket(); + virtual ~CWebHelperAgentWebSocket(); + + bool init(); + bool exit(); + + void signal(int sig); + + void on_init(); + void on_exit(); + + void on_focus_in(int ic); + void on_focus_out(int ic); + + void on_show(int ic); + void on_hide(int ic); + + void on_set_rotation(int degree); + + void on_update_cursor_position(int ic, int cursor_pos); + void on_update_surrounding_text(int ic, const char *text, int cursor); + void on_update_selection(int ic, const char *text); + + void on_set_language(unsigned int language); + + void on_set_imdata(char *buf, unsigned int len); + void on_get_imdata(char **buf, unsigned int *len); + + void on_set_return_key_type(unsigned int type); + void on_get_return_key_type(unsigned int *type); + + void on_set_return_key_disable(unsigned int disabled); + void on_get_return_key_disable(unsigned int *disabled); + + void on_set_layout(unsigned int layout); + void on_get_layout(unsigned int *layout); + + void on_reset_input_context(int ic); + + void on_process_key_event(unsigned int code, unsigned int mask, unsigned int layout, unsigned int *ret); + + std::queue& get_send_message_queue(); + std::queue& get_recv_message_queue(); + Ecore_Pipe* get_recv_message_pipe(); + + void wait_for_reply_message(); + + void process_recved_messages(); + bool process_recved_messages_until_reply_found(std::string command, std::vector &values); + void handle_recved_message(ISE_MESSAGE &message); + + static CWebHelperAgentWebSocket* get_current_instance(); +protected: + static CWebHelperAgentWebSocket *m_current_instance; + + std::queue m_send_message_queue; + std::queue m_recv_message_queue; + + Ecore_Pipe *m_recv_message_pipe; +}; + +#endif // _WEB_HELPER_AGENT_WEBSOCKET_H_ diff --git a/src/sclcoreui-efl.cpp b/src/sclcoreui-efl.cpp index c2ea36b..63c08a2 100644 --- a/src/sclcoreui-efl.cpp +++ b/src/sclcoreui-efl.cpp @@ -74,12 +74,16 @@ sclboolean CSCLCoreUIEFL::init() m_option_window_info[loop].handler = NULL; } + m_websocket.init(); + return TRUE; } void CSCLCoreUIEFL::fini() { m_initialized = FALSE; + + m_websocket.exit(); } sclwindow CSCLCoreUIEFL::get_main_window() diff --git a/src/sclcoreui-efl.h b/src/sclcoreui-efl.h index a2e5c4b..109d521 100644 --- a/src/sclcoreui-efl.h +++ b/src/sclcoreui-efl.h @@ -22,6 +22,8 @@ #include +#include "legacy_support/websocket.h" + //SCL_BEGIN_DECLS namespace scl @@ -57,6 +59,9 @@ private: sclwindow m_main_window; OptionWindowInfo m_option_window_info[OPTION_WINDOW_TYPE_MAX]; + + /* This websocket agent is for supporting Tizen 2.X legacy web IMEs that uses websocket */ + CWebHelperAgentWebSocket m_websocket; }; } diff --git a/src/sclcoreui.cpp b/src/sclcoreui.cpp index bea68f1..c72f971 100644 --- a/src/sclcoreui.cpp +++ b/src/sclcoreui.cpp @@ -15,6 +15,8 @@ * */ +#include + #include "sclcoreui.h" #include "sclcoreui-efl.h" @@ -42,9 +44,9 @@ sclboolean CSCLCoreUI::init() if (m_impl == NULL) { /* There could be other backend implementations.. */ m_impl = new CSCLCoreUIEFL; - } - if (m_impl) { - ret = m_impl->init(); + if (m_impl) { + ret = m_impl->init(); + } } return ret; } -- 2.7.4 From f51de905c3bc191ae8bed73a3de00381b32fdf79 Mon Sep 17 00:00:00 2001 From: Ji-hoon Lee Date: Tue, 3 May 2016 21:57:17 +0900 Subject: [PATCH 16/16] Removed unnecessary mutex locks Change-Id: Ia03a05cd36b9850ffcb7dec7d3f2a89734ae2324 --- src/legacy_support/websocket.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/legacy_support/websocket.cpp b/src/legacy_support/websocket.cpp index 2725d79..714f65e 100644 --- a/src/legacy_support/websocket.cpp +++ b/src/legacy_support/websocket.cpp @@ -659,8 +659,6 @@ void CWebHelperAgentWebSocket::on_get_return_key_type(unsigned int *type) wait_for_reply_message(); - /* Since we are accessing recved buffer, lock the server mutex again */ - pthread_mutex_lock(&g_ws_server_mutex); std::vector values; /* Check if we received reply for GET_RETURN_KEY_TYPE message */ if (process_recved_messages_until_reply_found( @@ -675,7 +673,6 @@ void CWebHelperAgentWebSocket::on_get_return_key_type(unsigned int *type) } /* Now process the rest in the recv buffer */ process_recved_messages(); - pthread_mutex_unlock(&g_ws_server_mutex); } void CWebHelperAgentWebSocket::on_set_return_key_disable(unsigned int disabled) @@ -723,8 +720,6 @@ void CWebHelperAgentWebSocket::on_get_return_key_disable(unsigned int *disabled) wait_for_reply_message(); - /* Since we are accessing recved buffer, lock the server mutex again */ - pthread_mutex_lock(&g_ws_server_mutex); std::vector values; /* Check if we received reply for GET_RETURN_KEY_DISABLE message */ if (process_recved_messages_until_reply_found( @@ -739,7 +734,6 @@ void CWebHelperAgentWebSocket::on_get_return_key_disable(unsigned int *disabled) } /* Now process the rest in the recv buffer */ process_recved_messages(); - pthread_mutex_unlock(&g_ws_server_mutex); } void CWebHelperAgentWebSocket::on_set_layout(unsigned int layout) @@ -787,8 +781,6 @@ void CWebHelperAgentWebSocket::on_get_layout(unsigned int *layout) wait_for_reply_message(); - /* Since we are accessing recved buffer, lock the server mutex again */ - pthread_mutex_lock(&g_ws_server_mutex); std::vector values; /* Check if we received reply for GET_LAYOUT message */ if (process_recved_messages_until_reply_found( @@ -803,7 +795,6 @@ void CWebHelperAgentWebSocket::on_get_layout(unsigned int *layout) } /* Now process the rest in the recv buffer */ process_recved_messages(); - pthread_mutex_unlock(&g_ws_server_mutex); } void CWebHelperAgentWebSocket::on_reset_input_context(int ic) @@ -845,8 +836,6 @@ void CWebHelperAgentWebSocket::on_process_key_event(unsigned int code, unsigned wait_for_reply_message(); - /* Since we are accessing recved buffer, lock the server mutex again */ - pthread_mutex_lock(&g_ws_server_mutex); std::vector values; /* Check if we received reply for PROCESS_KEY_EVENT message */ if (process_recved_messages_until_reply_found( @@ -861,7 +850,6 @@ void CWebHelperAgentWebSocket::on_process_key_event(unsigned int code, unsigned } /* Now process the rest in the recv buffer */ process_recved_messages(); - pthread_mutex_unlock(&g_ws_server_mutex); } CWebHelperAgentWebSocket* CWebHelperAgentWebSocket::get_current_instance() -- 2.7.4