Tizen 2.1 base
[platform/framework/native/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
27 #include <Ecore_IMF.h>
28 #include <Ecore_X.h> // ecore_x_icccm_hints_get
29 #include <Elementary.h> // elm_win_keyboard_win_set
30
31 #include <FBaseSysLog.h>
32 #include <FBase_StringConverter.h>
33
34 #include "FUi_EcoreEvas.h"
35 #include "FUi_EcoreEvasMgr.h"
36
37 #include "FUiIme_EcoreFdHandler.h"
38 #include "FUiIme_ImeInfo.h"
39 #include "FUiIme_InputMethodImpl.h"
40 #include "FUiIme_InputServiceSignalListener.h"
41 #include "FUiIme_ScimDataConverter.h"
42
43 using namespace Tizen::Base;
44 using namespace Tizen::Graphics;
45 using namespace Tizen::Locales;
46 using namespace Tizen::Ui;
47
48 namespace Tizen { namespace Ui { namespace Ime {
49
50 _InputMethodImpl* _InputMethodImpl::__pInputMethodImpl = null;
51
52 _InputMethodImpl::_InputMethodImpl(void)
53         :__pHelperAgent(null)
54         ,__pInputMethod(null)
55         ,__pEcoreFdHandler(null)
56         ,__pInputServiceBinder(null)
57         ,__pInputServiceSignalListener(null)
58         ,__pScimDataConverter(null)
59 {
60 }
61
62 _InputMethodImpl::~_InputMethodImpl(void)
63 {
64         __pInputMethodImpl = null;
65         __pHelperAgent = null;
66         __pInputMethod = null;
67
68         if (__pEcoreFdHandler)
69         {
70                 __pEcoreFdHandler->Deactivate();
71                 __pEcoreFdHandler = null;
72         }
73
74         if (__pInputServiceBinder)
75         {
76                 __pInputServiceBinder->Unbind();
77                 __pInputServiceBinder = null;
78         }
79
80         delete __pInputServiceSignalListener;
81         __pInputServiceSignalListener = null;
82
83         delete __pScimDataConverter;
84         __pScimDataConverter = null;
85 }
86
87 result
88 _InputMethodImpl::Construct(InputMethod& inputMethod)
89 {
90         result r = E_SUCCESS;
91
92         __pInputServiceBinder = _InputServiceBinder::GetInstance();
93         r = GetLastResult();
94         SysTryReturnResult(NID_UI_IME, __pInputServiceBinder, r, "Propagating.");
95
96         BindingId bindingId = -1;
97         bindingId = __pInputServiceBinder->Bind();
98         r = GetLastResult();
99         SysTryCatch(NID_UI_IME, bindingId > -1, , r, "[%s] Propagating.", GetErrorMessage(r));
100
101         __pHelperAgent = __pInputServiceBinder->GetHelperAgent();
102         __pInputMethod = &inputMethod;
103
104         __pInputServiceSignalListener = new(std::nothrow) _InputServiceSignalListener();
105         SysTryCatch(NID_UI_IME, __pInputServiceSignalListener, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
106
107         __pScimDataConverter = new(std::nothrow) _ScimDataConverter();
108         SysTryCatch(NID_UI_IME, __pScimDataConverter, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
109
110         SetInputServiceSignalCallback();
111
112         r = SetEcoreEvasAttribute();
113         SysTryCatch(NID_UI_IME, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
114
115         __pEcoreFdHandler = _EcoreFdHandler::GetInstance(bindingId, *__pHelperAgent);
116         r = GetLastResult();
117         SysTryCatch(NID_UI_IME, __pEcoreFdHandler, , r, "[%s] Propagating.", GetErrorMessage(r));
118
119         r = __pEcoreFdHandler->Activate();
120         SysTryCatch(NID_UI_IME, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
121
122         return r;
123
124 CATCH:
125         __pInputServiceBinder->Unbind();
126         __pInputServiceBinder = null;
127
128         __pHelperAgent = null;
129         __pInputMethod = null;
130
131         delete __pInputServiceSignalListener;
132         __pInputServiceSignalListener = null;
133
134         delete __pScimDataConverter;
135         __pScimDataConverter = null;
136
137         if (__pEcoreFdHandler)
138         {
139                 __pEcoreFdHandler->Deactivate();
140                 __pEcoreFdHandler = null;
141         }
142
143         return r;
144 }
145
146 _InputMethodImpl*
147 _InputMethodImpl::GetInstance(InputMethod& inputMethod)
148 {
149         result r = E_SUCCESS;
150
151         if (!__pInputMethodImpl)
152         {
153                 __pInputMethodImpl = new(std::nothrow) _InputMethodImpl();
154                 SysTryReturn(NID_UI_IME, __pInputMethodImpl, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
155                 
156                 r = __pInputMethodImpl->Construct(inputMethod);
157                 SysTryCatch(NID_UI_IME, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
158         }
159
160         return __pInputMethodImpl;
161
162 CATCH:
163         delete __pInputMethodImpl;
164         __pInputMethodImpl = null;
165
166         return null;
167 }
168
169 void
170 _InputMethodImpl::SetInputMethodProvider(IInputMethodProvider* pProvider)
171 {
172         __pInputServiceSignalListener->SetInputMethodProvider(pProvider);
173
174         return;
175 }
176
177 void
178 _InputMethodImpl::SetInputMethodListener(IInputMethodListener* pListener)
179 {
180         __pInputServiceSignalListener->SetInputMethodListener(pListener);
181
182         return;
183 }
184
185 result
186 _InputMethodImpl::DeleteText(int cursorOffset, int length)
187 {
188         SysTryReturnResult(NID_UI_IME, length > 0, E_INVALID_ARG, "Invalid argument(s) is used. The length is not greater than 0.");
189
190         result r = E_SUCCESS;
191
192         __pHelperAgent->delete_surrounding_text(cursorOffset, length);
193
194         return r;
195 }
196
197 result
198 _InputMethodImpl::NotifyInputPanelState(InputPanelShowState state)
199 {
200         SysTryReturnResult(NID_UI_IME, (state == INPUT_PANEL_SHOW_STATE_SHOW) || (state == INPUT_PANEL_SHOW_STATE_HIDE), E_INVALID_ARG,
201                                         "Invalid argument(s) is used. The state is beyond the scope.");
202
203         result r = E_SUCCESS;
204
205         Ecore_IMF_Input_Panel_State inputPanelState;
206
207         switch (state)
208         {
209         case INPUT_PANEL_SHOW_STATE_SHOW:
210                 inputPanelState = ECORE_IMF_INPUT_PANEL_STATE_SHOW;
211                 break;
212         case INPUT_PANEL_SHOW_STATE_HIDE:
213                 inputPanelState = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
214                 break;
215         default:
216                 break;
217         }
218
219         __pHelperAgent->update_input_context(ECORE_IMF_INPUT_PANEL_STATE_EVENT, inputPanelState);
220
221         return r;
222 }
223
224 result
225 _InputMethodImpl::RequestSurroundingText(int lengthBeforeCursor, int lengthAfterCursor)
226 {
227         SysTryReturnResult(NID_UI_IME, (lengthBeforeCursor >= 0) && (lengthAfterCursor >= 0), E_INVALID_ARG,
228                         "[E_INVALID_ARG] Invalid argument(s) is used. The length is not greater than or equal to 0.");
229
230         result r = E_SUCCESS;
231
232         _ImeInfo* pImeInfo = _ImeInfo::GetInstance();
233         scim::String uuid = pImeInfo->GetUuid();
234
235         __pHelperAgent->get_surrounding_text(uuid, lengthBeforeCursor, lengthAfterCursor);
236
237         return r;
238 }
239
240 result
241 _InputMethodImpl::SendCompositeText(const Tizen::Base::String& text)
242 {
243         result r = E_SUCCESS;
244
245         scim::WideString compositeText;
246         r = __pScimDataConverter->ConvertString(text, compositeText);
247         SysTryReturnResult(NID_UI_IME, r == E_SUCCESS, r, "Propagating.");
248
249         scim::AttributeList attributeList;
250         __pHelperAgent->update_preedit_string(-1, "", compositeText, attributeList);
251
252         return r;
253 }
254
255 result
256 _InputMethodImpl::SendKeyEvent(Tizen::Ui::KeyCode code, Tizen::Ui::KeyState state)
257 {
258         SysTryReturnResult(NID_UI_IME, (code > KEY_INVALID) && (code < KEY_HARDWARE_MAX), E_INVALID_ARG,
259                                         "Invalid argument(s) is used. The key code is beyond the scope.");
260         SysTryReturnResult(NID_UI_IME, (state >= KEY_PRESSED) && (state <= KEY_LONGPRESSED), E_INVALID_ARG,
261                                         "Invalid argument(s) is used. The key state is beyond the scope.");
262
263         result r = E_SUCCESS;
264
265         scim::KeyEvent keyEvent;
266         __pScimDataConverter->ConvertKey(code, state, keyEvent);
267         __pHelperAgent->forward_key_event(-1, "", keyEvent);
268
269         return r;
270 }
271
272 result
273 _InputMethodImpl::SendText(const Tizen::Base::String& text)
274 {
275         result r = E_SUCCESS;
276
277         scim::String scimText;
278         r = __pScimDataConverter->ConvertString(text, scimText);
279         SysTryReturnResult(NID_UI_IME, r == E_SUCCESS, r, "Propagating.");
280
281         scim::WideString wideString = scim::utf8_mbstowcs(scimText);
282
283         __pHelperAgent->commit_string(-1, "", wideString);
284
285         return r;
286 }
287
288 bool
289 _InputMethodImpl::HasPendingEvent(void) const
290 {
291         return __pHelperAgent->has_pending_event();
292 }
293
294 result
295 _InputMethodImpl::ProcessPendingEvent(void)
296 {
297         result r = E_SUCCESS;
298
299         bool bound = false;
300
301         bound = __pHelperAgent->filter_event();
302         SysTryReturnResult(NID_UI_IME, bound == true, E_HOST_NOT_FOUND, "The destination host is not found.");
303
304         return r;
305 }
306
307 result
308 _InputMethodImpl::SetEcoreEvasAttribute(void)
309 {
310         result r = E_SUCCESS;
311
312         _EcoreEvasMgr* pEcoreEvasMgr = null;
313         pEcoreEvasMgr = GetEcoreEvasMgr();
314         r = GetLastResult();
315         SysTryReturnResult(NID_UI_IME, pEcoreEvasMgr, r, "Propagating.");
316
317         _EcoreEvas* pEcoreEvas = null;
318         pEcoreEvas = pEcoreEvasMgr->GetEcoreEvas();
319         r = GetLastResult();
320         SysTryReturnResult(NID_UI_IME, pEcoreEvas, r, "Propagating.");
321
322         elm_win_keyboard_win_set(pEcoreEvas->GetWindowObject(), EINA_TRUE);
323
324         Eina_Bool accepts_focus = EINA_TRUE;
325         Ecore_X_Window_State_Hint initial_state = ECORE_X_WINDOW_STATE_HINT_NONE;
326         Ecore_X_Pixmap icon_pixmap = 0;
327         Ecore_X_Pixmap icon_mask = 0;
328         Ecore_X_Window icon_window = 0;
329         Ecore_X_Window window_group = 0;
330         Eina_Bool is_urgent = EINA_FALSE;
331
332         Eina_Bool result = EINA_FALSE;
333         result = ecore_x_icccm_hints_get(pEcoreEvas->GetXWindow(), &accepts_focus, &initial_state, &icon_pixmap, &icon_mask, &icon_window, &window_group, &is_urgent);
334         SysTryReturnResult(NID_UI_IME, result == EINA_TRUE, E_SYSTEM, "A failure occurs from the underlying system.");
335
336         ecore_x_icccm_hints_set(pEcoreEvas->GetXWindow(), EINA_FALSE, initial_state, icon_pixmap, icon_mask, icon_window, window_group, is_urgent);
337
338         return r;
339 }
340
341 void
342 _InputMethodImpl::SetInputServiceSignalCallback(void)
343 {
344         __pHelperAgent->signal_connect_exit(scim::slot(_InputServiceSignalListener::OnTerminate));
345         __pHelperAgent->signal_connect_get_geometry(scim::slot(_InputServiceSignalListener::GetInputPanelBounds));
346         __pHelperAgent->signal_connect_ise_hide(scim::slot(_InputServiceSignalListener::HideInputPanel));
347         __pHelperAgent->signal_connect_ise_show(scim::slot(_InputServiceSignalListener::ShowInputPanel));
348         __pHelperAgent->signal_connect_update_cursor_position(scim::slot(_InputServiceSignalListener::OnCursorPositionChanged));
349         __pHelperAgent->signal_connect_update_surrounding_text(scim::slot(_InputServiceSignalListener::OnSurroundingTextReceived));
350         __pHelperAgent->signal_connect_set_language(scim::slot(_InputServiceSignalListener::SetLanguage));
351         __pHelperAgent->signal_connect_set_return_key_type(scim::slot(_InputServiceSignalListener::SetEnterKeyAction));
352         __pHelperAgent->signal_connect_get_return_key_type(scim::slot(_InputServiceSignalListener::GetEnterKeyAction));
353         __pHelperAgent->signal_connect_set_return_key_disable(scim::slot(_InputServiceSignalListener::SetEnterKeyActionEnabled));
354         __pHelperAgent->signal_connect_get_return_key_disable(scim::slot(_InputServiceSignalListener::IsEnterKeyActionEnabled));
355         __pHelperAgent->signal_connect_get_layout(scim::slot(_InputServiceSignalListener::GetInputPanelStyle));
356         __pHelperAgent->signal_connect_set_layout(scim::slot(_InputServiceSignalListener::SetInputPanelStyle));
357         __pHelperAgent->signal_connect_set_caps_mode(scim::slot(_InputServiceSignalListener::SetCapsModeEnabled));
358
359         SysLog(NID_UI_IME, "The signal callback functions of the input service have been set");
360
361         return;
362 }
363
364 void
365 _InputMethodImpl::HideInputPanel(void)
366 {
367         _EcoreEvasMgr* pEcoreEvasMgr = null;
368         pEcoreEvasMgr = GetEcoreEvasMgr();
369         SysTryReturnVoidResult(NID_UI_IME, pEcoreEvasMgr, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] The required instance does not exist.");
370
371         _EcoreEvas* pEcoreEvas = null;
372         pEcoreEvas = pEcoreEvasMgr->GetEcoreEvas();
373         SysTryReturnVoidResult(NID_UI_IME, pEcoreEvas, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] The required instance does not exist.");
374
375         Evas_Object* pEvasObject = null;
376         pEvasObject = pEcoreEvas->GetWindowObject();
377         SysTryReturnVoidResult(NID_UI_IME, pEvasObject, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] The required instance does not exist.");
378
379         if (evas_object_visible_get(pEvasObject))
380         {
381                 evas_object_hide(pEvasObject);
382         }
383
384         return;
385 }
386
387 void
388 _InputMethodImpl::ShowInputPanel(void)
389 {
390         _EcoreEvasMgr* pEcoreEvasMgr = null;
391         pEcoreEvasMgr = GetEcoreEvasMgr();
392         SysTryReturnVoidResult(NID_UI_IME, pEcoreEvasMgr, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] The required instance does not exist.");
393
394         _EcoreEvas* pEcoreEvas = null;
395         pEcoreEvas = pEcoreEvasMgr->GetEcoreEvas();
396         SysTryReturnVoidResult(NID_UI_IME, pEcoreEvas, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] The required instance does not exist.");
397
398         Evas_Object* pEvasObject = null;
399         pEvasObject = pEcoreEvas->GetWindowObject();
400         SysTryReturnVoidResult(NID_UI_IME, pEvasObject, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] The required instance does not exist.");
401
402         if (evas_object_visible_get(pEvasObject) == false)
403         {
404                 evas_object_show(pEvasObject);
405         }
406
407         return;
408 }
409
410 }}} // Tizen::Ui::Ime