merge with master
[framework/osp/ime.git] / src / FUiIme_InputMethodImpl.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file        FUiIme_InputMethodImpl.cpp
20  * @brief       This is the implementation file for the %_InputMethodImpl class.
21  *
22  * This implementation file contains definition of the %_InputMethodImpl class.
23  */
24
25 #include <new>
26 #include <unique_ptr.h>
27
28 #include <Ecore_IMF.h>
29 #include <Ecore_X.h> // ecore_x_icccm_hints_get
30 #include <Elementary.h> // elm_win_keyboard_win_set
31
32 #include <FBaseSysLog.h>
33 #include <FBase_StringConverter.h>
34
35 #include "FUi_EcoreEvas.h"
36 #include "FUi_EcoreEvasMgr.h"
37
38 #include "FUiIme_EcoreEventHandler.h"
39 #include "FUiIme_EcoreFdHandler.h"
40 #include "FUiIme_ImeInfo.h"
41 #include "FUiIme_InputMethodImpl.h"
42 #include "FUiIme_InputServiceSignalListener.h"
43 #include "FUiIme_ScimDataConverter.h"
44
45 using namespace Tizen::Base;
46 using namespace Tizen::Graphics;
47 using namespace Tizen::Ui;
48
49 namespace Tizen { namespace Ui { namespace Ime {
50
51 _InputMethodImpl::_InputMethodImpl(void)
52         :__pHelperAgent(null)
53         ,__pEcoreEventHandler(null)
54         ,__pEcoreFdHandler(null)
55         ,__pInputServiceBinder(null)
56 {
57 }
58
59 _InputMethodImpl::~_InputMethodImpl(void)
60 {
61         __pHelperAgent = null;
62
63         if (__pEcoreEventHandler)
64         {
65                 __pEcoreEventHandler->Deactivate();
66                 __pEcoreEventHandler = null;
67         }
68
69         if (__pEcoreFdHandler)
70         {
71                 __pEcoreFdHandler->Deactivate();
72                 __pEcoreFdHandler = null;
73         }
74
75         if (__pInputServiceBinder)
76         {
77                 __pInputServiceBinder->Unbind();
78                 __pInputServiceBinder = null;
79         }
80 }
81
82 result
83 _InputMethodImpl::Construct(void)
84 {
85         result r = E_SUCCESS;
86
87         __pInputServiceBinder = _InputServiceBinder::GetInstance();
88         r = GetLastResult();
89         SysTryReturnResult(NID_UI_IME, __pInputServiceBinder, r, "Propagating.");
90
91         BindingId bindingId = -1;
92         bindingId = __pInputServiceBinder->Bind();
93         r = GetLastResult();
94         SysTryCatch(NID_UI_IME, bindingId > -1, , r, "[%s] Propagating.", GetErrorMessage(r));
95
96         __pHelperAgent = __pInputServiceBinder->GetHelperAgent();
97
98         SetInputServiceSignalCallback();
99
100         r = SetEcoreEvasAttribute();
101         SysTryCatch(NID_UI_IME, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
102
103         __pEcoreEventHandler = _EcoreEventHandler::GetInstance();
104         r = GetLastResult();
105         SysTryCatch(NID_UI_IME, __pEcoreEventHandler, , r, "[%s] Propagating.", GetErrorMessage(r));
106
107         r = __pEcoreEventHandler->Activate();
108         SysTryCatch(NID_UI_IME, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
109
110         __pEcoreFdHandler = _EcoreFdHandler::GetInstance(bindingId, *__pHelperAgent);
111         r = GetLastResult();
112         SysTryCatch(NID_UI_IME, __pEcoreFdHandler, , r, "[%s] Propagating.", GetErrorMessage(r));
113
114         r = __pEcoreFdHandler->Activate();
115         SysTryCatch(NID_UI_IME, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
116
117         return r;
118
119 CATCH:
120         __pInputServiceBinder->Unbind();
121         __pInputServiceBinder = null;
122
123         __pHelperAgent = null;
124
125         if (__pEcoreEventHandler)
126         {
127                 __pEcoreEventHandler->Deactivate();
128                 __pEcoreEventHandler = null;
129         }
130
131         if (__pEcoreFdHandler)
132         {
133                 __pEcoreFdHandler->Deactivate();
134                 __pEcoreFdHandler = null;
135         }
136
137         return r;
138 }
139
140 _InputMethodImpl*
141 _InputMethodImpl::GetInstance(InputMethod& inputMethod)
142 {
143         return inputMethod.__pInputMethodImpl;
144 }
145
146 void
147 _InputMethodImpl::SetInputMethodProvider(IInputMethodProvider* pProvider)
148 {
149         _InputServiceSignalListener::SetInputMethodProvider(pProvider);
150 }
151
152 void
153 _InputMethodImpl::SetInputMethodListener(IInputMethodListener* pListener)
154 {
155         _InputServiceSignalListener::SetInputMethodListener(pListener);
156 }
157
158 result
159 _InputMethodImpl::DeleteText(int cursorOffset, int length)
160 {
161         SysTryReturnResult(NID_UI_IME, length > 0, E_INVALID_ARG, "Invalid argument(s) is used. The length is not greater than 0.");
162
163         result r = E_SUCCESS;
164
165         __pHelperAgent->delete_surrounding_text(cursorOffset, length);
166
167         return r;
168 }
169
170 result
171 _InputMethodImpl::NotifyInputPanelState(InputPanelShowState state)
172 {
173         SysTryReturnResult(NID_UI_IME, (state == INPUT_PANEL_SHOW_STATE_SHOW) || (state == INPUT_PANEL_SHOW_STATE_HIDE), E_INVALID_ARG,
174                                         "Invalid argument(s) is used. The state is beyond the scope.");
175
176         result r = E_SUCCESS;
177
178         Ecore_IMF_Input_Panel_State inputPanelState;
179
180         switch (state)
181         {
182         case INPUT_PANEL_SHOW_STATE_SHOW:
183                 inputPanelState = ECORE_IMF_INPUT_PANEL_STATE_SHOW;
184                 break;
185         case INPUT_PANEL_SHOW_STATE_HIDE:
186                 inputPanelState = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
187                 break;
188         default:
189                 break;
190         }
191
192         __pHelperAgent->update_input_context(ECORE_IMF_INPUT_PANEL_STATE_EVENT, inputPanelState);
193
194         return r;
195 }
196
197 result
198 _InputMethodImpl::NotifyLanguageChanged(void)
199 {
200         result r = E_SUCCESS;
201
202         __pHelperAgent->update_input_context(ECORE_IMF_INPUT_PANEL_LANGUAGE_EVENT, 0);
203
204         return r;
205 }
206
207 result
208 _InputMethodImpl::RequestSurroundingText(int lengthBeforeCursor, int lengthAfterCursor)
209 {
210         SysTryReturnResult(NID_UI_IME, (lengthBeforeCursor >= 0) && (lengthAfterCursor >= 0), E_INVALID_ARG,
211                         "[E_INVALID_ARG] Invalid argument(s) is used. The length is not greater than or equal to 0.");
212
213         result r = E_SUCCESS;
214
215         _ImeInfo* pImeInfo = _ImeInfo::GetInstance();
216         scim::String uuid = pImeInfo->GetUuid();
217
218         __pHelperAgent->get_surrounding_text(uuid, lengthBeforeCursor, lengthAfterCursor);
219
220         return r;
221 }
222
223 result
224 _InputMethodImpl::SendCompositeText(const String& text)
225 {
226         result r = E_SUCCESS;
227
228         scim::WideString compositeText;
229         r = _ScimDataConverter::ConvertString(text, compositeText);
230         SysTryReturnResult(NID_UI_IME, r == E_SUCCESS, r, "Propagating.");
231
232         scim::AttributeList attributeList;
233         __pHelperAgent->update_preedit_string(-1, "", compositeText, attributeList);
234
235         return r;
236 }
237
238 result
239 _InputMethodImpl::SendKeyEvent(KeyCode code, KeyState state)
240 {
241         SysTryReturnResult(NID_UI_IME, (code > KEY_INVALID) && (code < KEY_HARDWARE_MAX), E_INVALID_ARG,
242                                         "Invalid argument(s) is used. The key code is beyond the scope.");
243         SysTryReturnResult(NID_UI_IME, (state >= KEY_PRESSED) && (state <= KEY_LONGPRESSED), E_INVALID_ARG,
244                                         "Invalid argument(s) is used. The key state is beyond the scope.");
245
246         result r = E_SUCCESS;
247
248         scim::KeyEvent keyEvent;
249         _ScimDataConverter::ConvertKey(code, state, keyEvent);
250         __pHelperAgent->forward_key_event(-1, "", keyEvent);
251
252         return r;
253 }
254
255 result
256 _InputMethodImpl::SendText(const String& text)
257 {
258         result r = E_SUCCESS;
259
260         scim::String scimText;
261         r = _ScimDataConverter::ConvertString(text, scimText);
262         SysTryReturnResult(NID_UI_IME, r == E_SUCCESS, r, "Propagating.");
263
264         scim::WideString wideString = scim::utf8_mbstowcs(scimText);
265
266         __pHelperAgent->commit_string(-1, "", wideString);
267
268         return r;
269 }
270
271 result
272 _InputMethodImpl::SetEcoreEvasAttribute(void)
273 {
274         result r = E_SUCCESS;
275
276         _EcoreEvasMgr* pEcoreEvasMgr = null;
277         pEcoreEvasMgr = GetEcoreEvasMgr();
278         r = GetLastResult();
279         SysTryReturnResult(NID_UI_IME, pEcoreEvasMgr, r, "Propagating.");
280
281         _EcoreEvas* pEcoreEvas = null;
282         pEcoreEvas = pEcoreEvasMgr->GetEcoreEvas();
283         r = GetLastResult();
284         SysTryReturnResult(NID_UI_IME, pEcoreEvas, r, "Propagating.");
285
286         elm_win_keyboard_win_set(pEcoreEvas->GetWindowObject(), EINA_TRUE);
287
288         Eina_Bool accepts_focus = EINA_TRUE;
289         Ecore_X_Window_State_Hint initial_state = ECORE_X_WINDOW_STATE_HINT_NONE;
290         Ecore_X_Pixmap icon_pixmap = 0;
291         Ecore_X_Pixmap icon_mask = 0;
292         Ecore_X_Window icon_window = 0;
293         Ecore_X_Window window_group = 0;
294         Eina_Bool is_urgent = EINA_FALSE;
295
296         Eina_Bool result = EINA_FALSE;
297         result = ecore_x_icccm_hints_get(pEcoreEvas->GetXWindow(), &accepts_focus, &initial_state, &icon_pixmap, &icon_mask, &icon_window, &window_group, &is_urgent);
298         SysTryReturnResult(NID_UI_IME, result == EINA_TRUE, E_SYSTEM, "A failure occurs from the underlying system.");
299
300         ecore_x_icccm_hints_set(pEcoreEvas->GetXWindow(), EINA_FALSE, initial_state, icon_pixmap, icon_mask, icon_window, window_group, is_urgent);
301
302         return r;
303 }
304
305 void
306 _InputMethodImpl::SetInputServiceSignalCallback(void)
307 {
308         __pHelperAgent->signal_connect_get_geometry(scim::slot(_InputServiceSignalListener::GetInputPanelBounds));
309         __pHelperAgent->signal_connect_get_layout(scim::slot(_InputServiceSignalListener::GetInputPanelStyle));
310         __pHelperAgent->signal_connect_get_language_locale(scim::slot(_InputServiceSignalListener::GetLanguage));
311         __pHelperAgent->signal_connect_get_return_key_disable(scim::slot(_InputServiceSignalListener::IsEnterKeyActionEnabled));
312         __pHelperAgent->signal_connect_get_return_key_type(scim::slot(_InputServiceSignalListener::GetEnterKeyAction));
313
314         __pHelperAgent->signal_connect_set_caps_mode(scim::slot(_InputServiceSignalListener::SetCapsModeEnabled));
315         __pHelperAgent->signal_connect_set_language(scim::slot(_InputServiceSignalListener::SetLanguage));
316         __pHelperAgent->signal_connect_set_layout(scim::slot(_InputServiceSignalListener::SetInputPanelStyle));
317         __pHelperAgent->signal_connect_set_return_key_disable(scim::slot(_InputServiceSignalListener::SetEnterKeyActionEnabled));
318         __pHelperAgent->signal_connect_set_return_key_type(scim::slot(_InputServiceSignalListener::SetEnterKeyAction));
319
320         __pHelperAgent->signal_connect_exit(scim::slot(_InputServiceSignalListener::OnTerminate));
321         __pHelperAgent->signal_connect_ise_hide(scim::slot(_InputServiceSignalListener::HideInputPanel));
322         __pHelperAgent->signal_connect_ise_show(scim::slot(_InputServiceSignalListener::ShowInputPanel));
323         __pHelperAgent->signal_connect_update_cursor_position(scim::slot(_InputServiceSignalListener::OnCursorPositionChanged));
324         __pHelperAgent->signal_connect_update_surrounding_text(scim::slot(_InputServiceSignalListener::OnSurroundingTextReceived));
325
326         SysLog(NID_UI_IME, "The signal callback functions of the input service have been set");
327 }
328
329 void
330 _InputMethodImpl::HideInputPanel(void)
331 {
332         _EcoreEvasMgr* pEcoreEvasMgr = null;
333         pEcoreEvasMgr = GetEcoreEvasMgr();
334         SysTryReturnVoidResult(NID_UI_IME, pEcoreEvasMgr, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] The required instance does not exist.");
335
336         _EcoreEvas* pEcoreEvas = null;
337         pEcoreEvas = pEcoreEvasMgr->GetEcoreEvas();
338         SysTryReturnVoidResult(NID_UI_IME, pEcoreEvas, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] The required instance does not exist.");
339
340         Evas_Object* pEvasObject = null;
341         pEvasObject = pEcoreEvas->GetWindowObject();
342         SysTryReturnVoidResult(NID_UI_IME, pEvasObject, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] The required instance does not exist.");
343
344         if (evas_object_visible_get(pEvasObject))
345         {
346                 evas_object_hide(pEvasObject);
347         }
348 }
349
350 void
351 _InputMethodImpl::ShowInputPanel(void)
352 {
353         _EcoreEvasMgr* pEcoreEvasMgr = null;
354         pEcoreEvasMgr = GetEcoreEvasMgr();
355         SysTryReturnVoidResult(NID_UI_IME, pEcoreEvasMgr, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] The required instance does not exist.");
356
357         _EcoreEvas* pEcoreEvas = null;
358         pEcoreEvas = pEcoreEvasMgr->GetEcoreEvas();
359         SysTryReturnVoidResult(NID_UI_IME, pEcoreEvas, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] The required instance does not exist.");
360
361         Evas_Object* pEvasObject = null;
362         pEvasObject = pEcoreEvas->GetWindowObject();
363         SysTryReturnVoidResult(NID_UI_IME, pEvasObject, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] The required instance does not exist.");
364
365         if (evas_object_visible_get(pEvasObject) == false)
366         {
367                 evas_object_show(pEvasObject);
368         }
369 }
370
371 }}} // Tizen::Ui::Ime