tizen 2.3.1 release tizen_2.3.1 submit/tizen_2.3.1/20150915.083137 tizen_2.3.1_release
authorjk7744.park <jk7744.park@samsung.com>
Tue, 8 Sep 2015 13:51:55 +0000 (22:51 +0900)
committerjk7744.park <jk7744.park@samsung.com>
Tue, 8 Sep 2015 13:51:55 +0000 (22:51 +0900)
39 files changed:
AUTHORS [new file with mode: 0644]
CMakeLists.txt [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
LICENSE [new file with mode: 0755]
NEWS [new file with mode: 0644]
NOTICE [new file with mode: 0644]
README [new file with mode: 0644]
data/ise-web-helper-agent.help [new file with mode: 0644]
data/sample/css/style.css [new file with mode: 0755]
data/sample/images/html5.png [new file with mode: 0644]
data/sample/images/icon_back.png [new file with mode: 0644]
data/sample/images/icon_enter.png [new file with mode: 0644]
data/sample/images/icon_shift.png [new file with mode: 0644]
data/sample/images/icon_shift_on.png [new file with mode: 0644]
data/sample/images/icon_space.png [new file with mode: 0644]
data/sample/images/tizen_32.png [new file with mode: 0755]
data/sample/index.html [new file with mode: 0644]
data/sample/js/web-helper-client.js [new file with mode: 0644]
ise-web-helper-agent.efl [new file with mode: 0644]
ise-web-helper-agent.manifest [new file with mode: 0755]
ise-web-helper-agent.xml [new file with mode: 0644]
packaging/ise-web-helper-agent.changes [new file with mode: 0644]
packaging/ise-web-helper-agent.spec [new file with mode: 0644]
src/common.cpp [new file with mode: 0644]
src/include/common.h [new file with mode: 0644]
src/include/ise.h [new file with mode: 0644]
src/include/packages.h [new file with mode: 0644]
src/include/web_container.h [new file with mode: 0644]
src/include/web_helper_agent.h [new file with mode: 0644]
src/ise.cpp [new file with mode: 0644]
src/main.cpp [new file with mode: 0644]
src/packages.cpp [new file with mode: 0644]
src/web_container.cpp [new file with mode: 0644]
src/web_container_plugin.cpp [new file with mode: 0644]
src/web_helper_agent.cpp [new file with mode: 0644]
src/web_helper_agents/direct.cpp [new file with mode: 0644]
src/web_helper_agents/direct.h [new file with mode: 0644]
src/web_helper_agents/websocket.cpp [new file with mode: 0644]
src/web_helper_agents/websocket.h [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..2e8a0de
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,2 @@
+Developer:
+  Ji-hoon Lee <dalton.lee at samsung dot com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..0c2678b
--- /dev/null
@@ -0,0 +1,111 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(ise-web-helper-agent CXX)
+
+SET(ISE_SRCS
+    src/main.cpp
+    src/common.cpp
+    src/ise.cpp
+    src/packages.cpp
+    src/web_container.cpp
+    src/web_helper_agent.cpp
+    src/web_helper_agents/websocket.cpp
+    src/web_helper_agents/direct.cpp
+)
+
+SET(ISE_PACKAGE ${PROJECT_NAME})
+SET(ISE_PKGNAME ${PACKAGE})
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(ISE_LIBDIR "${PREFIX}/lib/scim-1.0/1.4.0/Helper")
+SET(MANIFEST_DIR "${PREFIX}/share/packages")
+
+IF("${CMAKE_BUILD_TYPE}" STREQUAL "")
+    SET(CMAKE_BUILD_TYPE "Release")
+ENDIF()
+MESSAGE(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/include
+    ${CMAKE_SOURCE_DIR}/src/web_helper_agents
+    ${CMAKE_SOURCE_DIR}/src )
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(ISE_PKGS REQUIRED
+        elementary
+        dlog
+        ecore-imf
+        isf
+        vconf
+        libwebsockets
+        pkgmgr-info
+        capi-appfw-package-manager
+        )
+
+FOREACH(flag ${ISE_PKGS_CFLAGS})
+    SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -fPIC -Wall")
+#SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -finstrument-functions")
+SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_CXX_FLAGS_RELEASE "-O2 -g")
+
+ADD_DEFINITIONS("-DPACKAGE=\"${ISE_PACKAGE}\"")
+ADD_DEFINITIONS("-DPACKAGE_NAME=\"${ISE_PKGNAME}\"")
+
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${ISE_SRCS})
+
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${ISE_PKGS_LDFLAGS})
+
+set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${ISE_LIBDIR})
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/${PROJECT_NAME}.efl DESTINATION
+            /etc/smack/accesses.d/)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/${PROJECT_NAME}.xml DESTINATION
+            ${MANIFEST_DIR})
+
+###########################################
+# Web container plugin so #
+###########################################
+
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(web-container CXX)
+
+SET(WEB_CONTAINER_SRCS
+    src/packages.cpp
+    src/web_container_plugin.cpp
+)
+
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(ISF_LIBDIR "${PREFIX}/lib/scim-1.0/")
+
+IF("${CMAKE_BUILD_TYPE}" STREQUAL "")
+    SET(CMAKE_BUILD_TYPE "Release")
+ENDIF()
+MESSAGE(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/include
+    ${CMAKE_SOURCE_DIR}/src )
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(WEB_CONTAINER_PKGS REQUIRED
+        evas
+        dlog
+        ewebkit2
+        wrt-core
+        dpl-efl
+        )
+
+FOREACH(flag ${WEB_CONTAINER_PKGS_CFLAGS})
+    SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -fPIC -Wall -std=c++0x")
+#SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -finstrument-functions")
+SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_CXX_FLAGS_RELEASE "-O2 -g")
+
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${WEB_CONTAINER_SRCS})
+
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${WEB_CONTAINER_PKGS_LDFLAGS})
+
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES PREFIX "")
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${ISF_LIBDIR})
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..eed36bd
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,4 @@
+2014-04-15     11:15   Ji-hoon Lee <dalton.lee@samsung.com>
+
+       Initial version.
+
diff --git a/LICENSE b/LICENSE
new file mode 100755 (executable)
index 0000000..d645695
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/NOTICE b/NOTICE
new file mode 100644 (file)
index 0000000..aca1a51
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,6 @@
+Copyright (c) 2012 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
+Except as noted, this software is licensed under Apache License, Version 2.
+Please, see the LICENSE file for Apache License terms and conditions.
+
+ise-web-helper-agent is based in part on the work of the libwebsockets project
+(http://libwebsockets.org)
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..dde6230
--- /dev/null
+++ b/README
@@ -0,0 +1,5 @@
+ise-web-helper-agent
+==============
+
+This is a container ISE for web-based keyboards
+
diff --git a/data/ise-web-helper-agent.help b/data/ise-web-helper-agent.help
new file mode 100644 (file)
index 0000000..4b03846
--- /dev/null
@@ -0,0 +1,3 @@
+Web Helerper Agent:
+    A Container For Supporting Web-based Keyboards
+    By Samsung Electronics
diff --git a/data/sample/css/style.css b/data/sample/css/style.css
new file mode 100755 (executable)
index 0000000..f5acfc8
--- /dev/null
@@ -0,0 +1,140 @@
+/* CSS for web keyboard */
+
+body {
+       background:#111121;
+       margin:0;
+       margin-top:10px;
+       padding:0;
+}
+.tbl1 {
+       border:0px;
+       border-spacing: 2px 1px;
+       width:100%;
+       height:100%;
+}
+.tr25 .td25 {
+       height:25%;
+}
+.tr100 {
+       height:100%;
+}
+.key5 {
+       width:5%;
+       align:center;
+}
+.key10 {
+       width:10%;
+       align:center;
+}
+.key15 {
+       width:15%;
+       align:center;
+}
+.key40 {
+       width:40%;
+       align:center;
+}
+.visible {
+       background-color:#111124;
+       display:block;
+}
+.invisible {
+       background-color:#111124;
+       display:none;
+}
+/* common properties for key */
+.commonBtn, .keyBtn, .keyExBtn, .numsymKeyBtn, .functionKeyBtn, .shiftBtnOff, .shiftBtnOn, .backspaceBtn, .languageBtn,
+.numsymBtn, .spaceBtn, .dotBtn, .enterBtn
+ {
+       -moz-border-radius:2px;
+       -webkit-border-radius:2px;
+       border-radius:2px;
+       border:1px solid #2f3f57;
+       display:inline-block;
+       text-align: center;
+       cursor:pointer;
+       color:#ffffff;
+       font-size:140%;
+       font-family:arial;
+       text-decoration:none;
+       text-shadow:0pt 1pt 0pt #263666;
+       height:100%;
+}
+.commonBtn:active, .keyBtn:active, .keyExBtn:active, .functionKeyBtn:active, .backspaceBtn:active,
+.spaceBtn:active, .dotBtn:active, .enterBtn:active
+{
+       background-color:#4159b9;
+       position:relative;
+       top:-11px;
+}
+/* normal ascii key button */
+.keyBtn {
+       background-color:#2d3755;
+}
+/* lowercase english key button */
+.keyExBtn {
+       background-color:#2d3755;
+       font-size:200%;
+}
+/* numsym key button */
+.numsymKeyBtn {
+       background-color:inherit;
+       font-size:200%;
+}
+/* normal ascii key button */
+.functionKeyBtn {
+       background-color:inherit;
+       font-size:130%;
+}
+/* shift button */
+.shiftBtnOff {
+       background:url(../images/icon_shift.png);
+       background-size:auto 60%;
+       background-repeat:no-repeat;
+       background-position:center;
+}
+/* shift button */
+.shiftBtnOn {
+       background:url(../images/icon_shift_on.png);
+       background-size:auto 60%;
+       background-repeat:no-repeat;
+       background-position:center;
+}
+/* backspace button */
+.backspaceBtn {
+       background:url(../images/icon_back.png);
+       background-repeat:no-repeat;
+       background-size:auto 60%;
+       background-position:center;
+}
+/* language button */
+.languageBtn {
+       background:url(../images/icon_language.png);
+       background-repeat:no-repeat;
+       background-size:auto 60%;
+       background-position:center;
+}
+/* numsym button */
+.numsymBtn {
+       background-color:#111121;
+       font-size:120%;
+}
+/* space button */
+.spaceBtn {
+       background:url(../images/html5.png);
+       background-repeat:no-repeat;
+       background-size:auto 90%;
+       background-position:center;
+}
+/* dot button */
+.dotBtn {
+       background-color:#111121;
+       font-size:100%;
+}
+/* enter button */
+.enterBtn {
+       background:url(../images/icon_enter.png);
+       background-repeat:no-repeat;
+       background-size:auto 60%;
+       background-position:center;
+}
\ No newline at end of file
diff --git a/data/sample/images/html5.png b/data/sample/images/html5.png
new file mode 100644 (file)
index 0000000..e0c2020
Binary files /dev/null and b/data/sample/images/html5.png differ
diff --git a/data/sample/images/icon_back.png b/data/sample/images/icon_back.png
new file mode 100644 (file)
index 0000000..f4caf50
Binary files /dev/null and b/data/sample/images/icon_back.png differ
diff --git a/data/sample/images/icon_enter.png b/data/sample/images/icon_enter.png
new file mode 100644 (file)
index 0000000..1f5f7d5
Binary files /dev/null and b/data/sample/images/icon_enter.png differ
diff --git a/data/sample/images/icon_shift.png b/data/sample/images/icon_shift.png
new file mode 100644 (file)
index 0000000..fa87a43
Binary files /dev/null and b/data/sample/images/icon_shift.png differ
diff --git a/data/sample/images/icon_shift_on.png b/data/sample/images/icon_shift_on.png
new file mode 100644 (file)
index 0000000..d3bc1e7
Binary files /dev/null and b/data/sample/images/icon_shift_on.png differ
diff --git a/data/sample/images/icon_space.png b/data/sample/images/icon_space.png
new file mode 100644 (file)
index 0000000..385389c
Binary files /dev/null and b/data/sample/images/icon_space.png differ
diff --git a/data/sample/images/tizen_32.png b/data/sample/images/tizen_32.png
new file mode 100755 (executable)
index 0000000..647c3f9
Binary files /dev/null and b/data/sample/images/tizen_32.png differ
diff --git a/data/sample/index.html b/data/sample/index.html
new file mode 100644 (file)
index 0000000..42c0e9a
--- /dev/null
@@ -0,0 +1,445 @@
+<html>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
+    <meta name="description" content="Tizen Web IME template generated by Tizen Web IDE"/>
+
+    <title>Tizen Wearable Web IME</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+</head>
+<script type="text/javascript" src="js/web-helper-client.js"></script>
+<script>
+var prevMode = "english-lowercase";
+var WebHelperClientHandler = {
+       onInit : function () {
+               WebHelperClient.log("ON INIT");
+       },
+       onSetLayout : function (layout) {
+               var nextMode;
+               if (layout == "phonenumber") {
+                       nextMode = "numsym1";
+               } else if (layout == "number") {
+                       nextMode = "numsym1";
+               } else {
+                       nextMode = "english-lowercase";
+               }
+               inputModeChanged(prevMode, nextMode);
+               prevMode = nextMode;
+       },
+       onShow : function () {
+               var screenWidth = window.screen.width;
+               var screenHeight = window.screen.height;
+               if (screenWidth < 720) {
+                       WebHelperClient.setKeyboardSizes(screenWidth, screenHeight * 2 / 3, screenHeight, screenWidth * 2 / 3);
+               } else {
+                       WebHelperClient.setKeyboardSizes(screenWidth, screenHeight / 3, screenHeight, screenWidth * 2 / 5);
+               }
+       }
+};
+WebHelperClient.initialize(WebHelperClientHandler);
+</script>
+<script>
+function keyCode(key) {
+       event.preventDefault();
+       if (event.touches.length < 2) {
+               WebHelperClient.sendKeyEvent(key);
+       }
+}
+function keyPressed(key) {
+       event.preventDefault();
+       if (event.touches.length < 2) {
+               WebHelperClient.commitString(key);
+       }
+       return true;
+}
+function backspacePressed() {
+       event.preventDefault();
+       if (event.touches.length < 2) {
+               keyCode(WebHelperClient.Keycode.BACKSPACE);
+       }
+}
+function spacePressed() {
+       event.preventDefault();
+       if (event.touches.length < 2) {
+               keyCode(WebHelperClient.Keycode.SPACE);
+       }
+}
+function enterPressed() {
+       event.preventDefault();
+       if (event.touches.length < 2) {
+               keyCode(WebHelperClient.Keycode.RETURN);
+       }
+}
+function inputModeChanged(from, to) {
+       var process = true;
+       if (event) {
+               event.preventDefault();
+               if (event.touches && event.touches.length >= 2) {
+                       process = false;
+               }
+       }
+       if (process) {
+               var from_div = document.getElementById(from);
+               from_div.style.display = "none";
+               var to_div = document.getElementById(to);
+               to_div.style.display = "block";
+               prevMode = to;
+       }
+}
+</script>
+<body>
+<!-- English-lowercase mode -->
+<div id="english-lowercase" class="visible">
+       <table class="tbl1">
+       <tr class="tr25">
+               <td class="td25">
+                       <table class="tbl1">
+                       <tr class="tr100">
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('q')" ontouchstart="javascript:keyPressed('q')">q</td>
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('w')" ontouchstart="javascript:keyPressed('w')">w</td>
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('e')" ontouchstart="javascript:keyPressed('e')">e</td>
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('r')" ontouchstart="javascript:keyPressed('r')">r</td>
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('t')" ontouchstart="javascript:keyPressed('t')">t</td>
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('y')" ontouchstart="javascript:keyPressed('y')">y</td>
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('u')" ontouchstart="javascript:keyPressed('u')">u</td>
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('i')" ontouchstart="javascript:keyPressed('i')">i</td>
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('o')" ontouchstart="javascript:keyPressed('o')">o</td>
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('p')" ontouchstart="javascript:keyPressed('p')">p</td>
+                       </tr>
+                       </table>
+               </td>
+       </tr>
+       <tr class="tr25">
+               <td class="td25">
+                       <table class="tbl1">
+                       <tr class="tr100">
+                               <td class="key5">
+                               </td>
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('a')" ontouchstart="javascript:keyPressed('a')">a</td>
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('s')" ontouchstart="javascript:keyPressed('s')">s</td>
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('d')" ontouchstart="javascript:keyPressed('d')">d</td>
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('f')" ontouchstart="javascript:keyPressed('f')">f</td>
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('g')" ontouchstart="javascript:keyPressed('g')">g</td>
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('h')" ontouchstart="javascript:keyPressed('h')">h</td>
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('j')" ontouchstart="javascript:keyPressed('j')">j</td>
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('k')" ontouchstart="javascript:keyPressed('k')">k</td>
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('l')" ontouchstart="javascript:keyPressed('l')">l</td>
+                               <td class="key5">
+                               </td>
+                       </tr>
+                       </table>
+               </td>
+       </tr>
+       <tr class="tr25">
+               <td class="td25">
+                       <table class="tbl1">
+                       <tr class="tr100">
+                               <td class="key15 shiftBtnOff" onmousedown="javascript:inputModeChanged('english-lowercase','english-uppercase')" ontouchstart="javascript:inputModeChanged('english-lowercase','english-uppercase')">&nbsp;</td>
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('z')" ontouchstart="javascript:keyPressed('z')">z</td>
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('x')" ontouchstart="javascript:keyPressed('x')">x</td>
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('c')" ontouchstart="javascript:keyPressed('c')">c</td>
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('v')" ontouchstart="javascript:keyPressed('v')">v</td>
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('b')" ontouchstart="javascript:keyPressed('b')">b</td>
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('n')" ontouchstart="javascript:keyPressed('n')">n</td>
+                               <td class="key10 keyBtn" onmousedown="javascript:keyPressed('m')" ontouchstart="javascript:keyPressed('m')">m</td>
+                               <td class="key15 backspaceBtn" onmousedown="javascript:backspacePressed()" ontouchstart="javascript:backspacePressed()">&nbsp;</td>
+                       </tr>
+                       </table>
+               </td>
+       </tr>
+       <tr class="tr25">
+               <td class="td25">
+                       <table class="tbl1">
+                       <tr class="tr100">
+                               <td class="key15 numsymBtn" onmousedown="javascript:inputModeChanged('english-lowercase','numsym1')" ontouchstart="javascript:inputModeChanged('english-lowercase','numsym1')">123</td>
+                               <td class="key15 functionKeyBtn" onmousedown="javascript:keyPressed(',')" ontouchstart="javascript:keyPressed(',')">,</td>
+                               <td class="key40 spaceBtn" onmousedown="javascript:spacePressed()" ontouchstart="javascript:spacePressed()" >&nbsp;</td>
+                               <td class="key15 functionKeyBtn" onmousedown="javascript:keyPressed('.')" ontouchstart="javascript:keyPressed('.')">.</td>
+                               <td class="key15 enterBtn" onmousedown="javascript:enterPressed()" ontouchstart="javascript:enterPressed()">&nbsp;</td>
+                       </tr>
+                       </table>
+               </td>
+       </tr>
+       </table>
+</div>
+<!-- /page - English-uppercase mode -->
+<!-- English-uppercase mode -->
+<div id="english-uppercase" class="invisible">
+       <table class="tbl1">
+       <tr class="tr25">
+               <td class="td25">
+                       <table class="tbl1">
+                       <tr class="tr100">
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('Q')" ontouchstart="javascript:keyPressed('Q')">Q
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('W')" ontouchstart="javascript:keyPressed('W')">W
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('E')" ontouchstart="javascript:keyPressed('E')">E
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('R')" ontouchstart="javascript:keyPressed('R')">R
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('T')" ontouchstart="javascript:keyPressed('T')">T
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('Y')" ontouchstart="javascript:keyPressed('Y')">Y
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('U')" ontouchstart="javascript:keyPressed('U')">U
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('I')" ontouchstart="javascript:keyPressed('I')">I
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('O')" ontouchstart="javascript:keyPressed('O')">O
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('P')" ontouchstart="javascript:keyPressed('P')">P
+                               </td>
+                       </tr>
+                       </table>
+               </td>
+       </tr>
+       <tr class="tr25">
+               <td class="td25">
+                       <table class="tbl1">
+                       <tr class="tr100">
+                               <td class="key5">
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('A')" ontouchstart="javascript:keyPressed('A')">A
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('S')" ontouchstart="javascript:keyPressed('S')">S
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('D')" ontouchstart="javascript:keyPressed('D')">D
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('F')" ontouchstart="javascript:keyPressed('F')">F
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('G')" ontouchstart="javascript:keyPressed('G')">G
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('H')" ontouchstart="javascript:keyPressed('H')">H
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('J')" ontouchstart="javascript:keyPressed('J')">J
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('K')" ontouchstart="javascript:keyPressed('K')">K
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('L')" ontouchstart="javascript:keyPressed('L')">L
+                               </td>
+                               <td class="key5">
+                               </td>
+                       </tr>
+                       </table>
+               </td>
+       </tr>
+       <tr class="tr25">
+               <td class="td25">
+                       <table class="tbl1">
+                       <tr class="tr100">
+                               <td class="key15 shiftBtnOn"
+                                       onmousedown="javascript:inputModeChanged('english-uppercase', 'english-lowercase')" ontouchstart="javascript:inputModeChanged('english-uppercase', 'english-lowercase')">&nbsp;
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('Z')" ontouchstart="javascript:keyPressed('Z')">Z
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('X')" ontouchstart="javascript:keyPressed('X')">X
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('C')" ontouchstart="javascript:keyPressed('C')">C
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('V')" ontouchstart="javascript:keyPressed('V')">V
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('B')" ontouchstart="javascript:keyPressed('B')">B
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('N')" ontouchstart="javascript:keyPressed('N')">N
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('M')" ontouchstart="javascript:keyPressed('M')">M
+                               </td>
+                               <td class="key15 backspaceBtn"
+                                       onmousedown="javascript:backspacePressed()" ontouchstart="javascript:backspacePressed()">&nbsp;
+                               </td>
+                       </tr>
+                       </table>
+               </td>
+       </tr>
+       <tr class="tr25">
+               <td class="td25">
+                       <table class="tbl1">
+                       <tr class="tr100">
+                               <td class="key15 numsymBtn"
+                                       onmousedown="javascript:inputModeChanged('english-uppercase', 'numsym1')" ontouchstart="javascript:inputModeChanged('english-uppercase', 'numsym1')" >123
+                               </td>
+                               <td class="key15 functionKeyBtn" onmousedown="javascript:keyPressed(',')" ontouchstart="javascript:keyPressed(',')">,</td>
+                               <td class="key40 spaceBtn"
+                                       onmousedown="javascript:spacePressed()" ontouchstart="javascript:spacePressed()">&nbsp;
+                               </td>
+                               <td class="key15 functionKeyBtn"
+                                       onmousedown="javascript:keyPressed('.')" ontouchstart="javascript:keyPressed('.')">.
+                               </td>
+                               <td class="key15 enterBtn"
+                                       onmousedown="javascript:enterPressed()" ontouchstart="javascript:enterPressed()">&nbsp;
+                               </td>
+                       </tr>
+                       </table>
+               </td>
+       </tr>
+       </table>
+</div>
+<!-- /page - English-uppercase mode -->
+<!-- Numsym mode (1/2)-->
+<div id="numsym1" class="invisible">
+       <table class="tbl1">
+       <tr class="tr25">
+               <td class="td25">
+                       <table class="tbl1">
+                       <tr class="tr100">
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('1')" ontouchstart="javascript:keyPressed('1')">1
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('2')" ontouchstart="javascript:keyPressed('2')">2
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('3')" ontouchstart="javascript:keyPressed('3')">3
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('4')" ontouchstart="javascript:keyPressed('4')">4
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('5')" ontouchstart="javascript:keyPressed('5')">5
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('6')" ontouchstart="javascript:keyPressed('6')">6
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('7')" ontouchstart="javascript:keyPressed('7')">7
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('8')" ontouchstart="javascript:keyPressed('8')">8
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('9')" ontouchstart="javascript:keyPressed('9')">9
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('0')" ontouchstart="javascript:keyPressed('0')">0
+                               </td>
+                       </tr>
+                       </table>
+               </td>
+       </tr>
+       <tr class="tr25">
+               <td class="td25">
+                       <table class="tbl1">
+                       <tr class="tr100">
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('!')" ontouchstart="javascript:keyPressed('!')">!
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('@')" ontouchstart="javascript:keyPressed('@')">@
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('#')" ontouchstart="javascript:keyPressed('#')">#
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('$')" ontouchstart="javascript:keyPressed('$')">$
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('/')" ontouchstart="javascript:keyPressed('/')">/
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('^')" ontouchstart="javascript:keyPressed('^')">^
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('&')" ontouchstart="javascript:keyPressed('&')">&
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('*')" ontouchstart="javascript:keyPressed('*')">*
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('(')" ontouchstart="javascript:keyPressed('(')">(
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed(')')" ontouchstart="javascript:keyPressed(')')">)
+                               </td>
+                       </tr>
+                       </table>
+               </td>
+       </tr>
+       <tr class="tr25">
+               <td class="td25">
+                       <table class="tbl1">
+                       <tr class="tr100">
+                               <td class="key15 shiftBtnOff"
+                                       onmousedown="javascript:keyPressed('')" ontouchstart="javascript:keyPressed('')">&nbsp;
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('-')" ontouchstart="javascript:keyPressed('-')">-
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('\'')" ontouchstart="javascript:keyPressed('\'')">'
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('&quot;')" ontouchstart="javascript:keyPressed('&quot;')">"
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed(':')" ontouchstart="javascript:keyPressed(':')">:
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed(';')" ontouchstart="javascript:keyPressed(';')">;
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed(',')" ontouchstart="javascript:keyPressed(',')">,
+                               </td>
+                               <td class="key10 keyBtn"
+                                       onmousedown="javascript:keyPressed('?')" ontouchstart="javascript:keyPressed('?')">?
+                               </td>
+                               <td class="key15 backspaceBtn"
+                                       onmousedown="javascript:backspacePressed()" ontouchstart="javascript:backspacePressed()">&nbsp;
+                               </td>
+                       </tr>
+                       </table>
+               </td>
+       </tr>
+       <tr class="tr25">
+               <td class="td25">
+                       <table class="tbl1">
+                       <tr class="tr100">
+                               <td class="key15 numsymBtn"
+                                       onmousedown="javascript:inputModeChanged('numsym1', 'english-lowercase')" ontouchstart="javascript:inputModeChanged('numsym1', 'english-lowercase')" >abc
+                               </td>
+                               <td class="key15 functionKeyBtn" onmousedown="javascript:keyPressed(',')" ontouchstart="javascript:keyPressed(',')">,</td>
+                               <td class="key40 spaceBtn"
+                                       onmousedown="javascript:spacePressed()" ontouchstart="javascript:spacePressed()">&nbsp;
+                               </td>
+                               <td class="key15 functionKeyBtn"
+                                       onmousedown="javascript:keyPressed('.')" ontouchstart="javascript:keyPressed('.')">.
+                               </td>
+                               <td class="key15 enterBtn"
+                                       onmousedown="javascript:enterPressed()" ontouchstart="javascript:enterPressed()">&nbsp;
+                               </td>
+                       </tr>
+                       </table>
+               </td>
+       </tr>
+       </table>
+</div>
+<!-- /page - Numsym(1/2) mode -->
+</body>
+</html>
diff --git a/data/sample/js/web-helper-client.js b/data/sample/js/web-helper-client.js
new file mode 100644 (file)
index 0000000..f8b0818
--- /dev/null
@@ -0,0 +1,876 @@
+/*
+ * Copyright (c) 2012 - 2014 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.
+ *
+ */
+
+var WebHelperClient = {
+       /**
+         * @brief Initialize WebHelperClient object with registering a handler object.
+         *
+         * This is the function that initializes the WebHelperClient object.
+         * Before using the functionalities of WebHelperClient, make sure to call this function
+         * with passing the handler object as its parameter, which implements callback functions
+         * that needs to be handled by the IME.
+         *
+         * @param handler The handler object implementing "on*" callback functions
+         *
+         * @code
+         * var WebHelperClientHandler = {
+         *     onInit : function () {
+         *             // Do what you want when your IME gets the INIT message
+         *     }
+         * };
+         * WebHelperClient.initialize(WebHelperClientHandler);
+         * @endcode
+         */
+       initialize : function (handler) {
+               this.handler = handler;
+               if (this.impl === null) {
+                       this.impl = new this.WebHelperClientInternal(this);
+               }
+       },
+
+       /** IME to ISF requests
+         * The functions below, are used for sending request messages to the ISF.
+         */
+
+       /**
+         * @brief Leave a dlog message.
+         *
+         * @param str The log message to display
+         */
+       log : function(str) {
+               this.impl.log(str);
+       },
+
+       /**
+         * @brief Commit a UTF-8 String to client application directly.
+         *
+         * @param str The byte array of UTF-8 string to be committed.
+         */
+       commitString : function(str) {
+               this.impl.commitString(str);
+       },
+       /**
+         * @brief Update a new UTF-8 string for preedit.
+         *
+         * @param str The byte array of UTF-8 string to be updated.
+         */
+       updatePreeditString : function(str) {
+               this.impl.updatePreeditString(str);
+       },
+       /**
+         * @brief Send a KeyEvent to an client application.
+         *
+         * @param code The KeyEvent to be sent.
+         */
+       sendKeyEvent : function(code) {
+               this.impl.sendKeyEvent(code);
+       },
+       /**
+         * @brief Forward a KeyEvent to client application directly, without translation by Keyboard Engine.
+         *
+         * The difference between the sendKeyEvent and forwardKeyEvent is that the key event
+         * sent via forwardKeyEvent function will not be translated by Keyboard Engine and
+         * will be delivered as it is.
+         *
+         * @param code The KeyEvent to be forwarded.
+         */
+       forwardKeyEvent : function(code) {
+               this.impl.forwardKeyEvent(code);
+       },
+       /**
+         * @brief Updates the keyboard window's geometry information
+         *
+         * @param portraitWidth The width of keyboard, when in portrait mode
+         * @param portraitHeight The height of keyboard, when in portrait mode
+         * @param landscapeWidth The width of keyboard, when in landscape mode
+         * @param landscapeHeight The height of keyboard, when in landscape mode
+         */
+       setKeyboardSizes : function(portraitWidth, portraitHeight, landscapeWidth, landscapeHeight) {
+               this.impl.setKeyboardSizes(portraitWidth, portraitHeight, landscapeWidth, landscapeHeight);
+       },
+       /**
+         * @brief Request to select text
+         *
+         * @param start_index The start position in text
+         * @param end_index The end position in text
+         */
+       setSelection : function(start_index, end_index) {
+               this.impl.setSelection(start_index, end_index);
+       },
+       /**
+         * @brief Request to get selected text
+         */
+       getSelection : function() {
+               this.impl.getSelection();
+       },
+       /**
+         * @brief Request to get surrounding text
+         *
+         * @param maxlen_before The max length of before
+         * @param maxlen_after The max length of after
+         */
+       getSurroundingText : function(maxlen_before, maxlen_after) {
+               this.impl.getSurroundingText(maxlen_before, maxlen_after);
+       },
+       /**
+         * @brief Request to delete surrounding text
+         *
+         * @param offset The offset for cursor position
+         * @param len The length for delete text
+         */
+       deleteSurroundingText : function(offset, len) {
+               this.impl.deleteSurroundingText(offset, len);
+       },
+
+       /** ISF to IME notifications
+         * The functions below, are called when IME needs to be notified.
+         * You can implement these functions in a handler object and pass it to
+         * initialize() function so that your handler functions can be called on each events.
+         */
+
+       /**
+         * @brief Handler on initialization signal.
+         *
+         * This signal is used to notify that the WebIME framework finished initializing.
+         */
+       onInit : function() {
+               if (typeof this.handler.onInit === 'function') {
+                       this.handler.onInit();
+               }
+       },
+       /**
+         * @brief Handler on exit signal.
+         *
+         * This signal is used to notify that this WebIME is about to be terminated.
+         */
+       onExit : function() {
+               if (typeof this.handler.onExit === 'function') {
+                       this.handler.onExit();
+               }
+       },
+       /**
+         * @brief Handler on focus in signal.
+         *
+         * This signal is used to do something when input context is focused in.
+         *
+         * @param inputContext The handle of the client Input Context that sent this event
+         */
+       onFocusIn : function(inputContext) {
+               if (typeof this.handler.onFocusIn === 'function') {
+                       this.handler.onFocusIn(inputContext);
+               }
+       },
+       /**
+         * @brief Handler on focus out signal.
+         *
+         * This signal is used to do something when input context is focused out.
+         *
+         * @param inputContext The handle of the client Input Context that sent this event
+         */
+       onFocusOut : function(inputContext) {
+               if (typeof this.handler.onFocusOut === 'function') {
+                       this.handler.onFocusOut(inputContext);
+               }
+       },
+
+       /**
+         * @brief Handler on show signal.
+         *
+         * This signal is used to show keyboard.
+         *
+         * @param inputContext The handle of the client Input Context that sent this event
+         */
+       onShow : function(inputContext) {
+               if (typeof this.handler.onShow === 'function') {
+                       this.handler.onShow(inputContext);
+               }
+       },
+       /**
+         * @brief Handler on hide signal.
+         *
+         * This signal is used to hide keyboard.
+         *
+         * @param inputContext The handle of the client Input Context that sent this event
+         */
+       onHide : function(inputContext) {
+               if (typeof this.handler.onHide === 'function') {
+                       this.handler.onHide(inputContext);
+               }
+       },
+
+       /**
+         * @brief Handler on rotation signal.
+         *
+         * This signal is used to notify that the keyboard is being rotated.
+         *
+         * @param degree The angle that this keyboard is being rotated to
+         */
+       onSetRotation : function(degree) {
+               if (typeof this.handler.onSetRotation === 'function') {
+                       this.handler.onSetRotation(degree);
+               }
+       },
+
+       /**
+         * @brief Handler on update cursor position signal.
+         *
+         * This signal is used to let the keyboard get the cursor position information.
+         *
+         * @param inputContext The handle of the client Input Context that sent this event
+         * @param position The cursor position
+         */
+       onUpdateCursorPosition : function(inputContext, position) {
+               if (typeof this.handler.onUpdateCursorPosition === 'function') {
+                       this.handler.onUpdateCursorPosition(inputContext, position);
+               }
+       },
+
+       /**
+         * @brief Handler on update surrounding text signal.
+         *
+         * This signal is used to let the keyboard get the surrounding text.
+         *
+         * @param cursor The cursor position
+         * @param text The surrounding text near the cursor
+         */
+       onUpdateSurroundingText: function(cursor, text) {
+               if (typeof this.handler.onUpdateSurroundingText === 'function') {
+                       this.handler.onUpdateSurroundingText(cursor, text);
+               }
+       },
+
+       /**
+         * @brief Handler on update selection signal.
+         *
+         * This signal is used to let the keyboard get the selection.
+         *
+         * @param text The currently selected text
+         */
+       onUpdateSelection: function(text) {
+               if (typeof this.handler.onUpdateSelection === 'function') {
+                       this.handler.onUpdateSelection(text);
+               }
+       },
+
+       /**
+         * @brief Handler on set language signal.
+         *
+         * This signal is used to set input language.
+         *
+         * @param language The language to be set
+         */
+       onSetLanguage : function(language) {
+               if (typeof this.handler.onSetLanguage === 'function') {
+                       this.handler.onSetLanguage(language);
+               }
+       },
+
+       /**
+         * @brief Handler on set im data signal.
+         *
+         * This signal is used to send im data to keyboard.
+         *
+         * @param imdata The imdata to be set
+         */
+       onSetImdata : function(imdata) {
+               if (typeof this.handler.onSetImdata === 'function') {
+                       this.handler.onSetImdata(imdata);
+               }
+       },
+       /**
+         * @brief Handler on get im data signal.
+         *
+         * This signal is used to get im data from keyboard.
+         *
+      * @return the current imdata value
+         */
+       onGetImdata : function() {
+               var imdata = "";
+               if (typeof this.handler.onGetImdata === 'function') {
+                       imdata = this.handler.onGetImdata();
+               }
+               this.impl.replyGetImdata(imdata);
+       },
+
+       /**
+         * @brief Handler on set return key type signal.
+         *
+         * This signal is used to set return key type to keyboard.
+         *
+         * @param type The type of return key to be set, among the following values
+         *             "default", "done", "go", "join", "login",
+         *             "next", "search", "send", "signin"
+         */
+       onSetReturnKeyType : function(type) {
+               if (typeof this.handler.onSetReturnKeyType === 'function') {
+                       this.handler.onSetReturnKeyType(type);
+               }
+       },
+       /**
+         * @brief Handler on get return key type signal.
+         *
+         * This signal is used to get return key type from keyboard.
+         *
+         * @return the current return key type value
+         */
+       onGetReturnKeyType : function() {
+               if (typeof this.handler.onGetReturnKeyType === 'function') {
+                       this.handler.onGetReturnKeyType();
+               }
+       },
+
+       /**
+         * @brief Handler on set return key disable signal.
+         *
+         * This signal is used to set return key disabled state to keyboard.
+         *
+         * @param disabled The value that indicates whether the return key should be disabled or not
+         */
+       onSetReturnKeyDisable : function(disabled) {
+               if (typeof this.handler.onSetReturnKeyDisable === 'function') {
+                       this.handler.onSetReturnKeyDisable(disabled);
+               }
+       },
+       /**
+         * @brief Handler on get return key disable signal.
+         *
+         * This signal is used to get return key disabled state from keyboard.
+         *
+         * @return the current return key disabled state value
+         */
+       onGetReturnKeyDisable : function() {
+               if (typeof this.handler.onGetReturnKeyDisable === 'function') {
+                       this.handler.onGetReturnKeyDisable();
+               }
+       },
+
+       /**
+         * @brief Handler on set virtual keyboard layout signal.
+         *
+         * This signal is used to set virtual keyboard layout, among the following values.
+         *
+         * @param layout The virtual keyboard layout value to be set,
+         *             "normal", "number", "email", "url", "phonenumber",
+         *             "ip", "month", "numberonly", "password", "datetime"
+         */
+       onSetLayout : function(layout) {
+               if (typeof this.handler.onSetLayout === 'function') {
+                       this.handler.onSetLayout(layout);
+               }
+       },
+       /**
+         * @brief Handler on get virtual keyboard layout signal.
+         *
+         * This signal is used to get virtual keyboard layout.
+         *
+         * @return the current virtual keyboard layout value
+         */
+       onGetLayout : function() {
+               if (typeof this.handler.onGetLayout === 'function') {
+                       this.handler.onGetLayout();
+               }
+       },
+
+       /**
+         * @brief Handler on reset input context signal.
+         *
+         * This signal is used to reset keyboard input context.
+         *
+         * @param inputContext The handle of the client Input Context that sent this event
+         */
+       onResetInputContext : function(inputContext) {
+               if (typeof this.handler.onResetInputContext === 'function') {
+                       this.handler.onResetInputContext(inputContext);
+               }
+       },
+
+       /**
+         * @brief Handler on process key event signal.
+         *
+         * @param code The key code of current key event
+         * @param mask The key's modifier mask of current key event
+         * @param layout The hardware keyboard layout identifier
+         *
+      * @return true if the event is processed, otherwise it will be forwarded to client application
+         */
+       onProcessKeyEvent : function(code, mask, layout) {
+               var processed = false;
+               if (typeof this.handler.onProcessKeyEvent === 'function') {
+                       processed = this.handler.onProcessKeyEvent(code, mask, layout);
+               }
+               this.impl.replyProcessKeyEvent(processed);
+       },
+
+       /* Keycode enumeration values used when invoking sendKeyEvent() or forwardKeyEvent() functions */
+       Keycode : {
+               BACKSPACE:0xff08,
+               TAB:0xff09,
+               RETURN:0xff0d,
+               ESCAPE:0xff1b,
+               DELETE:0xffff,
+               HOME:0xff50,
+               LEFT:0xff51,
+               UP:0XFf52,
+               RIGHT:0xff53,
+               DOWN:0xff54,
+               PRIOR:0xff55,
+               PAGE_UP:0xff55,
+               NEXT:0xff56,
+               PAGE_DOWN:0xff56,
+               END:0Xff57,
+               INSERT:0xff63,
+               KP_SPACE:0xff80,
+               KP_TAB:0xff89,
+               KP_ENTER:0xff8d,
+               KP_F1:0xff91,
+               KP_F2:0xff92,
+               KP_F3:0xff93,
+               KP_F4:0xff94,
+               KP_HOME:0xff95,
+               KP_LEFT:0xff96,
+               KP_UP:0xff97,
+               KP_RIGHT:0xff98,
+               KP_DOWN:0xff99,
+               KP_PRIOR:0xff9a,
+               KP_PAGE_UP:0xff9a,
+               KP_NEXT:0xff9b,
+               KP_PAGE_DOWN:0xff9b,
+               KP_END:0xff9c,
+               KP_BEGIN:0xff9d,
+               KP_INSERT:0xff9e,
+               KP_DELETE:0xff9f,
+               KP_EQUAL:0xffbd,
+               KP_MULTIPLY:0xffaa,
+               KP_ADD:0xffab,
+               KP_SEPARATOR:0xffac,
+               KP_SUBTRACT:0xffad,
+               KP_DECIMAL:0xffae,
+               KP_DIVIDE:0xffaf,
+               KP_0:0xffb0,
+               KP_1:0xffb1,
+               KP_2:0xffb2,
+               KP_3:0xffb3,
+               KP_4:0xffb4,
+               KP_5:0xffb5,
+               KP_6:0xffb6,
+               KP_7:0xffb7,
+               KP_8:0xffb8,
+               KP_9:0xffb9,
+               F1:0xffbe,
+               F2:0xffbf,
+               F3:0xffc0,
+               F4:0xffc1,
+               F5:0xffc2,
+               F6:0xffc3,
+               F7:0xffc4,
+               F8:0xffc5,
+               F9:0xffc6,
+               F10:0xffc7,
+               F11:0xffc8,
+               F12:0xffc9,
+               SHIFT_L:0xffe1,
+               SHIFT_R:0xffe2,
+               CONTROL_L:0xffe3,
+               CONTROL_R:0xffe4,
+               CAPS_LOCK:0xffe5,
+               SHIFT_LOCK:0xffe6,
+               META_L:0xffe7,
+               META_R:0xffe8,
+               ALT_L:0xffe9,
+               ALT_R:0xffea,
+               SUPER_L:0xffeb,
+               SUPER_R:0xffec,
+               HYPER_L:0xffed,
+               HYPER_R:0xffee,
+               SPACE:0x020,
+               EXCLAM:0x021,
+               QUOTEDBL:0x022,
+               NUMBERSIGN:0x023,
+               DOLLAR:0x024,
+               PERCENT:0x025,
+               AMPERSAND:0x026,
+               APOSTROPHE:0x027,
+               QUOTERIGHT:0x027,
+               PARENLEFT:0x028,
+               PARENRIGHT:0x029,
+               ASTERISK:0x02a,
+               PLUS:0x02b,
+               COMMA:0x02c,
+               MINUS:0x02d,
+               PERIOD:0x02e,
+               SLASH:0x02f,
+               0:0X030,
+               1:0X031,
+               2:0X032,
+               3:0X033,
+               4:0X034,
+               5:0X035,
+               6:0X036,
+               7:0X037,
+               8:0X038,
+               9:0X039,
+               COLON:0x03a,
+               SEMICOLON:0x03b,
+               LESS:0x03c,
+               EQUAL:0x03d,
+               GREATER:0x03e,
+               QUESTION:0x03f,
+               AT:0x040,
+               A:0X041,
+               B:0X042,
+               C:0X043,
+               D:0X044,
+               E:0X045,
+               F:0X046,
+               G:0X047,
+               H:0X048,
+               I:0x049,
+               J:0x04a,
+               K:0x04b,
+               L:0x04c,
+               M:0x04d,
+               N:0x04e,
+               O:0x04f,
+               P:0x050,
+               Q:0x051,
+               R:0x052,
+               S:0x053,
+               T:0x054,
+               U:0x055,
+               V:0x056,
+               W:0x057,
+               X:0x058,
+               Y:0x059,
+               Z:0x05a,
+               BRACKETLEFT:0x05b,
+               BACKSLASH:0x05c,
+               BRACKETRIGHT:0x05d,
+               ASCIICIRCUM:0x05e,
+               UNDERSCORE:0x05f,
+               GRAVE:0x060,
+               QUOTELEFT:0x060,
+               a:0x061,
+               b:0x062,
+               c:0x063,
+               d:0x064,
+               e:0x065,
+               f:0x066,
+               g:0x067,
+               h:0x068,
+               i:0x069,
+               j:0x06a,
+               k:0x06b,
+               l:0x06c,
+               m:0x06d,
+               n:0x06e,
+               o:0x06f,
+               p:0x070,
+               q:0x071,
+               r:0x072,
+               s:0x073,
+               t:0x074,
+               u:0x075,
+               v:0x076,
+               w:0x077,
+               x:0x078,
+               y:0x079,
+               z:0x07a,
+               BRACELEFT:0x07b,
+               BAR:0x07c,
+               BRACERIGHT:0x07d,
+               ASCIITILDE:0x07e
+       },
+
+       /* The code below is only for internal implementation and not for keyboard developers */
+       impl : null,
+       handler : null,
+       WebHelperClientInternal: function (client) {
+               this.CLIENT_VERSION = "1.11";
+
+               this.MessageTypes = {
+                       PLAIN:"plain",
+                       QUERY:"query",
+                       REPLY:"reply"
+               };
+
+               this.MessageCommands = {
+                       INIT:"init",
+                       EXIT:"exit",
+
+                       FOCUS_IN:"focus_in",
+                       FOCUS_OUT:"focus_out",
+                       SHOW:"show",
+                       HIDE:"hide",
+                       SET_ROTATION:"set_rotation",
+                       UPDATE_CURSOR_POSITION:"update_cursor_position",
+                       UPDATE_SURROUNDING_TEXT:"update_surrounding_text",
+                       UPDATE_SELECTION:"update_selection",
+                       SET_LANGUAGE:"set_language",
+                       SET_IMDATA:"set_imdata",
+                       GET_IMDATA:"get_imdata",
+                       SET_RETURN_KEY_TYPE:"set_return_key_type",
+                       GET_RETURN_KEY_TYPE:"get_return_key_type",
+                       SET_RETURN_KEY_DISABLE:"set_return_key_disable",
+                       GET_RETURN_KEY_DISABLE:"get_return_key_disable",
+                       SET_LAYOUT:"set_layout",
+                       GET_LAYOUT:"get_layout",
+                       RESET_INPUT_CONTEXT:"reset_input_context",
+                       PROCESS_KEY_EVENT:"process_key_event",
+
+                       LOG:"log",
+                       COMMIT_STRING:"commit_string",
+                       UPDATE_PREEDIT_STRING:"update_preedit_string",
+                       SEND_KEY_EVENT:"send_key_event",
+                       FORWARD_KEY_EVENT:"forward_key_event",
+                       SET_KEYBOARD_SIZES:"set_keyboard_sizes",
+                       SET_SELECTION:"set_selection",
+                       GET_SELECTION:"get_selection",
+                       GET_SURROUNDING_TEXT:"get_surrounding_text",
+                       DELETE_SURROUNDING_TEXT:"delete_surrounding_text",
+                       LOGIN:"login"
+               };
+
+               this.log = function(str) {
+                       if (this.socket != null && this.socket !== "undefined") {
+                               this.socket.send(
+                                       this.MessageTypes.PLAIN + " " +
+                                       this.MessageCommands.LOG + " " +
+                                       str);
+                       }
+               };
+               this.commitString = function(str) {
+                       if (this.socket != null && this.socket !== "undefined") {
+                               this.socket.send(
+                                       this.MessageTypes.PLAIN + " " +
+                                       this.MessageCommands.COMMIT_STRING + " " +
+                                       str);
+                       }
+               };
+               this.updatePreeditString = function(str) {
+                       if (this.socket != null && this.socket !== "undefined") {
+                               this.socket.send(
+                                       this.MessageTypes.PLAIN + " " +
+                                       this.MessageCommands.UPDATE_PREEDIT_STRING + " " +
+                                       str);
+                       }
+               };
+               this.sendKeyEvent = function(code) {
+                       if (this.socket != null && this.socket !== "undefined") {
+                               this.socket.send(
+                                       this.MessageTypes.PLAIN + " " +
+                                       this.MessageCommands.SEND_KEY_EVENT + " " +
+                                       code);
+                       }
+               };
+               this.forwardKeyEvent = function(code) {
+                       if (this.socket != null && this.socket !== "undefined") {
+                               this.socket.send(
+                                       this.MessageTypes.PLAIN + " " +
+                                       this.MessageCommands.FORWARD_KEY_EVENT + " " +
+                                       code);
+                       }
+               };
+               this.setKeyboardSizes = function(portraitWidth, portraitHeight, landscapeWidth, landscapeHeight) {
+                       if (this.socket != null && this.socket !== "undefined") {
+                               this.socket.send(
+                                       this.MessageTypes.PLAIN + " " +
+                                       this.MessageCommands.SET_KEYBOARD_SIZES + " " +
+                                       portraitWidth + " " + portraitHeight + " " +
+                                       landscapeWidth + " " + landscapeHeight);
+                       }
+               };
+               this.setSelection = function(startIndex, endIndex) {
+                       if (this.socket != null && this.socket !== "undefined") {
+                               this.socket.send(
+                                       this.MessageTypes.PLAIN + " " +
+                                       this.MessageCommands.SET_SELECTION + " " +
+                                       startIndex + " " + endIndex);
+                       }
+               };
+               this.getSelection = function() {
+                       if (this.socket != null && this.socket !== "undefined") {
+                               this.socket.send(
+                                       this.MessageTypes.PLAIN + " " +
+                                       this.MessageCommands.GET_SELECTION + " ");
+                       }
+               };
+               this.getSurroundingText = function(maxLenBefore, maxLenAfter) {
+                       if (this.socket != null && this.socket !== "undefined") {
+                               this.socket.send(
+                                       this.MessageTypes.PLAIN + " " +
+                                       this.MessageCommands.GET_SURROUNDING_TEXT + " " +
+                                       maxLenBefore + " " + maxLenAfter);
+                       }
+               };
+               this.deleteSurroundingText = function(offset, len) {
+                       if (this.socket != null && this.socket !== "undefined") {
+                               this.socket.send(
+                                       this.MessageTypes.PLAIN + " " +
+                                       this.MessageCommands.DELETE_SURROUNDING_TEXT + " " +
+                                       offset + " " + len);
+                       }
+               };
+               this.replyGetImdata = function(data) {
+                       if (this.socket != null && this.socket !== "undefined") {
+                               this.socket.send(
+                                       this.MessageTypes.REPLY + " " +
+                                       this.MessageCommands.GET_IMDATA + " " +
+                                       data);
+                       }
+               };
+               this.replyProcessKeyEvent = function(ret) {
+                       if (this.socket != null && this.socket !== "undefined") {
+                               this.socket.send(
+                                       this.MessageTypes.REPLY + " " +
+                                       this.MessageCommands.PROCESS_KEY_EVENT + " " +
+                                       ret);
+                       }
+               };
+               this.defaultHandler = function (data) {
+                       var items = data.split(" ");
+                       if (items[1] === this.MessageCommands.INIT) {
+                               client.onInit();
+                       }
+                       if (items[1] === this.MessageCommands.EXIT) {
+                               client.onExit();
+                       }
+                       if (items[1] === this.MessageCommands.FOCUS_IN) {
+                               client.onFocusIn(parseInt(items[2], 10));
+                       }
+                       if (items[1] === this.MessageCommands.FOCUS_OUT) {
+                               client.onFocusOut(parseInt(items[2], 10));
+                       }
+
+                       if (items[1] === this.MessageCommands.SHOW) {
+                               client.onShow(parseInt(items[2], 10));
+                       }
+                       if (items[1] === this.MessageCommands.HIDE) {
+                               client.onHide(parseInt(items[2], 10));
+                       }
+
+                       if (items[1] === this.MessageCommands.SET_ROTATION) {
+                               client.onSetRotation(parseInt(items[2], 10));
+                       }
+
+                       if (items[1] === this.MessageCommands.UPDATE_CURSOR_POSITION) {
+                               client.onUpdateCursorPosition(parseInt(items[2], 10), parseInt(items[3], 10));
+                       }
+
+                       if (items[1] === this.MessageCommands.UPDATE_SURROUNDING_TEXT) {
+                               var text_array = items.slice(3);
+                               client.onUpdateSurroundingText(parseInt(items[2], 10), text_array.join(' '));
+                       }
+
+                       if (items[1] === this.MessageCommands.UPDATE_SELECTION) {
+                               client.onUpdateSelection(items[2]);
+                       }
+
+                       if (items[1] === this.MessageCommands.SET_LANGUAGE) {
+                               client.onSetLanguage(items[2]);
+                       }
+
+                       if (items[1] === this.MessageCommands.SET_IMDATA) {
+                               client.onSetImdata(items[2], items[3]);
+                       }
+                       if (items[1] === this.MessageCommands.GET_IMDATA) {
+                               client.onGetImdata();
+                       }
+
+                       if (items[1] === this.MessageCommands.SET_RETURN_KEY_TYPE) {
+                               client.onSetReturnKeyType(items[2]);
+                       }
+                       if (items[1] === this.MessageCommands.GET_RETURN_KEY_TYPE) {
+                               client.onGetReturnKeyType();
+                       }
+
+                       if (items[1] === this.MessageCommands.SET_RETURN_KEY_DISABLE) {
+                               client.onSetReturnKeyDisable(items[2]);
+                       }
+                       if (items[1] === this.MessageCommands.GET_RETURN_KEY_DISABLE) {
+                               client.onGetReturnKeyDisable();
+                       }
+
+                       if (items[1] === this.MessageCommands.SET_LAYOUT) {
+                               client.onSetLayout(items[2]);
+                       }
+                       if (items[1] === this.MessageCommands.GET_LAYOUT) {
+                               client.onGetLayout();
+                       }
+
+                       if (items[1] === this.MessageCommands.RESET_INPUT_CONTEXT) {
+                               client.onResetInputContext(parseInt(items[2], 10));
+                       }
+
+                       if (items[1] === this.MessageCommands.PROCESS_KEY_EVENT) {
+                               client.onProcessKeyEvent(parseInt(items[2], 10), parseInt(items[3], 10), parseInt(items[4], 10));
+                       }
+               };
+
+               this.getAppropriateWsUrl = function() {
+                       return "ws://localhost:7681";
+               };
+
+               this.connectWebSocket = function() {
+                       if (typeof MozWebSocket != "undefined") {
+                               this.socket =
+                                       new MozWebSocket(this.getAppropriateWsUrl(), "keyboard-protocol");
+                       } else {
+                               this.socket =
+                                       new WebSocket(this.getAppropriateWsUrl(), "keyboard-protocol");
+                       }
+               };
+
+               this.prepare = function(key) {
+                       this.magicKey = key;
+                       return this.CLIENT_VERSION;
+               };
+               this.activate = function() {
+                       this.connectWebSocket();
+                       this.registerHandlers(this);
+               };
+
+               this.registerHandlers = function(handler) {
+                       try {
+                               this.socket.onopen = function() {
+                                       this.send(
+                                       handler.MessageTypes.PLAIN + " " +
+                                       handler.MessageCommands.LOGIN + " " +
+                                       handler.magicKey);
+                               };
+
+                               this.socket.onmessage = function(msg) {
+                                       handler.defaultHandler(msg.data);
+                               };
+
+                               this.socket.onclose = function(evt) {
+                                       /* Try to reconnect if disconnected uncleanly */
+                                       if (evt.wasClean === false) {
+                                               /*
+                                               setTimeout((function(handler) {
+                                                       alert("connecting again!");
+                                                       this.connectWebSocket();
+                                                       this.registerHandlers(this);
+                                               }).call(handler), 500);
+                                               */
+                                       }
+                               };
+                       } catch(exception) {
+                               alert(exception);
+                       }
+               };
+       }
+};
diff --git a/ise-web-helper-agent.efl b/ise-web-helper-agent.efl
new file mode 100644 (file)
index 0000000..3c08e8d
--- /dev/null
@@ -0,0 +1,2 @@
+isf webkit2-efl r-x--- ------
+isf system::use_internet rw---- ------
diff --git a/ise-web-helper-agent.manifest b/ise-web-helper-agent.manifest
new file mode 100755 (executable)
index 0000000..017d22d
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+ <request>
+    <domain name="_"/>
+ </request>
+</manifest>
diff --git a/ise-web-helper-agent.xml b/ise-web-helper-agent.xml
new file mode 100644 (file)
index 0000000..07edcc2
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<manifest xmlns="http://tizen.org/ns/packages" package="PRIVTISE02" type="rpm" version="1.0.4" install-location="internal-only">
+<label>Web keyboard container</label>
+<author/>
+<description/>
+<label>Web keyboard container</label>
+<icon/>
+<ui-application appid="PRIVTISE02.ise-web-helper-agent" exec="/usr/lib/scim-1.0/scim-helper-launcher" nodisplay="true" taskmanage="false" multiple="false" type="capp" hw-acceleration="use-system-setting" mainapp="true">
+        <category name="http://tizen.org/category/ime"/>
+        <label>Web keyboard container</label>
+        <label xml:lang="en-us">Web keyboard container</label>
+        <icon/>
+</ui-application>
+<ime appid="PRIVTISE02.ise-web-helper-agent">
+        <uuid>1373647e-5d53-4019-b810-ed068e44873c</uuid>
+        <label>Web keyboard container</label>
+        <label xml:lang="en-us">Web keyboard container</label>
+        <languages>
+                <language>en-us</language>
+        </languages>
+        <type>SOFTWARE_KEYBOARD_ISE</type>
+        <options>
+                <option>STAND_ALONE</option>
+                <option>NEED_SCREEN_INFO</option>
+                <option>AUTO_RESTART</option>
+        </options>
+</ime>
+</manifest>
diff --git a/packaging/ise-web-helper-agent.changes b/packaging/ise-web-helper-agent.changes
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/packaging/ise-web-helper-agent.spec b/packaging/ise-web-helper-agent.spec
new file mode 100644 (file)
index 0000000..8e72260
--- /dev/null
@@ -0,0 +1,69 @@
+Name:       ise-web-helper-agent
+Summary:    Tizen web keyboard container
+Version:    0.0.1
+Release:    1
+Group:      Graphics & UI Framework/Input
+License:    Apache-2.0
+Source0:    ise-web-helper-agent-%{version}.tar.gz
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+BuildRequires:  gettext-tools
+BuildRequires:  cmake
+BuildRequires:  pkgconfig(elementary)
+BuildRequires:  pkgconfig(isf)
+BuildRequires:  pkgconfig(vconf)
+BuildRequires:  pkgconfig(dlog)
+BuildRequires:  pkgconfig(ecore-imf)
+BuildRequires:  pkgconfig(ewebkit2)
+BuildRequires:  pkgconfig(libwebsockets)
+BuildRequires:  pkgconfig(pkgmgr-info)
+BuildRequires:  pkgconfig(wrt-core)
+BuildRequires:  pkgconfig(dpl-efl)
+BuildRequires:  capi-appfw-package-manager-devel
+
+
+%description
+Description: Web keyboard container
+
+
+%prep
+%setup -q
+
+%build
+export CFLAGS+=" -DTIZEN_ENGINEER_MODE"
+export CXXFLAGS+=" -DTIZEN_ENGINEER_MODE"
+export FFLAGS+=" -DTIZEN_ENGINEER_MODE"
+
+%if "%{?tizen_profile_name}" == "mobile"
+CFLAGS+=" -D_MOBILE";
+CXXFLAGS+=" -D_MOBILE";
+%elseif "%{?tizen_profile_name}" == "wearable"
+CFLAGS+=" -D_WEARABLE";
+CXXFLAGS+=" -D_WEARABLE";
+%endif
+
+rm -rf CMakeFiles
+rm -rf CMakeCache.txt
+cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix}
+
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+mkdir -p %{buildroot}/usr/share/license
+cp LICENSE %{buildroot}/usr/share/license/%{name}
+
+%make_install
+
+%post
+
+%postun
+
+%files
+%manifest %{name}.manifest
+%defattr(-,root,root,-)
+%{_libdir}/scim-1.0/1.4.0/Helper/ise-web-helper-agent.so
+%{_libdir}/scim-1.0/web-container.so
+%{_datadir}/packages/*
+/usr/share/license/%{name}
+/etc/smack/accesses.d/%{name}.efl
diff --git a/src/common.cpp b/src/common.cpp
new file mode 100644 (file)
index 0000000..18c0adc
--- /dev/null
@@ -0,0 +1,1179 @@
+/*
+ * Copyright (c) 2012 - 2014 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 <stdio.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <Ecore_X.h>
+#include <Elementary.h>
+
+#include <dlog.h>
+
+#include <vconf.h>
+#include <vconf-keys.h>
+
+#include "common.h"
+#include "ise.h"
+#include "packages.h"
+
+#define IMDATA_STRING_MAX_LEN 256
+
+
+CISECommon* CISECommon::m_instance = NULL; /* For singleton */
+
+extern KEYBOARD_STATE g_keyboard_state;
+
+/* Internal signal handler function */
+void signal_handler(int sig);
+
+/* Internal input handler function */
+Eina_Bool input_handler(void *data, Ecore_Fd_Handler *fd_handler);
+
+static int get_app_window_degree(Evas_Object *keypad_win)
+{
+    int  ret = 0;
+    Atom type_return;
+    int  format_return;
+    unsigned long    nitems_return;
+    unsigned long    bytes_after_return;
+    unsigned char   *data_window = NULL;
+    unsigned char   *data_angle = NULL;
+
+    int retVal = 0;
+    Ecore_X_Window app_window = 0;
+
+    LOGD("Trying to get app window degree for %p\n", keypad_win);
+    Ecore_X_Window win = elm_win_xwindow_get(static_cast<Evas_Object*>(keypad_win));
+    ret = XGetWindowProperty((Display *)ecore_x_display_get(),
+        ecore_x_window_root_get(win),
+        ecore_x_atom_get("_ISF_ACTIVE_WINDOW"),
+        0, G_MAXLONG, False, XA_WINDOW, &type_return,
+        &format_return, &nitems_return, &bytes_after_return,
+        &data_window);
+
+    if (ret == Success) {
+        if ((type_return == XA_WINDOW) && (format_return == 32) && (data_window)) {
+            app_window = *(Window *)data_window;
+
+            ret = XGetWindowProperty((Display *)ecore_x_display_get(), app_window,
+                ecore_x_atom_get("_E_ILLUME_ROTATE_WINDOW_ANGLE"),
+                0, G_MAXLONG, False, XA_CARDINAL, &type_return,
+                &format_return, &nitems_return, &bytes_after_return,
+                &data_angle);
+
+            LOGD("app_window : %p, ret %d, %d, %p\n", app_window, ret, type_return, data_angle);
+            if (ret == Success) {
+                if (data_angle) {
+                    if (type_return == XA_CARDINAL) {
+                        retVal = *(unsigned int*)data_angle;
+                        LOGD("current rotation angle is %p %d\n", app_window, retVal);
+                    }
+                    XFree(data_angle);
+                }
+            }
+        }
+        if (data_window)
+            XFree(data_window);
+    }
+
+
+    return retVal;
+}
+
+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;
+}
+
+void language_changed_cb(keynode_t *key, void* data)
+{
+    char clang[_POSIX_PATH_MAX] = {0};
+    char *vconf_str = vconf_get_str(VCONFKEY_LANGSET);
+    if (vconf_str) {
+        snprintf(clang, sizeof(clang), "%s",vconf_str);
+        free(vconf_str);
+    }
+    LOGD("current language is %s\n",clang);
+
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->set_display_language(clang);
+        }
+    }
+}
+
+void accessibility_changed_cb(keynode_t *key, void* data)
+{
+    int vconf_value = 0;
+    if (vconf_get_bool(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, &vconf_value) == 0) {
+        LOGD("accessibility state : %d\n", vconf_value);
+
+        CISECommon *impl = CISECommon::get_instance();
+        if (impl) {
+            IISECommonEventCallback *callback = impl->get_core_event_callback();
+            if (callback) {
+                callback->set_accessibility_state(vconf_value);
+            }
+        }
+    }
+}
+
+static Eina_Bool _client_message_cb(void *data, int type, void *event)
+{
+    Ecore_X_Event_Client_Message *ev = (Ecore_X_Event_Client_Message *)event;
+
+    IISECommonEventCallback *callback = NULL;
+    CISECommon *common = CISECommon::get_instance();
+    Evas_Object *main_window = NULL;
+    if (common) {
+        callback = common->get_core_event_callback();
+        main_window = common->get_main_window();
+    }
+
+#ifndef APPLY_WINDOW_MANAGER_CHANGE
+#else
+    if (ev->message_type == ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE) {
+        LOGD("ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE , %d %d\n", ev->data.l[0], gFHiddenState);
+        angle = ev->data.l[0];
+        ise_set_screen_direction(angle);
+        if (!gFHiddenState) {
+            ise_show(gLastIC);
+        }
+    } else if (ev->message_type == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE) {
+        LOGD("ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE , %d\n", ev->data.l[0]);
+        elm_win_keyboard_mode_set(main_window, (Elm_Win_Keyboard_Mode)(ev->data.l[0]));
+        gFHiddenState = !(ev->data.l[0]);
+    }
+#endif
+
+    if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST) {
+        if (ev->win == elm_win_xwindow_get(main_window)) {
+            int angle = ev->data.l[1];
+            LOGD("_ECORE_X_ATOM_E_WINDOW_ROTATION_REQUEST, %d\n", angle);
+            if (callback) {
+                callback->set_rotation_degree(angle);
+            }
+            Ecore_X_Window control_window = 0;
+            Ecore_X_Atom atom = ecore_x_atom_get("_ISF_CONTROL_WINDOW");
+            Ecore_X_Window root = ecore_x_window_root_first_get();
+            if (ecore_x_window_prop_xid_get(root, atom, ECORE_X_ATOM_WINDOW, &control_window, 1) == 1) {
+                ecore_x_client_message32_send(control_window, ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST,
+                    ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
+                    ev->data.l[0], ev->data.l[1], ev->data.l[2], ev->data.l[3], ev->data.l[4]);
+            }
+        }
+    }
+
+    return ECORE_CALLBACK_RENEW;
+}
+
+CISECommon::CISECommon()
+{
+    m_main_window = NULL;
+    m_event_callback = NULL;
+}
+
+CISECommon::~CISECommon()
+{
+}
+
+CISECommon*
+CISECommon::get_instance()
+{
+    static CISECommon instance;
+    return &instance;
+}
+
+
+void CISECommon::init()
+{
+    /*
+    package_list_query();
+    {
+        HelperInfoEx helper_info_ex;
+
+        helper_info_ex.helper_info.uuid = scim::String(ISEUUID);
+        helper_info_ex.helper_info.name = scim::String(ISENAME);
+        helper_info_ex.helper_info.option = scim::SCIM_HELPER_STAND_ALONE | scim::SCIM_HELPER_NEED_SCREEN_INFO |
+            scim::SCIM_HELPER_NEED_SPOT_LOCATION_INFO | scim::SCIM_HELPER_AUTO_RESTART;
+        helper_info_ex.supported_languages = scim::String("en_US");
+
+        m_helper_infos.push_back(helper_info_ex);
+    }
+    */
+    CPackages *packages = CPackages::get_instance();
+    if (packages) {
+        packages->init();
+    }
+}
+
+void CISECommon::exit()
+{
+}
+
+void CISECommon::run(const char *uuid, const scim::ConfigPointer &config, const char *display)
+{
+    char *argv[4];
+    int argc = 3;
+
+    /*
+    scim::HelperInfo helper_info;
+    for (int loop = 0;loop < m_helper_infos.size();loop++) {
+        if (m_helper_infos.at(loop).helper_info.uuid.compare(uuid) == 0) {
+            helper_info = m_helper_infos.at(loop).helper_info;
+        }
+    }
+    */
+    m_uuid_ise = uuid;
+    HelperInfoEx info;
+    CPackages *packages = CPackages::get_instance();
+    if (packages) {
+        info = packages->get_package_information_by_uuid(m_uuid_ise);
+    }
+
+    argv [0] = const_cast<char *>(info.helper_info.name.c_str());
+    argv [1] = (char *)"--display";
+    argv [2] = const_cast<char *>(display);
+    argv [3] = 0;
+
+    elm_init(argc, argv);
+
+    elm_policy_set (ELM_POLICY_THROTTLE, ELM_POLICY_THROTTLE_NEVER);
+
+    m_main_window = elm_win_add(NULL, "Tizen Keyboard", ELM_WIN_UTILITY);
+    elm_win_borderless_set(m_main_window, EINA_TRUE);
+    elm_win_keyboard_win_set(m_main_window, EINA_TRUE);
+    elm_win_autodel_set(m_main_window, EINA_TRUE);
+    elm_win_title_set(m_main_window, "Tizen Keyboard");
+
+    unsigned int set = 1;
+    ecore_x_window_prop_card32_set(elm_win_xwindow_get(m_main_window),
+        ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED,
+        &set, 1);
+
+    int rots[] = {0, 90, 180, 270};
+    elm_win_wm_rotation_available_rotations_set(m_main_window, rots, 4);
+
+#ifdef FULL_SCREEN_TEST
+    elm_win_fullscreen_set(m_main_window, EINA_TRUE);
+#endif
+
+    if (m_event_callback) {
+        m_event_callback->init();
+    }
+
+    vconf_notify_key_changed(VCONFKEY_LANGSET, language_changed_cb, NULL);
+    vconf_notify_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, accessibility_changed_cb, NULL);
+
+    /* Should we call these callback functions here? */
+    language_changed_cb(NULL, NULL);
+    accessibility_changed_cb(NULL, NULL);
+
+    register_slot_functions();
+
+    m_helper_agent.open_connection(info.helper_info, display);
+    int fd = m_helper_agent.get_connection_number();
+
+    if (!m_uuid_keyboard_ise.empty()) {
+        m_helper_agent.set_keyboard_ise_by_uuid(m_uuid_keyboard_ise);
+    }
+
+    Ecore_Fd_Handler *fd_handler = NULL;
+
+    if (fd >= 0) {
+        Ecore_X_Window xwindow = elm_win_xwindow_get(m_main_window);
+        char xid[255];
+        snprintf(xid, 255, "%d", xwindow);
+        scim::Property prop(xid, "XID", "", "");
+        scim::PropertyList props;
+        props.push_back(prop);
+        m_helper_agent.register_properties(props);
+
+        fd_handler = ecore_main_fd_handler_add(fd, ECORE_FD_READ, input_handler, NULL, NULL, NULL);
+    }
+
+    Ecore_Event_Handler *XClientMsgHandler = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, _client_message_cb, m_main_window);
+
+    signal(SIGQUIT, signal_handler);
+    signal(SIGTERM, signal_handler);
+    signal(SIGINT,  signal_handler);
+    signal(SIGHUP,  signal_handler);
+
+    elm_run();
+
+    vconf_ignore_key_changed(VCONFKEY_LANGSET, language_changed_cb);
+    vconf_ignore_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, accessibility_changed_cb);
+
+    if (XClientMsgHandler) {
+        ecore_event_handler_del(XClientMsgHandler);
+        XClientMsgHandler = NULL;
+    }
+
+    if (fd_handler) {
+        ecore_main_fd_handler_del(fd_handler);
+        fd_handler = NULL;
+    }
+
+    /* Would the below code needed? */
+    /*
+    if (m_event_callback) {
+        m_event_callback->exit();
+    }
+    */
+
+    elm_shutdown();
+
+}
+
+scim::HelperAgent* CISECommon::get_helper_agent()
+{
+    return &m_helper_agent;
+}
+
+int CISECommon::get_number_of_helpers(void)
+{
+    int ret = 0;
+    CPackages *packages = CPackages::get_instance();
+    if (packages) {
+        ret = packages->get_number_of_packages();
+    }
+    return ret;
+}
+
+bool CISECommon::get_helper_info(int idx, scim::HelperInfo &info)
+{
+    bool ret = false;
+    CPackages *packages = CPackages::get_instance();
+    if (packages) {
+        if (idx >= 0 && idx < packages->get_number_of_packages()) {
+            info = packages->get_package_information_by_index(idx).helper_info;
+            ret = true;
+        }
+    }
+
+    return ret;
+}
+
+scim::String CISECommon::get_helper_language(int idx)
+{
+    std::vector<scim::String> langlist;
+    CPackages *packages = CPackages::get_instance();
+    if (packages) {
+        if (idx >= 0 && idx < packages->get_number_of_packages()) {
+            langlist.push_back(packages->get_package_information_by_index(idx).supported_languages);
+        }
+    }
+    return scim::scim_combine_string_list(langlist);
+}
+
+void CISECommon::set_core_event_callback(IISECommonEventCallback *callback)
+{
+    m_event_callback = callback;
+}
+
+Evas_Object* CISECommon::get_main_window()
+{
+    return m_main_window;
+}
+
+void CISECommon::set_keyboard_size_hints(int portrait_width, int portrait_height, int landscape_width, int landscape_height)
+{
+    /* Temporary code, this should be automatically calculated when changing input mode */
+    Ecore_X_Window xwin = elm_win_xwindow_get(m_main_window);
+    ecore_x_e_window_rotation_geometry_set(xwin,
+        0, 0, 0, portrait_width, portrait_height);
+    ecore_x_e_window_rotation_geometry_set(xwin,
+        90, 0, 0, landscape_height, landscape_width);
+    ecore_x_e_window_rotation_geometry_set(xwin,
+        180, 0, 0, portrait_width, portrait_height);
+    ecore_x_e_window_rotation_geometry_set(xwin,
+        270, 0, 0, landscape_height, landscape_width);
+}
+
+scim::String CISECommon::get_keyboard_ise_uuid()
+{
+    return m_uuid_keyboard_ise;
+}
+
+IISECommonEventCallback* CISECommon::get_core_event_callback()
+{
+    return m_event_callback;
+}
+
+void CISECommon::reload_config()
+{
+    m_helper_agent.reload_config();
+}
+
+void CISECommon::send_imengine_event(int ic, const char *ic_uuid, const int command, const int value)
+{
+    scim::String uuid;
+    if (ic_uuid) {
+        uuid = scim::String(ic_uuid);
+    }
+    scim::Transaction trans;
+    trans.put_command(command);
+    trans.put_data(value);
+    m_helper_agent.send_imengine_event(ic, uuid, trans);
+}
+
+void CISECommon::reset_keyboard_ise() {
+    m_helper_agent.reset_keyboard_ise();
+}
+
+void CISECommon::send_key_event(int ic, const char *ic_uuid, int keycode, int keymask)
+{
+    scim::String uuid;
+    if (ic_uuid) {
+        uuid = scim::String(ic_uuid);
+    }
+    scim::KeyEvent event;
+    event.code = keycode;
+    event.mask = keymask;
+    m_helper_agent.send_key_event(ic, uuid, event);
+}
+
+void CISECommon::forward_key_event(int ic, const char *ic_uuid, int keycode, int keymask)
+{
+    scim::String uuid;
+    if (ic_uuid) {
+        uuid = scim::String(ic_uuid);
+    }
+    scim::KeyEvent event;
+    event.code = keycode;
+    event.mask = keymask;
+    m_helper_agent.forward_key_event(ic, uuid, event);
+}
+
+void CISECommon::commit_string(int ic, const char *ic_uuid, const char *str)
+{
+    scim::String uuid;
+    if (ic_uuid) {
+        uuid = scim::String(ic_uuid);
+    }
+    m_helper_agent.commit_string(ic, uuid, scim::utf8_mbstowcs(str));
+}
+
+void CISECommon::show_preedit_string(int ic, const char *ic_uuid)
+{
+    scim::String uuid;
+    if (ic_uuid) {
+        uuid = scim::String(ic_uuid);
+    }
+    m_helper_agent.show_preedit_string(ic, uuid);
+}
+
+void CISECommon::show_aux_string(void)
+{
+    m_helper_agent.show_aux_string();
+}
+
+void CISECommon::show_candidate_string(void)
+{
+    m_helper_agent.show_candidate_string();
+}
+
+void CISECommon::show_associate_string(void)
+{
+    m_helper_agent.show_associate_string();
+}
+
+void CISECommon::hide_preedit_string(int ic, const char *ic_uuid)
+{
+    scim::String uuid;
+    if (ic_uuid) {
+        uuid = scim::String(ic_uuid);
+    }
+    m_helper_agent.hide_preedit_string(ic, uuid);
+}
+
+void CISECommon::hide_aux_string(void)
+{
+    m_helper_agent.hide_aux_string();
+}
+
+void CISECommon::hide_candidate_string(void)
+{
+    m_helper_agent.hide_candidate_string();
+}
+
+void CISECommon::hide_associate_string(void)
+{
+    m_helper_agent.hide_associate_string();
+}
+
+void CISECommon::update_preedit_string(int ic, const char *ic_uuid, const char *str)
+{
+    scim::AttributeList list;
+    scim::String uuid;
+    if (ic_uuid) {
+        uuid = scim::String(ic_uuid);
+    }
+    m_helper_agent.update_preedit_string(ic, uuid, scim::utf8_mbstowcs(str), list);
+
+    if (str && strlen(str) > 0) {
+        show_preedit_string(ic, ic_uuid);
+    } else {
+        hide_preedit_string(ic, ic_uuid);
+    }
+}
+
+void CISECommon::update_aux_string(const char *str)
+{
+    scim::AttributeList list;
+    m_helper_agent.update_aux_string(scim::String(str), list);
+}
+
+void CISECommon::update_input_context(int type, int value)
+{
+    m_helper_agent.update_input_context(type, value);
+}
+
+void CISECommon::get_surrounding_text(int maxlen_before, int maxlen_after)
+{
+    m_helper_agent.get_surrounding_text("", maxlen_before, maxlen_after);
+}
+
+void CISECommon::delete_surrounding_text(int offset, int len)
+{
+    m_helper_agent.delete_surrounding_text(offset, len);
+}
+
+void CISECommon::set_selection(int start_index, int end_index)
+{
+    m_helper_agent.set_selection(start_index, end_index);
+}
+
+void CISECommon::get_selection()
+{
+    m_helper_agent.get_selection("");
+}
+
+void CISECommon::set_candidate_position(int left, int top)
+{
+    m_helper_agent.set_candidate_position(left, top);
+}
+
+void CISECommon::candidate_hide(void)
+{
+    m_helper_agent.candidate_hide();
+}
+
+void CISECommon::set_keyboard_ise_by_uuid(const char *uuid)
+{
+    if (uuid) {
+        m_uuid_keyboard_ise = scim::String(uuid);
+        if (g_keyboard_state.ic == g_keyboard_state.focused_ic) {
+            LOGD("Calling helper_agent.set_keyboard_ise_by_uuid() : %s", uuid);
+            m_helper_agent.set_keyboard_ise_by_uuid(m_uuid_keyboard_ise);
+        }
+        m_helper_agent.set_candidate_style(scim::ONE_LINE_CANDIDATE, scim::SOFT_CANDIDATE_WINDOW);
+    }
+}
+
+void CISECommon::get_keyboard_ise(const char *uuid)
+{
+    m_helper_agent.get_keyboard_ise(scim::String(uuid));
+}
+
+/* Slot functions for calling appropriate callback functions */
+void slot_exit(const scim::HelperAgent *agent, int ic, const scim::String &ic_uuid) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->ise_hide(ic, ic_uuid.c_str());
+            callback->exit(ic, ic_uuid.c_str());
+        }
+        scim::HelperAgent *helper_agent = impl->get_helper_agent();
+        if (helper_agent) {
+            helper_agent->update_ise_exit();
+            helper_agent->close_connection();
+        }
+    }
+    elm_exit();
+}
+
+void slot_attach_input_context(const scim::HelperAgent *agent, int ic, const scim::String &ic_uuid) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->attach_input_context(ic, ic_uuid.c_str());
+        }
+    }
+}
+
+void slot_detach_input_context(const scim::HelperAgent *agent, int ic, const scim::String &ic_uuid) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->detach_input_context(ic, ic_uuid.c_str());
+        }
+    }
+}
+
+void slot_reload_config(const scim::HelperAgent *agent, int ic, const scim::String &ic_uuid) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->reload_config(ic, ic_uuid.c_str());
+        }
+    }
+}
+
+void slot_update_screen(const scim::HelperAgent *agent, int ic, const scim::String &ic_uuid, int screen_number) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            //callback->update_screen(ic, ic_uuid.c_str(), screen_number);
+        }
+    }
+}
+
+void slot_update_spot_location(const scim::HelperAgent *agent, int ic, const scim::String &ic_uuid, int x, int y) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->update_spot_location(ic, ic_uuid.c_str(), x, y);
+        }
+    }
+}
+
+void slot_update_cursor_position(const scim::HelperAgent *agent, int ic, const scim::String &ic_uuid, int cursor_pos) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->update_cursor_position(ic, ic_uuid.c_str(), cursor_pos);
+        }
+    }
+}
+
+void slot_update_surrounding_text(const scim::HelperAgent *agent, int ic, const scim::String &text, int cursor) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->update_surrounding_text(ic, text.c_str(), cursor);
+        }
+    }
+}
+
+void slot_update_selection(const scim::HelperAgent *agent, int ic, const scim::String &text) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->update_selection(ic, text.c_str());
+        }
+    }
+}
+
+void slot_trigger_property(const scim::HelperAgent *agent, int ic, const scim::String &ic_uuid, const scim::String &property) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            //callback->trigger_property(ic, ic_uuid.c_str(), property.c_str());
+        }
+    }
+}
+
+//void slot_process_imengine_event(const HelperAgent *agent, int ic,
+//                                  const String &ic_uuid, const Transaction transaction) {
+//    CISECommon *impl = CISECommon::get_instance();
+//    if (impl) {
+//        IISECommonEventCallback *callback = impl->get_core_event_callback();
+//        if (callback) {
+//            callback->
+//        }
+//    }
+//}
+
+void slot_focus_out(const scim::HelperAgent *agent, int ic, const scim::String &ic_uuid) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->focus_out(ic, ic_uuid.c_str());
+        }
+    }
+}
+
+void slot_focus_in(const scim::HelperAgent *agent, int ic, const scim::String &ic_uuid) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->focus_in(ic, ic_uuid.c_str());
+        }
+    }
+}
+
+void slot_ise_show(const scim::HelperAgent *agent, int ic, char *buf, size_t &len) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        /* Make sure the appropriate keyboard ise was selected -> is this really necessary? */
+        //impl->set_keyboard_ise_by_uuid(impl->get_keyboard_ise_uuid().c_str());
+
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            /* Check if effect is enabled */
+            Ise_Context ise_context;
+            memset(&ise_context, 0x00, sizeof(ise_context));
+
+            if (len >= sizeof(Ise_Context)) {
+                memcpy(&ise_context, buf, sizeof(ise_context));
+
+                char imdata[IMDATA_STRING_MAX_LEN] = {0,};
+                if (ise_context.imdata_size > 0 && ise_context.imdata_size < IMDATA_STRING_MAX_LEN) {
+                    memcpy((void *)imdata, buf+sizeof(ise_context), ise_context.imdata_size);
+                    //set_ise_imdata(imdata, (size_t&)ise_context.imdata_size);
+                }
+            } else {
+                LOGD("\n-=-= WARNING - buf %p len %d size %d \n", buf, len, sizeof(ise_context));
+            }
+            callback->ise_show(ic, get_app_window_degree(impl->get_main_window()), ise_context);
+        }
+    }
+}
+
+void slot_ise_hide(const scim::HelperAgent *agent, int ic, const scim::String &ic_uuid) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->ise_hide(ic, ic_uuid.c_str());
+        }
+    }
+}
+
+void slot_get_geometry(const scim::HelperAgent *agent, struct scim::rectinfo &info) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->get_geometry(&(info.pos_x), &(info.pos_y), &(info.width), &(info.height));
+        }
+    }
+}
+
+void slot_set_mode(const scim::HelperAgent *agent, scim::uint32 &mode) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->set_mode(mode);
+        }
+    }
+}
+
+void slot_set_language(const scim::HelperAgent *agent, scim::uint32 &language) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->set_language(language);
+        }
+    }
+}
+
+void slot_set_imdata(const scim::HelperAgent *agent, char *buf, size_t &len) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->set_imdata(buf, len);
+        }
+    }
+}
+
+void slot_get_imdata(const scim::HelperAgent *, char **buf, size_t &len) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->get_imdata(buf, &len);
+        }
+    }
+}
+
+void slot_get_language_locale(const scim::HelperAgent *, int ic, char **locale) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->get_language_locale(ic, locale);
+        }
+    }
+}
+
+void slot_set_return_key_type(const scim::HelperAgent *agent, scim::uint32 &type) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->set_return_key_type(type);
+        }
+    }
+}
+
+void slot_get_return_key_type(const scim::HelperAgent *agent, scim::uint32 &type) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->get_return_key_type(&type);
+        }
+    }
+}
+
+void slot_set_return_key_disable(const scim::HelperAgent *agent, scim::uint32 &disabled) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->set_return_key_disable(disabled);
+        }
+    }
+}
+
+void slot_get_return_key_disable(const scim::HelperAgent *agent, scim::uint32 &disabled) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->get_return_key_disable(&disabled);
+        }
+    }
+}
+
+void slot_set_layout(const scim::HelperAgent *agent, scim::uint32 &layout) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->set_layout(layout);
+        }
+    }
+}
+
+void slot_get_layout(const scim::HelperAgent *agent, scim::uint32 &layout) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->get_layout(&layout);
+        }
+    }
+}
+
+void slot_set_caps_mode(const scim::HelperAgent *agent, scim::uint32 &mode) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->set_caps_mode(mode);
+        }
+    }
+}
+
+void slot_reset_input_context(const scim::HelperAgent *agent, int ic, const scim::String &uuid) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->reset_input_context(ic, uuid.c_str());
+        }
+    }
+}
+
+void slot_update_candidate_geometry(const scim::HelperAgent *agent, int ic,
+                                    const scim::String &uuid, const scim::rectinfo &info) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->update_candidate_geometry(ic, uuid.c_str(), info.pos_x, info.pos_y, info.width, info.height);
+        }
+    }
+}
+void slot_update_keyboard_ise(const scim::HelperAgent *agent, int ic, const scim::String &uuid,
+                              const scim::String &ise_name, const scim::String &ise_uuid) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->update_keyboard_ise(ic, uuid.c_str(), ise_name.c_str(), ise_uuid.c_str());
+        }
+    }
+}
+
+//void slot_update_keyboard_ise_list(const HelperAgent *agent, int ic, const String &uuid,
+//                                   const std::vector<String> &ise_list) {
+//    CISECommon *impl = CISECommon::get_instance();
+//    if (impl) {
+//        IISECommonEventCallback *callback = impl->get_core_event_callback();
+//        if (callback) {
+//            callback->get_layout(&layout);
+//        }
+//    }
+//}
+
+void slot_candidate_more_window_show(const scim::HelperAgent *agent, int ic, const scim::String &uuid) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->candidate_more_window_show(ic, uuid.c_str());
+        }
+    }
+}
+
+void slot_candidate_more_window_hide(const scim::HelperAgent *agent, int ic, const scim::String &uuid) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->candidate_more_window_hide(ic, uuid.c_str());
+        }
+    }
+}
+
+void slot_select_aux(const scim::HelperAgent *agent, int ic, const scim::String &uuid, int index) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->select_aux(ic, uuid.c_str(), index);
+        }
+    }
+}
+
+void slot_select_candidate(const scim::HelperAgent *agent, int ic, const scim::String &uuid, int index) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->select_candidate(ic, uuid.c_str(), index);
+        }
+    }
+}
+
+void slot_candidate_table_page_up(const scim::HelperAgent *agent, int ic, const scim::String &uuid) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->candidate_table_page_up(ic, uuid.c_str());
+        }
+    }
+}
+
+void slot_candidate_table_page_down(const scim::HelperAgent *agent, int ic, const scim::String &uuid) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->candidate_table_page_down(ic, uuid.c_str());
+        }
+    }
+}
+
+void slot_update_candidate_table_page_size(const scim::HelperAgent *, int ic, const scim::String &uuid, int page_size) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->update_candidate_table_page_size(ic, uuid.c_str(), page_size);
+        }
+    }
+}
+
+void slot_select_associate(const scim::HelperAgent *agent, int ic, const scim::String &uuid, int index) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->select_associate(ic, uuid.c_str(), index);
+        }
+    }
+}
+
+void slot_associate_table_page_up(const scim::HelperAgent *agent, int ic, const scim::String &uuid) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->associate_table_page_up(ic, uuid.c_str());
+        }
+    }
+}
+
+void slot_associate_table_page_down(const scim::HelperAgent *agent, int ic, const scim::String &uuid) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->associate_table_page_down(ic, uuid.c_str());
+        }
+    }
+}
+
+void slot_update_associate_table_page_size(const scim::HelperAgent *, int ic, const scim::String &uuid, int page_size) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->update_associate_table_page_size(ic, uuid.c_str(), page_size);
+        }
+    }
+}
+
+void slot_turn_on_log(const scim::HelperAgent *agent, scim::uint32 &on) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->turn_on_log(on);
+        }
+    }
+}
+
+/* Internal signal handler function */
+void signal_handler(int sig) {
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        IISECommonEventCallback *callback = impl->get_core_event_callback();
+        if (callback) {
+            callback->signal_handler(sig);
+        }
+    }
+    elm_exit();
+}
+
+/* Internal input handler function */
+Eina_Bool input_handler(void *data, Ecore_Fd_Handler *fd_handler)
+{
+    CISECommon *impl = CISECommon::get_instance();
+    if (impl) {
+        scim::HelperAgent *agent = impl->get_helper_agent();
+        if (agent) {
+            if (agent->has_pending_event()) {
+                if (!(agent->filter_event())) {
+                    LOGD("helper_agent.filter_event() failed!!!\n");
+                    impl->exit();
+                    elm_exit();
+                }
+            } else {
+                LOGD("helper_agent.has_pending_event() failed!!!\n");
+                impl->exit();
+                elm_exit();
+            }
+        }
+    }
+
+    return ECORE_CALLBACK_RENEW;
+}
+
+void CISECommon::register_slot_functions()
+{
+    m_helper_agent.signal_connect_exit(scim::slot(slot_exit));
+    m_helper_agent.signal_connect_attach_input_context(scim::slot(slot_attach_input_context));
+    m_helper_agent.signal_connect_detach_input_context(scim::slot(slot_detach_input_context));
+    m_helper_agent.signal_connect_reload_config(scim::slot(slot_reload_config));
+    m_helper_agent.signal_connect_update_screen(scim::slot(slot_update_screen));
+    m_helper_agent.signal_connect_update_spot_location(scim::slot(slot_update_spot_location));
+    m_helper_agent.signal_connect_update_cursor_position(scim::slot(slot_update_cursor_position));
+    m_helper_agent.signal_connect_update_surrounding_text(scim::slot(slot_update_surrounding_text));
+    m_helper_agent.signal_connect_update_selection(scim::slot(slot_update_selection));
+    m_helper_agent.signal_connect_trigger_property(scim::slot(slot_trigger_property));
+    //m_helper_agent.signal_connect_process_imengine_event(slot (slot_process_imengine_event));
+    m_helper_agent.signal_connect_focus_out(scim::slot(slot_focus_out));
+    m_helper_agent.signal_connect_focus_in(scim::slot(slot_focus_in));
+    m_helper_agent.signal_connect_ise_show(scim::slot(slot_ise_show));
+    m_helper_agent.signal_connect_ise_hide(scim::slot(slot_ise_hide));
+    m_helper_agent.signal_connect_get_geometry(scim::slot(slot_get_geometry));
+    m_helper_agent.signal_connect_set_mode(scim::slot(slot_set_mode));
+    m_helper_agent.signal_connect_set_language(scim::slot(slot_set_language));
+    m_helper_agent.signal_connect_set_imdata(scim::slot(slot_set_imdata));
+    m_helper_agent.signal_connect_get_imdata(scim::slot(slot_get_imdata));
+    m_helper_agent.signal_connect_get_language_locale(scim::slot(slot_get_language_locale));
+    m_helper_agent.signal_connect_set_return_key_type(scim::slot(slot_set_return_key_type));
+    m_helper_agent.signal_connect_get_return_key_type(scim::slot(slot_get_return_key_type));
+    m_helper_agent.signal_connect_set_return_key_disable(scim::slot(slot_set_return_key_disable));
+    m_helper_agent.signal_connect_get_return_key_disable(scim::slot(slot_get_return_key_disable));
+    m_helper_agent.signal_connect_get_layout(scim::slot(slot_get_layout));
+    m_helper_agent.signal_connect_set_layout(scim::slot(slot_set_layout));
+    m_helper_agent.signal_connect_set_caps_mode(scim::slot(slot_set_caps_mode));
+    m_helper_agent.signal_connect_reset_input_context(scim::slot(slot_reset_input_context));
+    m_helper_agent.signal_connect_update_candidate_geometry(scim::slot(slot_update_candidate_geometry));
+    m_helper_agent.signal_connect_update_keyboard_ise(scim::slot(slot_update_keyboard_ise));
+    //m_helper_agent.signal_connect_update_keyboard_ise_list(slot (slot_update_keyboard_ise_list));
+    m_helper_agent.signal_connect_candidate_more_window_show(scim::slot(slot_candidate_more_window_show));
+    m_helper_agent.signal_connect_candidate_more_window_hide(scim::slot(slot_candidate_more_window_hide));
+    m_helper_agent.signal_connect_select_aux(scim::slot(slot_select_aux));
+    m_helper_agent.signal_connect_select_candidate(scim::slot(slot_select_candidate));
+    m_helper_agent.signal_connect_candidate_table_page_up(scim::slot(slot_candidate_table_page_up));
+    m_helper_agent.signal_connect_candidate_table_page_down(scim::slot(slot_candidate_table_page_down));
+    m_helper_agent.signal_connect_update_candidate_table_page_size(scim::slot(slot_update_candidate_table_page_size));
+    m_helper_agent.signal_connect_select_associate(scim::slot(slot_select_associate));
+    m_helper_agent.signal_connect_associate_table_page_up(scim::slot(slot_associate_table_page_up));
+    m_helper_agent.signal_connect_associate_table_page_down(scim::slot(slot_associate_table_page_down));
+    m_helper_agent.signal_connect_update_associate_table_page_size(scim::slot(slot_update_associate_table_page_size));
+    m_helper_agent.signal_connect_turn_on_log(scim::slot(slot_turn_on_log));
+}
+
+const char* CISECommon::get_ise_uuid()
+{
+    return m_uuid_ise.c_str();
+}
diff --git a/src/include/common.h b/src/include/common.h
new file mode 100644 (file)
index 0000000..81c08ae
--- /dev/null
@@ -0,0 +1,413 @@
+/*
+ * Copyright (c) 2012 - 2014 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 __COMMON_H__
+#define __COMMON_H__
+
+#define Uses_SCIM_UTILITY
+#define Uses_SCIM_OBJECT
+#define Uses_SCIM_POINTER
+#define Uses_SCIM_EVENT
+#define Uses_SCIM_HELPER
+#define Uses_SCIM_CONFIG_BASE
+
+#include <scim.h>
+#include <Evas.h>
+#include <ise_context.h>
+
+#include "packages.h"
+
+
+struct IISECommonEventCallback {
+    virtual void init() {}
+    virtual void exit(int ic, const char *ic_uuid) {}
+    virtual void attach_input_context(int ic, const char *ic_uuid) {}
+    virtual void detach_input_context(int ic, const char *ic_uuid) {}
+    virtual void reload_config(int ic, const char *ic_uuid) {}
+    virtual void update_spot_location(int ic, const char *ic_uuid, int x, int y) {}
+    virtual void update_cursor_position(int ic, const char *ic_uuid, int cursor_pos) {}
+    virtual void update_surrounding_text(int ic, const char *text, int cursor) {}
+    virtual void update_selection(int ic, const char *text) {}
+    virtual void focus_out(int ic, const char *ic_uuid) {}
+    virtual void focus_in(int ic, const char *ic_uuid) {}
+    virtual void ise_show(int ic, const int degree, Ise_Context &context) {}
+    virtual void ise_hide(int ic, const char *ic_uuid) {}
+    virtual void get_geometry(unsigned int *pos_x, unsigned int *pos_y, unsigned int *width, unsigned int *height) {}
+    virtual void set_mode(unsigned int mode) {}
+    virtual void set_language(unsigned int language) {}
+    virtual void set_imdata(char *buf, unsigned int len) {}
+    virtual void get_imdata(char **buf, unsigned int *len) {}
+    virtual void get_language_locale(int ic, char **locale) {}
+    virtual void set_return_key_type(unsigned int type) {}
+    virtual void get_return_key_type(unsigned int *type) {}
+    virtual void set_return_key_disable(unsigned int disabled) {}
+    virtual void get_return_key_disable(unsigned int *disabled) {}
+    virtual void set_layout(unsigned int layout) {}
+    virtual void get_layout(unsigned int *layout) {}
+    virtual void set_caps_mode(unsigned int mode) {}
+    virtual void reset_input_context(int ic, const char *uuid) {}
+    virtual void update_candidate_geometry(int ic, const char *uuid, int pos_x, int pos_y, int width, int height) {}
+    virtual void update_keyboard_ise(int ic, const char *uuid, const char *ise_name, const char *ise_uuid) {}
+    virtual void candidate_more_window_show(int ic, const char *uuid) {}
+    virtual void candidate_more_window_hide(int ic, const char *uuid) {}
+    virtual void select_aux(int ic, const char *uuid, int index) {}
+    virtual void select_candidate(int ic, const char *uuid, int index) {}
+    virtual void candidate_table_page_up(int ic, const char *uuid) {}
+    virtual void candidate_table_page_down(int ic, const char *uuid) {}
+    virtual void update_candidate_table_page_size(int ic, const char *uuid, int page_size) {}
+    virtual void select_associate(int ic, const char *uuid, int index) {}
+    virtual void associate_table_page_up(int ic, const char *uuid) {}
+    virtual void associate_table_page_down(int ic, const char *uuid) {}
+    virtual void update_associate_table_page_size(int ic, const char *uuid, int page_size) {}
+    virtual void turn_on_log(unsigned int on) {}
+    virtual void ise_process_key_event(unsigned int code, unsigned int mask, unsigned int layout, unsigned int *ret) {}
+
+    virtual void set_display_language(const char *language) {}
+    virtual void set_theme_name(const char *name) {}
+    virtual void set_rotation_degree(int degree) {}
+    virtual void set_accessibility_state(int state) {}
+
+    virtual void signal_handler(int sig) {}
+};
+
+/**
+ * @brief The base class to work as a soft-based keyboard
+ *
+ * This class defines all functions for working as a soft-based keyboard
+ * In side of ISE developer, they can use it by their requirements.
+ */
+class CISECommon
+{
+private:
+    static CISECommon* m_instance; /* For singleton */
+    CISECommon();
+
+public:
+    ~CISECommon();
+
+    static CISECommon* get_instance();
+
+    /**
+     * @brief This API returns the pointer to current helper agent object
+     */
+    scim::HelperAgent* get_helper_agent();
+
+    /**
+     * @brief This API creates an SCLCore object that communicates with SCIM server
+     */
+    void init();
+
+    /**
+     * @brief This API deletes SCLCore object and releases all resources
+     */
+    void exit();
+
+    /**
+     * @brief This API runs the main loop
+     * @param[in] uuid The uuid string acquired from SCIM's run_helper interface
+     * @param[in] display The display string acquired from SCIM's run_helper interface
+     */
+    void run(const char *uuid, const scim::ConfigPointer &config, const char *display);
+    //void run(const char *uuid, const char *display);
+
+    /**
+     * @brief This API returns the number of helpers in current ISE
+     */
+    int get_number_of_helpers(void);
+
+    /**
+     * @brief This API returns the helper information
+     * @param[in] idx The index number of helper acquired from SCIM's get_helper_info interface
+     * @param[out] info The HelperInfo structure acquired from SCIM's get_helper_info interface
+     */
+    bool get_helper_info(int idx, scim::HelperInfo &info);
+
+    /**
+     * @brief This API returns the language locale string supported by current ISE
+     * @param[in] idx The index number of helper acquired from SCIM's get_helper_language interface
+     */
+    scim::String get_helper_language(int idx);
+
+    /**
+     * @brief This API registers a callback interface, to handle the core events generated by SCIM
+     * @param[in] callback a pointer to IISECommonEventCallback interface implementation class
+     */
+    void set_core_event_callback(IISECommonEventCallback *callback);
+
+    /**
+     * @brief This API returns the current callback interface.
+     * @param[in] callback a pointer to IISECommonEventCallback interface implementation class
+     */
+    IISECommonEventCallback* get_core_event_callback();
+
+    /**
+     * @brief This API returns the pointer to main keyboard window
+     */
+    Evas_Object* get_main_window();
+
+    /**
+     * @brief This API updates the keyboard window's geometry information
+     */
+    void set_keyboard_size_hints(int portrait_width, int portrait_height, int landscape_width, int landscape_height);
+
+    /**
+     * @brief This API returns the uuid of keyboard ise that was previously set.
+     */
+    scim::String get_keyboard_ise_uuid();
+
+    /**
+     * @brief Request SCIM to reload all configuration.
+     */
+    void reload_config();
+
+    /**
+     * @brief Send an Event to IMEngine
+     *
+     * @param[in] ic The handle of the IMEngineInstance to receive the event.
+     *            -1 means the currently focused IMEngineInstance.
+     * @param[in] ic_uuid The UUID of the IMEngineInstance. NULL means don't match.
+     * @param[in] command The command to be sent.
+     * @param[in] value The value corresponding to the command.
+     */
+    void send_imengine_event(int ic, const char *ic_uuid, const int command, const int value);
+
+    /**
+     * @brief Send a reset keyboard Event to IMEngine
+     */
+    void reset_keyboard_ise();
+
+    /**
+     * @brief Send a KeyEvent to SCIM
+     *
+     * @param[in] ic The handle of the IMEngineInstance to receive the event.
+     *            -1 means the currently focused IMEngineInstance.
+     * @param[in] ic_uuid The UUID of the IMEngineInstance. NULL means don't match.
+     * @param[in] keycode The KeyEvent to be sent.
+     * @param[in] keymask The modifier key mask
+     */
+    void send_key_event(int ic, const char *ic_uuid, int keycode, int keymask);
+
+    /**
+     * @brief Forward a KeyEvent to client application directly.
+     *
+     * @param[in] ic The handle of the client Input Context to receive the event.
+     *            -1 means the currently focused Input Context.
+     * @param[in] ic_uuid The UUID of the IMEngineInstance. NULL means don't match.
+     * @param[in] keycode The KeyEvent to be sent.
+     * @param[in] keymask The modifier key mask
+     */
+    void forward_key_event(int ic, const char *ic_uuid, int keycode, int keymask);
+
+    /**
+     * @brief Commit a WideString to client application directly.
+     *
+     * @param[in] ic The handle of the client Input Context to receive the WideString.
+     *            -1 means the currently focused Input Context.
+     * @param[in] ic_uuid The UUID of the IMEngine used by the Input Context.
+     *            NULL means don't match.
+     * @param[in] str The UTF-8 string to be committed.
+     */
+    //void commit_string(int ic, const char *ic_uuid, const WideString &wstr) const;
+    void commit_string(int ic, const char *ic_uuid, const char *str);
+
+    /**
+     * @brief Request to show preedit string.
+     *
+     * @param[in] ic The handle of the client Input Context to receive the request.
+     *            -1 means the currently focused Input Context.
+     * @param[in] ic_uuid The UUID of the IMEngine used by the Input Context.
+     *            NULL means don't match.
+     */
+    void show_preedit_string(int ic, const char *ic_uuid);
+
+    /**
+     * @brief Request to show aux string.
+     */
+    void show_aux_string(void);
+
+    /**
+     * @brief Request to show candidate string.
+     */
+    void show_candidate_string(void);
+
+    /**
+     * @brief Request to show associate string.
+     */
+    void show_associate_string(void);
+
+    /**
+     * @brief Request to hide preedit string.
+     *
+     * @param[in] ic The handle of the client Input Context to receive the request.
+     *            -1 means the currently focused Input Context.
+     * @param[in] ic_uuid The UUID of the IMEngine used by the Input Context.
+     *            NULL means don't match.
+     */
+    void hide_preedit_string(int ic, const char *ic_uuid);
+
+    /**
+     * @brief Request to hide aux string.
+     */
+    void hide_aux_string(void);
+
+    /**
+     * @brief Request to hide candidate string.
+     */
+    void hide_candidate_string(void);
+
+    /**
+     * @brief Request to hide associate string.
+     */
+    void hide_associate_string(void);
+
+    /**
+     * @brief Update a new WideString for preedit.
+     *
+     * @param[in] ic The handle of the client Input Context to receive the WideString.
+     *            -1 means the currently focused Input Context.
+     * @param[in] ic_uuid The UUID of the IMEngine used by the Input Context.
+     *            NULL means don't match.
+     * @param[in] str The UTF-8 string to be updated.
+     * @param[in] attrs The attribute list for preedit string.
+     */
+    /*void update_preedit_string(int ic, const char *ic_uuid, const char *str, const AttributeList &attrs) const;*/
+    void update_preedit_string(int ic, const char *ic_uuid, const char *str);
+
+    /**
+     * @brief Update a new string for aux.
+     *
+     * @param[in] str The string to be updated.
+     * @param[in] attrs The attribute list for aux string.
+     */
+    //void update_aux_string(const char *str, const AttributeList &attrs) const;
+    void update_aux_string(const char *str);
+
+    /**
+     * @brief Request to update candidate.
+     *
+     * @param[in] table The lookup table for candidate.
+     */
+    //void update_candidate_string(const LookupTable &table) const;
+
+    /**
+     * @brief Request to update associate.
+     *
+     * @param[in] table The lookup table for associate.
+     */
+    //void update_associate_string(const LookupTable &table) const;
+
+    /**
+     * @ brief When the input context of ISE is changed,
+     *         ISE can call this function to notify application
+     *
+     * @param[in] type  type of event.
+     * @param[in] value value of event.
+     */
+    void update_input_context(int type, int value);
+
+    /**
+     * @ brief Request to get surrounding text.
+     *
+     * @param[in] maxlen_before The max length of before.
+     * @param[in] maxlen_after The max length of after.
+     */
+    void get_surrounding_text(int maxlen_before, int maxlen_after);
+
+    /**
+     * @ brief Request to delete surrounding text.
+     *
+     * @param[in] offset The offset for cursor position.
+     * @param[in] len The length for delete text.
+     */
+    void delete_surrounding_text(int offset, int len);
+
+    /**
+     * @brief Request to select text.
+     *
+     * @param start_index The start position in text.
+     * @param end_index The end position in text.
+     */
+    void set_selection(int start_index, int end_index);
+
+    /**
+     * @brief Request to get selection.
+     */
+    void get_selection();
+
+    /**
+     * @ brief Set candidate position in screen.
+     *
+     * @param[in] left The x position in screen.
+     * @param[in] top The y position in screen.
+     */
+    void set_candidate_position(int left, int top);
+
+    /**
+     * @ brief Request to hide candidate window.
+     */
+    void candidate_hide(void);
+
+    /**
+     * @ 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.
+     *
+     * @param[in] uuid The keyboard ISE UUID.
+     */
+    void set_keyboard_ise_by_uuid(const char *uuid);
+
+    /**
+     * @ brief Request to get current keyboard ISE information.
+     *
+     * @param[in] uuid The helper ISE UUID.
+     */
+    void get_keyboard_ise(const char *uuid);
+
+    /**
+     * @ brief Request to get uuid list of all keyboard ISEs.
+     *
+     * @param[in] uuid The helper ISE UUID.
+     */
+    //void get_keyboard_ise_list    (const String                &uuid) const;
+
+    /**
+     * @ brief Request to get the uuid of currently selected ISE.
+     *
+     */
+    const char* get_ise_uuid();
+
+private:
+    virtual void register_slot_functions();
+
+private:
+    //std::vector<HelperInfoEx> m_helper_infos;
+    scim::HelperAgent m_helper_agent;
+
+    IISECommonEventCallback *m_event_callback;
+
+    scim::String m_uuid_ise;
+    scim::String m_uuid_keyboard_ise;
+
+    Evas_Object *m_main_window;
+};
+
+#endif //__COMMON_H__
diff --git a/src/include/ise.h b/src/include/ise.h
new file mode 100644 (file)
index 0000000..e124adf
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2012 - 2014 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 _ISE_H_
+#define _ISE_H_
+
+#include <Ecore.h>
+#include <Evas.h>
+#include <Ecore_Evas.h>
+#include <Ecore_IMF.h>
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif  /*  */
+
+//#include "languages.h"
+
+#define ISE_VERSION "0.0.1-1"
+#define LOCALEDIR "/usr/share/locale"
+
+#define PRIMARY_LATIN_LANGUAGE "English"
+
+#define DEFAULT_KEYBOARD_ISE_UUID "d75857a5-4148-4745-89e2-1da7ddaf7999"
+
+//#define INPUT_MODE_NATIVE    MAX_INPUT_MODE /* Native mode. It will distinguish to the current user language */
+
+//#define ISE_RELEASE_AUTOCOMMIT_BLOCK_INTERVAL 1300
+
+#include <dlog.h>
+#undef LOG_TAG
+#define LOG_TAG "ISE_WEB_HELPER_AGENT"
+
+enum ISE_LAYOUT{
+    ISE_LAYOUT_STYLE_NORMAL = 0,
+    ISE_LAYOUT_STYLE_NUMBER,
+    ISE_LAYOUT_STYLE_EMAIL,
+    ISE_LAYOUT_STYLE_URL,
+    ISE_LAYOUT_STYLE_PHONENUMBER,
+    ISE_LAYOUT_STYLE_IP,
+    ISE_LAYOUT_STYLE_MONTH,
+    ISE_LAYOUT_STYLE_NUMBERONLY,
+    ISE_LAYOUT_STYLE_INVALID,
+    ISE_LAYOUT_STYLE_HEX,
+    ISE_LAYOUT_STYLE_TERMINAL,
+    ISE_LAYOUT_STYLE_PASSWORD,
+    ISE_LAYOUT_STYLE_DATETIME,
+
+    ISE_LAYOUT_STYLE_MAX
+};
+
+typedef struct {
+    int ic;
+    int focused_ic;
+    unsigned int layout;
+    unsigned int caps_mode;
+    unsigned int need_reset;
+    unsigned int visible_state;
+
+    int angle;
+    int portrait_width;
+    int portrait_height;
+    int landscape_width;
+    int landscape_height;
+} KEYBOARD_STATE;
+
+void ise_signal_handler(int sig);
+
+void ise_log(const char *str);
+void ise_send_string(const char *key_value);
+void ise_update_preedit_string(const char *str);
+void ise_send_event(int key_event, int key_mask);
+void ise_forward_key_event(int key_event);
+void ise_set_keyboard_size_hints(int portrait_width, int portrait_height, int landscape_width, int landscape_height);
+void ise_set_selection(int start_index, int end_index);
+void ise_get_selection();
+void ise_get_surrounding_text(int maxlen_before, int maxlen_after);
+void ise_delete_surrounding_text(int offset, int len);
+
+void ise_create();
+void ise_destroy();
+void ise_attach_input_context(int ic);
+void ise_detach_input_context(int ic);
+
+void ise_focus_in(int ic);
+void ise_focus_out(int ic);
+void ise_show(int ic);
+void ise_hide(int ic);
+void ise_set_screen_rotation(int degree);
+void ise_update_cursor_position(int ic, int position);
+void ise_update_surrounding_text(int ic, const char *text, int cursor);
+void ise_update_selection(int ic, const char *text);
+void ise_set_language(unsigned int language);
+void ise_set_imdata(char *buf, unsigned int len);
+void ise_get_imdata(char **buf, unsigned int *len);
+void ise_set_return_key_type(unsigned int type);
+void ise_get_return_key_type(unsigned int *type);
+void ise_set_return_key_disable(unsigned int disabled);
+void ise_get_return_key_disable(unsigned int *disabled);
+void ise_set_layout(unsigned int layout);
+void ise_get_layout(unsigned int *layout);
+void ise_reset_input_context(int ic);
+void ise_process_key_event(unsigned int code, unsigned int mask, unsigned int layout, unsigned int *ret);
+
+void ise_reset_context();
+void ise_set_accessibility_state(int state);
+void ise_set_caps_mode(unsigned int mode);
+void ise_get_language_locale(int ic, char **locale);
+
+#endif
diff --git a/src/include/packages.h b/src/include/packages.h
new file mode 100644 (file)
index 0000000..4ba7b3e
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2012 - 2014 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 _PACKAGES_H_
+#define _PACKAGES_H_
+
+#define Uses_SCIM_UTILITY
+#define Uses_SCIM_OBJECT
+#define Uses_SCIM_POINTER
+#define Uses_SCIM_EVENT
+#define Uses_SCIM_HELPER
+#define Uses_SCIM_CONFIG_BASE
+
+#include <stdio.h>
+#include <string>
+#include <vector>
+#include <scim.h>
+
+typedef struct {
+    scim::HelperInfo helper_info;
+    scim::String supported_languages;
+    std::string application_path;
+} HelperInfoEx;
+
+class CPackages {
+private:
+    static CPackages* m_instance; /* For singleton */
+    CPackages() {};
+public:
+    virtual ~CPackages() {};
+
+    static CPackages* get_instance();
+
+    void init();
+    void fini();
+
+    int get_number_of_packages();
+
+    HelperInfoEx get_package_information_by_index(int index);
+    HelperInfoEx get_package_information_by_uuid(scim::String uuid);
+
+private:
+};
+
+#endif // _PACKAGES_H_
diff --git a/src/include/web_container.h b/src/include/web_container.h
new file mode 100644 (file)
index 0000000..232a9a3
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2012 - 2014 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.
+ *
+ */
+
+#define WEB_CONTAINER_PLUGIN_PATH "/usr/lib/scim-1.0/web-container.so"
+
+#define WEB_CONTENT_PREPARE_COMMAND "WebHelperClient.impl.prepare"
+#define WEB_CONTENT_ACTIVATE_COMMAND "WebHelperClient.impl.activate"
+
+#include "packages.h"
+#include "Evas.h"
+
+/* Plugin interfaces */
+#define WEB_CONTAINER_CREATE_API "web_container_create"
+#define WEB_CONTAINER_DESTROY_API "web_container_destroy"
+#define WEB_CONTAINER_RESIZE_API "web_container_resize"
+#define WEB_CONTAINER_JAVASCRIPT_API "web_container_javascript"
+
+typedef void (*web_container_javascript_cb)(const char* result_value);
+typedef void (*web_container_loaded_cb)();
+
+typedef bool (*web_container_create_api) (Evas_Object *window, HelperInfoEx info, web_container_loaded_cb callback);
+typedef bool (*web_container_destroy_api) ();
+typedef bool (*web_container_resize_api) (int width, int height);
+typedef bool (*web_container_javascript_api) (const char *command, web_container_javascript_cb callback);
+
+/* Container interfaces */
+extern "C" {
+bool web_container_create(Evas_Object *window, HelperInfoEx info, web_container_loaded_cb callback);
+bool web_container_destroy();
+
+bool web_container_resize(int width, int height);
+bool web_container_javascript(const char *command, web_container_javascript_cb callback);
+}
diff --git a/src/include/web_helper_agent.h b/src/include/web_helper_agent.h
new file mode 100644 (file)
index 0000000..96aaaa6
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2012 - 2014 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 <string>
+#include <sstream>
+#include <vector>
+
+class CStringTokenizer
+{
+public:
+    static std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
+        int loop = 0;
+        int start = 0;
+        for (loop = 0;loop < (int)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<std::string> split(const std::string &s, char delim) {
+        std::vector<std::string> 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/ise.cpp b/src/ise.cpp
new file mode 100644 (file)
index 0000000..796e80a
--- /dev/null
@@ -0,0 +1,610 @@
+/*
+ * Copyright (c) 2012 - 2014 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 <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <Ecore_X.h>
+#include <Ecore_IMF.h>
+#include <Elementary.h>
+
+#include <X11/XF86keysym.h>
+
+#include <vconf.h>
+#include <vconf-keys.h>
+
+#include <package_manager.h>
+#include <pkgmgr-info.h>
+
+#include "ise.h"
+#include "common.h"
+#include "packages.h"
+#include "web_helper_agent.h"
+
+#include "web_container.h"
+
+#include <memory>
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+extern CISECommon *g_ise_common;
+
+static CWebHelperAgent *g_web_helper_agent = NULL;
+static package_manager_h g_package_manager = NULL;
+
+KEYBOARD_STATE g_keyboard_state = {
+    0,
+    0,
+    ISE_LAYOUT_STYLE_NORMAL,
+    FALSE,
+    TRUE,
+    FALSE,
+};
+
+int
+check_ic_temporary(int ic)
+{
+    if ((ic & 0xFFFF) == 0) {
+        return TRUE;
+    }
+    return FALSE;
+}
+
+/**
+ * Leave a log
+ */
+void
+ise_log(const char *str)
+{
+    LOGD("ISELOG : %s", str);
+}
+
+/**
+ * Send the given string to input framework
+ */
+void
+ise_send_string(const char *key_value)
+{
+    int ic = -1;
+    if (!check_ic_temporary(g_keyboard_state.ic)) {
+        ic = g_keyboard_state.ic;
+    }
+    g_ise_common->hide_preedit_string(ic, "");
+    g_ise_common->commit_string(ic, "", key_value);
+}
+
+/**
+* Send the preedit string to input framework
+*/
+void
+ise_update_preedit_string(const char *str)
+{
+    int ic = -1;
+    if (!check_ic_temporary(g_keyboard_state.ic)) {
+        ic = g_keyboard_state.ic;
+    }
+    g_ise_common->update_preedit_string(ic, "", str);
+}
+
+/**
+* Send the given event to input framework
+*/
+void
+ise_send_event(int key_event, int key_mask)
+{
+    int ic = -1;
+    if (!check_ic_temporary(g_keyboard_state.ic)) {
+        ic = g_keyboard_state.ic;
+    }
+    g_ise_common->forward_key_event(ic, "", key_event, scim::SCIM_KEY_NullMask);
+    g_ise_common->forward_key_event(ic, "", key_event, scim::SCIM_KEY_ReleaseMask);
+}
+
+/**
+* Forward the given event to input framework
+*/
+void
+ise_forward_key_event(int key_event)
+{
+    int ic = -1;
+    if (!check_ic_temporary(g_keyboard_state.ic)) {
+        ic = g_keyboard_state.ic;
+    }
+    g_ise_common->forward_key_event(ic, "", key_event, scim::SCIM_KEY_NullMask);
+    g_ise_common->forward_key_event(ic, "", key_event, scim::SCIM_KEY_ReleaseMask);
+}
+
+void ise_set_keyboard_size_hints(int portrait_width, int portrait_height, int landscape_width, int landscape_height)
+{
+    g_keyboard_state.portrait_width = portrait_width;
+    g_keyboard_state.portrait_height = portrait_height;
+    g_keyboard_state.landscape_width = landscape_width;
+    g_keyboard_state.landscape_height = landscape_height;
+
+    g_ise_common->set_keyboard_size_hints(portrait_width, portrait_height, landscape_width, landscape_height);
+
+    if (g_keyboard_state.angle == 90 || g_keyboard_state.angle == 270) {
+        web_container_resize(g_keyboard_state.landscape_width, g_keyboard_state.landscape_height);
+    } else {
+        web_container_resize(g_keyboard_state.portrait_width, g_keyboard_state.portrait_height);
+    }
+}
+
+void ise_set_selection(int start_index, int end_index)
+{
+    g_ise_common->set_selection(start_index, end_index);
+}
+
+void ise_get_selection()
+{
+    g_ise_common->get_selection();
+}
+
+void ise_get_surrounding_text(int maxlen_before, int maxlen_after)
+{
+    g_ise_common->get_surrounding_text(maxlen_before, maxlen_after);
+}
+
+void ise_delete_surrounding_text(int offset, int len)
+{
+    g_ise_common->delete_surrounding_text(offset, len);
+}
+
+void web_content_prepared(const char* result_value)
+{
+    if (result_value) {
+        std::string version_string = result_value;
+        LOGD("Version : %s", version_string.c_str());
+
+        std::vector<std::string> vec = CStringTokenizer::split(version_string, VERSION_DELIMITER);
+
+        if (vec.size() == VERSION_TOKEN_NUM) {
+            WEB_HELPER_AGENT_TYPE type =
+                CWebHelperAgent::get_web_helper_agent_type_from_major_version(atoi(vec.at(0).c_str()));
+            if (g_web_helper_agent) {
+                g_web_helper_agent->exit();
+                CWebHelperAgent::destroy_web_helper_agent(g_web_helper_agent);
+            }
+            g_web_helper_agent = CWebHelperAgent::create_web_helper_agent(type);
+            if (g_web_helper_agent) {
+                g_web_helper_agent->init();
+            }
+        }
+    }
+
+    const int MAX_COMMAND_LENGTH = 255;
+    char activate_command[MAX_COMMAND_LENGTH + 1] = {'\0'};
+    snprintf(activate_command, MAX_COMMAND_LENGTH, "%s();", WEB_CONTENT_ACTIVATE_COMMAND);
+    activate_command[MAX_COMMAND_LENGTH] = '\0';
+
+    if (web_container_javascript(activate_command, NULL) == EINA_FALSE) {
+        LOGW("Failed while executing command : %s", WEB_CONTENT_ACTIVATE_COMMAND);
+    }
+}
+
+void web_container_loaded()
+{
+    const int MAX_COMMAND_LENGTH = 255;
+    char prepare_command[MAX_COMMAND_LENGTH + 1] = {'\0'};
+    snprintf(prepare_command, MAX_COMMAND_LENGTH, "%s('%s');",
+        WEB_CONTENT_PREPARE_COMMAND, CMagicKeyManager::get_magic_key().c_str());
+    prepare_command[MAX_COMMAND_LENGTH] = '\0';
+    LOGD("Executing command : %s", WEB_CONTENT_PREPARE_COMMAND);
+    if (web_container_javascript(prepare_command, web_content_prepared) == false) {
+        LOGW("Failed while executing command : %s", WEB_CONTENT_PREPARE_COMMAND);
+    }
+}
+
+static bool
+app_info_cb (package_info_app_component_type_e comp_type, const char *app_id, void *user_data)
+{
+    pkgmgrinfo_appinfo_h appinfo_handle;
+    bool exist = false;
+    bool *result = static_cast<bool*>(user_data);
+
+    if (pkgmgrinfo_appinfo_get_appinfo (app_id, &appinfo_handle) != PMINFO_R_OK)
+        return true;
+
+    pkgmgrinfo_appinfo_is_category_exist (appinfo_handle, "http://tizen.org/category/ime", &exist);
+
+    if (exist) {
+        /* FIXME : need to use generated UUID */
+        LOGD ("package being installed or updated, : %s %s\n", app_id, g_ise_common->get_ise_uuid());
+        if (strcmp(app_id, g_ise_common->get_ise_uuid()) == 0) {
+            LOGD ("Same appid, reloading");
+            if (result) {
+                *result = true;
+            }
+        }
+    }
+
+    pkgmgrinfo_appinfo_destroy_appinfo (appinfo_handle);
+
+    return true;
+}
+
+static void check_helper_ise_info(const char *type, const char *package)
+{
+    package_info_h pkg_info = NULL;
+    char *pkg_label = NULL;
+    char *pkg_icon_path = NULL;
+    bool result = false;
+
+    if (!type)
+        return;
+
+    if (strncmp (type, "wgt", 3) != 0)
+        return;
+
+    if (package_info_create (package, &pkg_info) != PACKAGE_MANAGER_ERROR_NONE)
+        return;
+
+    if (!pkg_info)
+        return;
+
+    package_info_get_label (pkg_info, &pkg_label);
+    package_info_get_icon (pkg_info, &pkg_icon_path);
+
+    package_info_foreach_app_from_package (pkg_info, PACKAGE_INFO_UIAPP, app_info_cb, &result);
+
+    if (pkg_label)
+        free (pkg_label);
+
+    if (pkg_icon_path)
+        free (pkg_icon_path);
+
+    package_info_destroy (pkg_info);
+
+    if (result) {
+        scim::HelperAgent *helper_agent = g_ise_common->get_helper_agent();
+        if (helper_agent) {
+            helper_agent->update_ise_exit();
+            helper_agent->close_connection();
+        }
+        IISECommonEventCallback *callback = g_ise_common->get_core_event_callback();
+        if (callback) {
+            callback->exit(-1, "");
+        }
+        elm_exit();
+    }
+}
+
+static void _package_manager_event_cb(const char *type, const char *package, package_manager_event_type_e event_type, package_manager_event_state_e event_state, int progress, package_manager_error_e error, void *user_data)
+{
+    if (!package || !type) return;
+
+    if (event_type == PACKAGE_MANAGER_EVENT_TYPE_INSTALL ||
+            event_type == PACKAGE_MANAGER_EVENT_TYPE_UPDATE) {
+
+        if (event_state != PACKAGE_MANAGER_EVENT_STATE_COMPLETED)
+            return;
+
+        check_helper_ise_info (type, package);
+    }
+}
+
+void
+ise_create()
+{
+    if (g_package_manager == NULL) {
+        package_manager_create(&g_package_manager);
+        package_manager_set_event_cb(g_package_manager, _package_manager_event_cb, NULL);
+    }
+
+    if (g_ise_common) {
+        if (g_ise_common->get_main_window()) {
+            ecore_x_icccm_name_class_set(
+                elm_win_xwindow_get(static_cast<Evas_Object*>(g_ise_common->get_main_window())),
+                "Virtual Keyboard", "ISF" );
+            elm_win_prop_focus_skip_set(g_ise_common->get_main_window(), EINA_TRUE);
+        }
+    }
+
+    Evas_Object* bg = elm_bg_add(g_ise_common->get_main_window());
+    evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+    elm_bg_color_set(bg, 0, 0, 0);
+    elm_win_resize_object_add(g_ise_common->get_main_window(), bg);
+    evas_object_show(bg);
+
+    HelperInfoEx info;
+    CPackages *packages = CPackages::get_instance();
+    if (packages) {
+        info = packages->get_package_information_by_uuid(g_ise_common->get_ise_uuid());
+    }
+
+    web_container_create(g_ise_common->get_main_window(), info, web_container_loaded);
+}
+
+void
+ise_destroy()
+{
+    if (g_package_manager) {
+        package_manager_destroy(g_package_manager);
+        g_package_manager = NULL;
+    }
+
+    if (g_web_helper_agent) {
+        g_web_helper_agent->exit();
+        CWebHelperAgent::destroy_web_helper_agent(g_web_helper_agent);
+    }
+
+    web_container_destroy();
+}
+
+void
+ise_attach_input_context(int ic)
+{
+    LOGD("attaching, ic : %x , %x , g_ic : %x , %x, g_focused_ic : %x , %x", ic, check_ic_temporary(ic),
+        g_keyboard_state.ic, check_ic_temporary(g_keyboard_state.ic),
+        g_keyboard_state.focused_ic, check_ic_temporary(g_keyboard_state.focused_ic));
+    ise_focus_in(ic);
+}
+
+void
+ise_detach_input_context(int ic)
+{
+    ise_focus_out(ic);
+}
+
+void
+ise_focus_in(int ic)
+{
+    LOGD("ic : %x , %x , g_ic : %x , %x, g_focused_ic : %x , %x", ic, check_ic_temporary(ic),
+        g_keyboard_state.ic, check_ic_temporary(g_keyboard_state.ic),
+        g_keyboard_state.focused_ic, check_ic_temporary(g_keyboard_state.focused_ic));
+    if (check_ic_temporary(g_keyboard_state.ic) && !check_ic_temporary(ic)) {
+        g_keyboard_state.ic = ic;
+    }
+    g_keyboard_state.focused_ic = ic;
+    if (ic == g_keyboard_state.ic) {
+        if (g_ise_common) {
+            if (g_keyboard_state.layout == ISE_LAYOUT_STYLE_PHONENUMBER ||
+                g_keyboard_state.layout == ISE_LAYOUT_STYLE_IP ||
+                g_keyboard_state.layout == ISE_LAYOUT_STYLE_MONTH ||
+                g_keyboard_state.layout == ISE_LAYOUT_STYLE_NUMBERONLY) {
+                    g_ise_common->set_keyboard_ise_by_uuid(DEFAULT_KEYBOARD_ISE_UUID);
+            } else {
+                g_ise_common->set_keyboard_ise_by_uuid(g_ise_common->get_keyboard_ise_uuid().c_str());
+            }
+        }
+    }
+    if (g_web_helper_agent) {
+        g_web_helper_agent->on_focus_in(ic);
+    }
+}
+
+void
+ise_focus_out(int ic)
+{
+    g_keyboard_state.focused_ic = 0;
+
+    if (g_web_helper_agent) {
+        g_web_helper_agent->on_focus_out(ic);
+    }
+}
+
+void
+ise_show(int ic)
+{
+    if (g_ise_common) {
+        LOGD("ic : %x , %x , g_ic : %x , %x, g_focused_ic : %x , %x", ic, check_ic_temporary(ic),
+            g_keyboard_state.ic, check_ic_temporary(g_keyboard_state.ic),
+            g_keyboard_state.focused_ic, check_ic_temporary(g_keyboard_state.focused_ic));
+        if (check_ic_temporary(ic) && !check_ic_temporary(g_keyboard_state.focused_ic)) {
+            ic = g_keyboard_state.focused_ic;
+        }
+        if (!check_ic_temporary(ic) && check_ic_temporary(g_keyboard_state.focused_ic)) {
+            g_keyboard_state.focused_ic = ic;
+        }
+        g_keyboard_state.ic = ic;
+
+        if (g_web_helper_agent) {
+            g_web_helper_agent->on_show(ic);
+        }
+
+        evas_object_show(g_ise_common->get_main_window());
+    }
+
+    g_keyboard_state.visible_state = TRUE;
+}
+
+void
+ise_hide(int ic)
+{
+    if (g_web_helper_agent) {
+        g_web_helper_agent->on_hide(ic);
+    }
+    evas_object_hide(g_ise_common->get_main_window());
+    g_keyboard_state.visible_state = FALSE;
+}
+
+/**
+ * Sets screen rotation
+ */
+void
+ise_set_screen_rotation(int degree)
+{
+    g_keyboard_state.angle = degree;
+    if (g_keyboard_state.angle == 90 || g_keyboard_state.angle == 270) {
+        web_container_resize(g_keyboard_state.landscape_width, g_keyboard_state.landscape_height);
+    } else {
+        web_container_resize(g_keyboard_state.portrait_width, g_keyboard_state.portrait_height);
+    }
+
+    if (g_web_helper_agent) {
+        g_web_helper_agent->on_set_rotation(degree);
+    }
+}
+
+void
+ise_update_cursor_position(int ic, int position)
+{
+    if (g_web_helper_agent) {
+        g_web_helper_agent->on_update_cursor_position(ic, position);
+    }
+}
+
+void
+ise_update_surrounding_text(int ic, const char *text, int cursor)
+{
+    if (g_web_helper_agent) {
+        g_web_helper_agent->on_update_surrounding_text(ic, text, cursor);
+    }
+}
+
+void
+ise_update_selection(int ic, const char *text)
+{
+    if (g_web_helper_agent) {
+        g_web_helper_agent->on_update_selection(ic, text);
+    }
+}
+
+void
+ise_set_language(unsigned int language)
+{
+    if (g_web_helper_agent) {
+        g_web_helper_agent->on_set_language(language);
+    }
+}
+
+void ise_set_imdata(char *buf, unsigned int len)
+{
+    if (g_web_helper_agent) {
+        g_web_helper_agent->on_set_imdata(buf, len);
+    }
+}
+
+void ise_get_imdata(char **buf, unsigned int *len)
+{
+    if (g_web_helper_agent) {
+        g_web_helper_agent->on_get_imdata(buf, len);
+        if (buf && len) {
+            if (*buf) {
+                LOGD("imdata : %s, %d", *buf, *len);
+            }
+        }
+    }
+}
+
+void ise_set_return_key_type(unsigned int type)
+{
+    if (g_web_helper_agent) {
+        g_web_helper_agent->on_set_return_key_type(type);
+    }
+}
+
+void ise_get_return_key_type(unsigned int *type)
+{
+    if (g_web_helper_agent) {
+        g_web_helper_agent->on_get_return_key_type(type);
+    }
+}
+
+void ise_set_return_key_disable(unsigned int disabled)
+{
+    if (g_web_helper_agent) {
+        g_web_helper_agent->on_set_return_key_type(disabled);
+    }
+}
+
+void ise_get_return_key_disable(unsigned int *disabled)
+{
+    if (g_web_helper_agent) {
+        g_web_helper_agent->on_get_return_key_type(disabled);
+    }
+}
+
+void
+ise_set_layout(unsigned int layout)
+{
+    /* Check if the layoutIdx is in the valid range */
+    if (layout < ISE_LAYOUT_STYLE_MAX) {
+        if (g_keyboard_state.layout != layout) {
+            g_keyboard_state.need_reset = TRUE;
+        }
+        g_keyboard_state.layout = layout;
+
+        if (g_web_helper_agent) {
+            g_web_helper_agent->on_set_layout(layout);
+        }
+    }
+}
+
+void
+ise_get_layout(unsigned int *layout)
+{
+    if (g_web_helper_agent) {
+        g_web_helper_agent->on_get_layout(layout);
+    }
+}
+
+void
+ise_reset_input_context(int ic)
+{
+    if (g_web_helper_agent) {
+        g_web_helper_agent->on_reset_input_context(ic);
+    }
+}
+
+
+void ise_process_key_event(unsigned int code, unsigned int mask, unsigned int layout, unsigned int *ret)
+{
+    if (g_web_helper_agent) {
+        g_web_helper_agent->on_process_key_event(code, mask, layout, ret);
+    }
+}
+
+void
+ise_reset_context()
+{
+}
+
+void
+ise_set_accessibility_state(int state)
+{
+}
+
+void ise_signal_handler(int sig)
+{
+    if (g_web_helper_agent) {
+        g_web_helper_agent->signal(sig);
+    }
+}
+
+void
+ise_set_caps_mode(unsigned int mode)
+{
+    if (mode) {
+        g_keyboard_state.caps_mode = TRUE;
+    } else {
+        g_keyboard_state.caps_mode = FALSE;
+    }
+}
+
+void ise_get_language_locale(int ic, char **locale)
+{
+}
+
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644 (file)
index 0000000..6c2fc30
--- /dev/null
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2012 - 2014 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 <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <Elementary.h>
+#include "common.h"
+#include "ise.h"
+
+using namespace scim;
+
+#include <Elementary.h>
+
+CISECommon *g_ise_common = NULL;
+
+extern KEYBOARD_STATE g_keyboard_state;
+
+class CCoreEventCallback : public IISECommonEventCallback
+{
+    void init();
+    void exit(int ic, const char *ic_uuid);
+
+    void attach_input_context(int ic, const char *ic_uuid);
+    void detach_input_context(int ic, const char *ic_uuid);
+
+    void focus_in(int ic, const char *ic_uuid);
+    void focus_out(int ic, const char *ic_uuid);
+
+    void ise_show(int ic, const int degree, Ise_Context &context);
+    void ise_hide(int ic, const char *ic_uuid);
+
+    void set_rotation_degree(int degree);
+
+    void update_cursor_position(int ic, const char *ic_uuid, int cursor_pos);
+    void update_surrounding_text(int ic, const char *text, int cursor);
+    void update_selection(int ic, const char *text);
+
+    void set_language(unsigned int language);
+
+    void set_imdata(char *buf, unsigned int len);
+    void get_imdata(char **buf, unsigned int *len);
+
+    void set_return_key_type(unsigned int type);
+    void get_return_key_type(unsigned int *type);
+
+    void set_return_key_disable(unsigned int disabled);
+    void get_return_key_disable(unsigned int *disabled);
+
+    void set_layout(unsigned int layout);
+    void get_layout(unsigned int *layout);
+
+    void reset_input_context(int ic, const char *uuid);
+
+    void process_key_event(unsigned int code, unsigned int mask, unsigned int layout, unsigned int *ret);
+
+    void set_display_language(const char *language);
+    void set_accessibility_state(const int state);
+
+    void set_caps_mode(int mode);
+
+    void get_language_locale(int ic, char **locale);
+
+    void signal_handler(int sig);
+};
+
+void CCoreEventCallback::init()
+{
+    LOGD("CCoreEventCallback::init()\n");
+    ise_create();
+}
+
+void CCoreEventCallback::exit(int ic, const char *ic_uuid)
+{
+    ::ise_hide(ic);
+    ise_destroy();
+}
+
+void CCoreEventCallback::attach_input_context(int ic, const char *ic_uuid)
+{
+    ise_attach_input_context(ic);
+}
+
+void CCoreEventCallback::detach_input_context(int ic, const char *ic_uuid)
+{
+    ise_detach_input_context(ic);
+}
+
+void CCoreEventCallback::focus_in(int ic, const char *ic_uuid)
+{
+    ise_focus_in(ic);
+}
+
+void CCoreEventCallback::focus_out(int ic, const char *ic_uuid)
+{
+    ise_focus_out(ic);
+}
+
+void CCoreEventCallback::ise_show(int ic, const int degree, Ise_Context &context)
+{
+    //g_ise_common->set_keyboard_ise_by_uuid(KEYBD_ISE_UUID);
+
+    ise_reset_context(); // reset ISE
+
+    /*if (context.language == ECORE_IMF_INPUT_PANEL_LANG_ALPHABET) {
+        ise_explictly_set_language(PRIMARY_LATIN_LANGUAGE_INDEX);
+    }*/
+
+    ise_set_layout(context.layout);
+
+    ise_set_return_key_type(context.return_key_type);
+    ise_set_return_key_disable(context.return_key_disabled);
+
+    ise_set_caps_mode(context.caps_mode);
+    ise_update_cursor_position(ic, context.cursor_pos);
+
+    /* Do not follow the application's rotation angle if we are already in visible state,
+       since in that case we will receive the angle through ROTATION_CHANGE_REQUEST message */
+    if (!(g_keyboard_state.visible_state)) {
+        ise_set_screen_rotation(degree);
+    } else {
+        LOGD("Skipping rotation angle , %d", degree);
+    }
+
+    ::ise_show(ic);
+}
+
+void CCoreEventCallback::ise_hide(int ic, const char *ic_uuid)
+{
+    ::ise_hide(ic);
+}
+
+void CCoreEventCallback::set_rotation_degree(int degree)
+{
+    ise_set_screen_rotation(degree);
+}
+
+void CCoreEventCallback::update_cursor_position(int ic, const char *ic_uuid, int cursor_pos)
+{
+    ise_update_cursor_position(ic, cursor_pos);
+}
+
+void CCoreEventCallback::update_surrounding_text(int ic, const char *text, int cursor)
+{
+    ise_update_surrounding_text(ic, text, cursor);
+}
+
+void CCoreEventCallback::update_selection(int ic, const char *text)
+{
+    ise_update_selection(ic, text);
+}
+
+void CCoreEventCallback::set_language(unsigned int language)
+{
+    ise_set_language(language);
+}
+
+void CCoreEventCallback::set_imdata(char *buf, unsigned int len)
+{
+    ise_set_imdata(buf, len);
+}
+
+void CCoreEventCallback::get_imdata(char **buf, unsigned int *len)
+{
+    ise_get_imdata(buf, len);
+}
+
+void CCoreEventCallback::set_return_key_type(unsigned int type)
+{
+    ise_set_return_key_type(type);
+}
+
+void CCoreEventCallback::get_return_key_type(unsigned int *type)
+{
+    ise_get_return_key_type(type);
+}
+
+void CCoreEventCallback::set_return_key_disable(unsigned int disabled)
+{
+    ise_set_return_key_disable(disabled);
+}
+
+void CCoreEventCallback::get_return_key_disable(unsigned int *disabled)
+{
+    ise_get_return_key_disable(disabled);
+}
+
+void CCoreEventCallback::set_layout(unsigned int layout)
+{
+    ise_set_layout(layout);
+}
+
+void CCoreEventCallback::get_layout(unsigned int *layout)
+{
+    ise_get_layout(layout);
+}
+
+void CCoreEventCallback::reset_input_context(int ic, const char *uuid)
+{
+    ise_reset_input_context(ic);
+}
+
+void CCoreEventCallback::process_key_event(unsigned int code, unsigned int mask, unsigned int layout, unsigned int *ret)
+{
+    ise_process_key_event(code, mask, layout, ret);
+}
+
+void CCoreEventCallback::set_display_language(const char *language)
+{
+    setlocale(LC_ALL, language);
+    bindtextdomain(PACKAGE, LOCALEDIR);
+    textdomain(PACKAGE);
+
+    LOGD("Language : %s\n", (language ? language : "NULL"));
+}
+
+void CCoreEventCallback::set_accessibility_state(const int state)
+{
+    ise_set_accessibility_state(state);
+}
+
+void CCoreEventCallback::set_caps_mode(int mode)
+{
+    ise_set_caps_mode(mode);
+}
+
+void CCoreEventCallback::signal_handler(int sig)
+{
+    ise_signal_handler(sig);
+}
+
+void CCoreEventCallback::get_language_locale(int ic, char **locale)
+{
+    ise_get_language_locale(ic, locale);
+}
+
+static CCoreEventCallback g_core_event_callback;
+
+extern "C"
+{
+    void scim_module_init(void) {
+        if (g_ise_common == NULL) {
+            g_ise_common = CISECommon::get_instance();
+        }
+        if  (g_ise_common) {
+            g_ise_common->init();
+            g_ise_common->set_core_event_callback(&g_core_event_callback);
+        }
+    }
+
+    void scim_module_exit(void) {
+        if (g_ise_common) {
+            g_ise_common->exit();
+
+            g_ise_common = NULL;
+        }
+    }
+
+    unsigned int scim_helper_module_number_of_helpers(void) {
+        if (g_ise_common) {
+            return g_ise_common->get_number_of_helpers();
+        }
+        return 0;
+    }
+
+    bool scim_helper_module_get_helper_info(unsigned int idx, HelperInfo &info) {
+        if (g_ise_common) {
+            return g_ise_common->get_helper_info(idx, info);
+        }
+        return false;
+    }
+
+    String scim_helper_module_get_helper_language(unsigned int idx) {
+        if (g_ise_common) {
+            return g_ise_common->get_helper_language(idx);
+        }
+        return String("");
+    }
+
+    void scim_helper_module_run_helper(const String &uuid, const ConfigPointer &config, const String &display) {
+        if (g_ise_common) {
+            g_ise_common->run(uuid.c_str(), config, display.c_str());
+        }
+    }
+}
+
diff --git a/src/packages.cpp b/src/packages.cpp
new file mode 100644 (file)
index 0000000..e81cb10
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2012 - 2014 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 <stdio.h>
+#include <string.h>
+#include <dlog.h>
+#include <pkgmgr-info.h>
+
+#include "packages.h"
+
+#define ISEUUID "1373647e-5d53-4019-b810-ed068e44873c"
+#define ISENAME "Web Keyboard Container"
+
+CPackages* CPackages::m_instance = NULL; /* For singleton */
+static std::vector<HelperInfoEx> helper_infos;
+
+int app_list_cb(pkgmgrinfo_appinfo_h handle, void *user_data)
+{
+    int ret;
+    char *app_id = NULL;
+    char *pkg_id = NULL, *pkg_label = NULL, *pkg_type = NULL, *pkg_root_path = NULL, *pkg_icon_path = NULL;
+    pkgmgrinfo_appinfo_h appinfo_handle = NULL;
+    pkgmgrinfo_pkginfo_h pkginfo_handle = NULL;
+    HelperInfoEx helper_info_ex;
+
+    /* Get appid */
+    ret = pkgmgrinfo_appinfo_get_appid(handle, &app_id);
+    if (ret != PMINFO_R_OK)
+        return 0;
+
+    ret = pkgmgrinfo_appinfo_get_appinfo(app_id, &appinfo_handle);
+    if (ret != PMINFO_R_OK)
+        return 0;
+
+    /* Get package id */
+    ret = pkgmgrinfo_appinfo_get_pkgname(appinfo_handle, &pkg_id);
+    if (ret != PMINFO_R_OK) {
+        pkgmgrinfo_appinfo_destroy_appinfo(appinfo_handle);
+        return 0;
+    }
+
+    /* Get package info handle */
+    ret = pkgmgrinfo_pkginfo_get_pkginfo(pkg_id, &pkginfo_handle);
+    if (ret != PMINFO_R_OK) {
+        pkgmgrinfo_appinfo_destroy_appinfo(appinfo_handle);
+        return 0;
+    }
+
+    /* Get the type of package */
+    ret = pkgmgrinfo_pkginfo_get_type(pkginfo_handle, &pkg_type);
+    if (ret != PMINFO_R_OK) {
+        pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_handle);
+        pkgmgrinfo_appinfo_destroy_appinfo(appinfo_handle);
+        return 0;
+    }
+
+    if (pkg_type && !strncmp(pkg_type, "wgt", 3)) {
+        // FIXME : need to get UUID
+        helper_info_ex.helper_info.uuid = scim::String(app_id);
+
+        /* Get the label of package */
+        if (pkgmgrinfo_pkginfo_get_label(pkginfo_handle, &pkg_label) == PMINFO_R_OK)
+            helper_info_ex.helper_info.name = scim::String(pkg_label);
+
+        /* Get the icon path of package */
+        if (pkgmgrinfo_pkginfo_get_icon(pkginfo_handle, &pkg_icon_path) == PMINFO_R_OK)
+            helper_info_ex.helper_info.icon = scim::String(pkg_icon_path);
+
+        // FIXME : fill the helper option from package or app information
+        helper_info_ex.helper_info.option = scim::SCIM_HELPER_STAND_ALONE | scim::SCIM_HELPER_NEED_SCREEN_INFO |
+            scim::SCIM_HELPER_NEED_SPOT_LOCATION_INFO | scim::SCIM_HELPER_AUTO_RESTART;
+
+        // FIXME : fill the input language from package or app information
+        helper_info_ex.supported_languages = scim::String("en_US");
+
+        /* Get the root path of package */
+        if (pkgmgrinfo_pkginfo_get_root_path(pkginfo_handle, &pkg_root_path) == PMINFO_R_OK)
+            helper_info_ex.application_path = scim::String("file://") + scim::String(pkg_root_path) + scim::String("/res/wgt/index.html");
+
+        helper_infos.push_back(helper_info_ex);
+    }
+
+    pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_handle);
+    pkgmgrinfo_appinfo_destroy_appinfo(appinfo_handle);
+
+    return 0;
+}
+
+CPackages* CPackages::get_instance()
+{
+    if (!m_instance) {
+        m_instance = new CPackages();
+    }
+    return (CPackages*)m_instance;
+}
+
+void
+CPackages::init()
+{
+    /* Collect web keyboards' information here */
+    int ret = 0;
+    pkgmgrinfo_appinfo_filter_h handle;
+    ret = pkgmgrinfo_appinfo_filter_create(&handle);
+    if (ret != PMINFO_R_OK)
+        return;
+
+    ret = pkgmgrinfo_appinfo_filter_add_string(handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime");
+    if (ret == PMINFO_R_OK) {
+        pkgmgrinfo_appinfo_filter_foreach_appinfo(handle, app_list_cb, NULL);
+    }
+
+    pkgmgrinfo_appinfo_filter_destroy(handle);
+}
+
+void
+CPackages::fini()
+{
+
+}
+
+int
+CPackages::get_number_of_packages()
+{
+    return helper_infos.size();
+}
+
+HelperInfoEx
+CPackages::get_package_information_by_index(int index)
+{
+    HelperInfoEx ret;
+    if (index >= 0 && index < (int)helper_infos.size()) {
+        ret = helper_infos.at(index);
+    }
+    return ret;
+}
+
+HelperInfoEx
+CPackages::get_package_information_by_uuid(scim::String uuid)
+{
+    HelperInfoEx ret;
+    for (int loop = 0;loop < (int)helper_infos.size();loop++) {
+        if (helper_infos.at(loop).helper_info.uuid.compare(uuid) == 0) {
+            ret = helper_infos.at(loop);
+        }
+    }
+    return ret;
+}
diff --git a/src/web_container.cpp b/src/web_container.cpp
new file mode 100644 (file)
index 0000000..895b39b
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2012 - 2014 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 <dlfcn.h>
+
+#include <dlog.h>
+
+#include "web_container.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "ISE_WEB_HELPER_AGENT"
+
+static void *_plugin_handle = NULL;
+
+bool web_container_create(Evas_Object *window, HelperInfoEx info, web_container_loaded_cb callback)
+{
+    bool ret = false;
+    if (_plugin_handle == NULL) {
+        _plugin_handle = dlopen(WEB_CONTAINER_PLUGIN_PATH, RTLD_NOW);
+        if (_plugin_handle) {
+            ret = true;
+        } else {
+            LOGD("dlopen failed : %s %s", WEB_CONTAINER_PLUGIN_PATH, dlerror());
+        }
+    }
+
+    if (ret) {
+        web_container_create_api api =
+            (web_container_create_api)dlsym(_plugin_handle, WEB_CONTAINER_CREATE_API);
+        char *result = dlerror();
+        if (result) {
+            LOGD("dlsym failed : %s %s", WEB_CONTAINER_CREATE_API, result);
+        } else {
+            if (api)
+                api(window, info, callback);
+        }
+    }
+
+    return ret;
+}
+
+bool web_container_destroy()
+{
+    bool ret = false;
+    if (_plugin_handle) {
+        web_container_destroy_api api =
+            (web_container_destroy_api)dlsym(_plugin_handle, WEB_CONTAINER_DESTROY_API);
+        char *result = dlerror();
+        if (result) {
+            LOGD("dlsym failed : %s %s", WEB_CONTAINER_DESTROY_API, result);
+        } else {
+            if (api)
+                api();
+        }
+
+        dlclose(_plugin_handle);
+        _plugin_handle = NULL;
+        ret = true;
+    }
+    return ret;
+}
+
+bool web_container_resize(int width, int height)
+{
+    bool ret = false;
+    if (_plugin_handle) {
+        web_container_resize_api api =
+            (web_container_resize_api)dlsym(_plugin_handle, WEB_CONTAINER_RESIZE_API);
+        char *result = dlerror();
+        if (result) {
+            LOGD("dlsym failed : %s %s", WEB_CONTAINER_RESIZE_API, result);
+        } else {
+            if (api)
+                api(width, height);
+        }
+
+        ret = true;
+    }
+    return ret;
+}
+
+bool web_container_javascript(const char *command, web_container_javascript_cb callback)
+{
+    bool ret = false;
+    if (_plugin_handle) {
+        web_container_javascript_api api =
+            (web_container_javascript_api)dlsym(_plugin_handle, WEB_CONTAINER_JAVASCRIPT_API);
+        char *result = dlerror();
+        if (result) {
+            LOGD("dlsym failed : %s %s", WEB_CONTAINER_JAVASCRIPT_API, result);
+        } else {
+            if (api)
+                api(command, callback);
+        }
+
+        ret = true;
+    }
+    return ret;
+}
diff --git a/src/web_container_plugin.cpp b/src/web_container_plugin.cpp
new file mode 100644 (file)
index 0000000..609ac6c
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2012 - 2014 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 "web_container.h"
+
+#include <dlog.h>
+#include <Evas.h>
+
+#include <EWebKit.h>
+
+#include <i_runnable_widget_object.h>
+#include <core_module.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "ISF_WEB_CONTAINER"
+
+typedef std::shared_ptr<WRT::IRunnableWidgetObject> WrtCorePtr;
+
+static WrtCorePtr _pWrt;
+static Evas_Object *_pCurrentWebView = NULL;
+
+static web_container_loaded_cb _loaded_callback = NULL;
+
+static void web_container_loaded(Evas_Object* webview, void* eventInfo)
+{
+    if (_loaded_callback) {
+        _loaded_callback();
+    }
+}
+
+static void ewk_javascript_callback(Evas_Object* webview, const char* result_value, void* user_data)
+{
+    if (user_data) {
+        web_container_javascript_cb callback = (web_container_javascript_cb)user_data;
+        callback(result_value);
+    }
+}
+
+bool web_container_create(Evas_Object *window, HelperInfoEx info, web_container_loaded_cb callback)
+{
+    bool ret = false;
+
+    WRT::CoreModuleSingleton::Instance().Init();
+
+    WrtCorePtr wrt;
+    /* FIXME : we need appid instead of uuid here */
+    wrt = WRT::CoreModuleSingleton::Instance().getRunnableWidgetObject(info.helper_info.uuid);
+    if (wrt) {
+        LOGD("Loading URL : %s, %d", info.application_path.c_str(),
+            wrt->PrepareView(info.application_path.c_str(), window, NULL));
+
+#ifdef _WEARABLE
+        wrt->CheckBeforeLaunch();
+#endif
+
+        WRT::UserDelegatesPtr cbs(new WRT::UserDelegates);
+        using namespace std::placeholders;
+        _loaded_callback = callback;
+        cbs->loadFinishedCallback = std::bind(web_container_loaded, _1, _2);
+        wrt->SetUserDelegates(cbs);
+
+        _pCurrentWebView = wrt->GetCurrentWebview();
+
+        _pWrt = wrt;
+        _pWrt->Show();
+
+        ret = true;
+    }
+
+    return ret;
+}
+
+bool web_container_destroy()
+{
+    bool ret = false;
+
+    if (_pWrt) {
+        ret = true;
+        _pWrt->Hide();
+    }
+    _pWrt.reset();
+
+    WRT::CoreModuleSingleton::Instance().Terminate();
+
+    return ret;
+}
+
+bool web_container_resize(int width, int height)
+{
+    bool ret = false;
+
+    if (_pCurrentWebView) {
+        evas_object_resize(_pCurrentWebView, width, height);
+        evas_object_move(_pCurrentWebView, 0, 0);
+        evas_object_show(_pCurrentWebView);
+        ret = true;
+    }
+
+    return ret;
+}
+
+bool web_container_javascript(const char *command, web_container_javascript_cb callback)
+{
+    bool ret = false;
+
+    if (_pCurrentWebView) {
+        if (ewk_view_script_execute(_pCurrentWebView, command, ewk_javascript_callback, (void*)callback) == EINA_FALSE) {
+            LOGW("Failed while executing command : %s", command);
+        }
+        ret = true;
+    }
+
+    return ret;
+}
+
+/* API conformance checking */
+static web_container_create_api create_api_test = web_container_create;
+static web_container_destroy_api destroy_api_test = web_container_destroy;
+static web_container_resize_api resize_api_test = web_container_resize;
+static web_container_javascript_api javascript_api_test = web_container_javascript;
diff --git a/src/web_helper_agent.cpp b/src/web_helper_agent.cpp
new file mode 100644 (file)
index 0000000..6b6ee2a
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2012 - 2014 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 <stdio.h>
+#include <dlog.h>
+
+#include "web_helper_agent.h"
+
+#include "ise.h"
+
+#include "websocket.h"
+#include "direct.h"
+
+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;
+    } else if (type == WEB_HELPER_AGENT_DIRECT) {
+        ret = new CWebHelperAgentDirect;
+    }
+    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)
+{
+    ise_log(str);
+}
+
+void CWebHelperAgent::commit_string(const char *str)
+{
+    ise_send_string(str);
+}
+
+void CWebHelperAgent::update_preedit_string(const char *str)
+{
+    ise_update_preedit_string(str);
+}
+
+void CWebHelperAgent::send_key_event(unsigned int key, unsigned int key_mask)
+{
+    ise_send_event(key, key_mask);
+}
+
+void CWebHelperAgent::forward_key_event(unsigned int key)
+{
+    ise_forward_key_event(key);
+}
+
+void CWebHelperAgent::set_keyboard_sizes(int portrait_width, int portrait_height, int landscape_width, int landscape_height)
+{
+    ise_set_keyboard_size_hints(portrait_width, portrait_height, landscape_width, landscape_height);
+}
+
+void CWebHelperAgent::set_selection(int start_index, int end_index)
+{
+    ise_set_selection(start_index, end_index);
+}
+
+void CWebHelperAgent::get_selection()
+{
+    ise_get_selection();
+}
+
+void CWebHelperAgent::get_surrounding_text(int maxlen_before, int maxlen_after)
+{
+    ise_get_surrounding_text(maxlen_before, maxlen_after);
+}
+
+void CWebHelperAgent::delete_surrounding_text(int offset, int len)
+{
+    ise_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/web_helper_agents/direct.cpp b/src/web_helper_agents/direct.cpp
new file mode 100644 (file)
index 0000000..083d49c
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012 - 2014 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 "direct.h"
+
+#include "ise.h"
+
+CWebHelperAgentDirect::CWebHelperAgentDirect()
+{
+
+}
+
+CWebHelperAgentDirect::~CWebHelperAgentDirect()
+{
+
+}
+
+bool CWebHelperAgentDirect::init()
+{
+    return true;
+}
+
+bool CWebHelperAgentDirect::exit()
+{
+    return true;
+}
+
+void CWebHelperAgentDirect::signal( int sig )
+{
+
+}
diff --git a/src/web_helper_agents/direct.h b/src/web_helper_agents/direct.h
new file mode 100644 (file)
index 0000000..a52307e
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012 - 2014 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_DIRECT_H_
+#define _WEB_HELPER_AGENT_DIRECT_H_
+
+#include "web_helper_agent.h"
+
+class CWebHelperAgentDirect : public CWebHelperAgent {
+public:
+    CWebHelperAgentDirect();
+    virtual ~CWebHelperAgentDirect();
+
+    bool init();
+    bool exit();
+
+    void signal(int sig);
+};
+
+#endif // _WEB_HELPER_AGENT_DIRECT_H_
\ No newline at end of file
diff --git a/src/web_helper_agents/websocket.cpp b/src/web_helper_agents/websocket.cpp
new file mode 100644 (file)
index 0000000..82fb95c
--- /dev/null
@@ -0,0 +1,930 @@
+/*
+ * Copyright (c) 2012 - 2014 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <Ecore.h>
+#include <dlog.h>
+
+#include "ise.h"
+#include "websocket.h"
+
+#include <syslog.h>
+#include <signal.h>
+
+#include <libwebsockets.h>
+
+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 libwebsocket_context *g_ws_server_context = NULL;
+
+CWebHelperAgentWebSocket* CWebHelperAgentWebSocket::m_current_instance = NULL;
+
+int force_exit = 0;
+
+enum demo_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 libwebsocket_context *context,
+        struct libwebsocket *wsi,
+        enum libwebsocket_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 libwebsocket_context *context,
+        struct libwebsocket *wsi,
+        enum libwebsocket_callback_reasons reason,
+        void *user, void *in, size_t len);
+
+static struct libwebsocket_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 libwebsocket_context *context,
+        struct libwebsocket *wsi,
+        enum libwebsocket_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 : %d", pss->session_id);
+        pss->valid = false;
+        libwebsocket_callback_on_writable_all_protocol(&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 transmission only if this client is guaranteed to be valid */
+            if (pss->valid) {
+                pthread_mutex_lock(&g_ws_server_mutex);
+                std::queue<ISE_MESSAGE>& 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 = libwebsocket_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;
+                }
+            }
+
+            if (pss->valid) {
+                pthread_mutex_lock(&g_ws_server_mutex);
+                std::queue<ISE_MESSAGE>& 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);
+
+        libwebsocket_service(g_ws_server_context, 50);
+    }
+    return NULL;
+}
+
+void log_func(int level, const char *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;
+#ifndef LWS_NO_EXTENSIONS
+    info.extensions = libwebsocket_get_internal_extensions();
+#endif
+    info.ssl_cert_filepath = NULL;
+    info.ssl_private_key_filepath = NULL;
+    info.gid = -1;
+    info.uid = -1;
+    info.options = 0;
+
+    /* 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 = libwebsocket_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) {
+        libwebsocket_context_destroy(g_ws_server_context);
+        g_ws_server_context = NULL;
+    }
+
+    return true;
+}
+
+void CWebHelperAgentWebSocket::signal(int sig)
+{
+    force_exit = 1;
+}
+
+template<class T>
+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);
+
+    libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_KEYBOARD]);
+}
+
+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);
+
+    libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_KEYBOARD]);
+}
+
+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);
+
+    libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_KEYBOARD]);
+}
+
+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);
+
+    libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_KEYBOARD]);
+}
+
+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);
+
+    libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_KEYBOARD]);
+
+    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);
+
+    libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_KEYBOARD]);
+}
+
+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);
+
+    libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_KEYBOARD]);
+}
+
+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);
+
+    libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_KEYBOARD]);
+}
+
+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);
+
+    libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_KEYBOARD]);
+}
+
+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);
+
+    libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_KEYBOARD]);
+}
+
+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);
+
+        libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_KEYBOARD]);
+    }
+}
+
+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);
+
+    libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_KEYBOARD]);
+}
+
+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);
+
+    libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_KEYBOARD]);
+
+    wait_for_reply_message();
+
+    std::vector<std::string> 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);
+
+        libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_KEYBOARD]);
+    }
+}
+
+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);
+
+    libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_KEYBOARD]);
+
+    wait_for_reply_message();
+
+    /* Since we are accessing recved buffer, lock the server mutex again */
+    pthread_mutex_lock(&g_ws_server_mutex);
+    std::vector<std::string> 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);
+
+        libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_KEYBOARD]);
+    }
+}
+
+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);
+
+    libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_KEYBOARD]);
+
+    wait_for_reply_message();
+
+    /* Since we are accessing recved buffer, lock the server mutex again */
+    pthread_mutex_lock(&g_ws_server_mutex);
+    std::vector<std::string> 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);
+
+        libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_KEYBOARD]);
+    }
+}
+
+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);
+
+    libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_KEYBOARD]);
+
+    wait_for_reply_message();
+
+    /* Since we are accessing recved buffer, lock the server mutex again */
+    pthread_mutex_lock(&g_ws_server_mutex);
+    std::vector<std::string> 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);
+
+    libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_KEYBOARD]);
+}
+
+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);
+
+    libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_KEYBOARD]);
+
+    wait_for_reply_message();
+
+    /* Since we are accessing recved buffer, lock the server mutex again */
+    pthread_mutex_lock(&g_ws_server_mutex);
+    std::vector<std::string> 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<ISE_MESSAGE>& CWebHelperAgentWebSocket::get_send_message_queue()
+{
+    return m_send_message_queue;
+}
+
+std::queue<ISE_MESSAGE>& 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<std::string> &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 (int loop = 0;loop < (int)message.values.size();loop++) {
+            str += message.values.at(loop).c_str();
+            if (loop < (int)message.values.size() - 1) {
+                str += " ";
+            }
+        }
+        log(str.c_str());
+    }
+    else 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 (int loop = 0;loop < (int)message.values.size();loop++) {
+            str += message.values.at(loop).c_str();
+            if (loop < (int)message.values.size() - 1) {
+                str += " ";
+            }
+        }
+        commit_string(str.c_str());
+    }
+    else if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_UPDATE_PREEDIT_STRING]) == 0) {
+        std::string str = "";
+        for (int loop = 0;loop < (int)message.values.size();loop++) {
+            str += message.values.at(loop).c_str();
+            if (loop < (int)message.values.size() - 1) {
+                str += " ";
+            }
+        }
+        update_preedit_string(str.c_str());
+    }
+    else 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);
+        }
+    }
+    else 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()));
+        }
+    }
+    else 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()));
+        }
+    }
+    else if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_SELECTION]) == 0) {
+        if (message.values.size() == 0) {
+            get_selection();
+        }
+    }
+    else 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()));
+        }
+    }
+    else 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()));
+        }
+    }
+    else if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_LOGIN]) == 0) {
+        libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_KEYBOARD]);
+    }
+}
diff --git a/src/web_helper_agents/websocket.h b/src/web_helper_agents/websocket.h
new file mode 100644 (file)
index 0000000..58d470a
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2012 - 2014 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 <queue>
+
+/* 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<std::string> 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<std::string> 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<ISE_MESSAGE>& get_send_message_queue();
+    std::queue<ISE_MESSAGE>& 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<std::string> &values);
+    void handle_recved_message(ISE_MESSAGE &message);
+
+    static CWebHelperAgentWebSocket* get_current_instance();
+protected:
+    static CWebHelperAgentWebSocket *m_current_instance;
+
+    std::queue<ISE_MESSAGE> m_send_message_queue;
+    std::queue<ISE_MESSAGE> m_recv_message_queue;
+
+    Ecore_Pipe *m_recv_message_pipe;
+};
+
+#endif // _WEB_HELPER_AGENT_WEBSOCKET_H_