2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
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
9 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 * @file FUiIme_InputMethodImpl.cpp
20 * @brief This is the implementation file for the %_InputMethodImpl class.
22 * This implementation file contains definition of the %_InputMethodImpl class.
26 #include <unique_ptr.h>
28 #include <Ecore_IMF.h>
29 #include <Ecore_X.h> // ecore_x_icccm_hints_get
30 #include <Elementary.h> // elm_win_keyboard_win_set
32 #include <FBaseSysLog.h>
33 #include <FGrpCoordinateSystem.h>
35 #include <FBase_StringConverter.h>
37 #include "FUi_EcoreEvas.h"
38 #include "FUi_EcoreEvasMgr.h"
40 #include "FUiIme_EcoreEventHandler.h"
41 #include "FUiIme_EcoreFdHandler.h"
42 #include "FUiIme_ImeInfo.h"
43 #include "FUiIme_InputMethodImpl.h"
44 #include "FUiIme_InputServiceSignalListener.h"
45 #include "FUiIme_ScimDataConverter.h"
47 using namespace Tizen::Base;
48 using namespace Tizen::Graphics;
49 using namespace Tizen::Ui;
51 namespace Tizen { namespace Ui { namespace Ime {
53 _InputMethodImpl::_InputMethodImpl(void)
55 ,__pEcoreEventHandler(null)
56 ,__pEcoreFdHandler(null)
57 ,__pInputServiceBinder(null)
61 _InputMethodImpl::~_InputMethodImpl(void)
63 __pHelperAgent = null;
65 if (__pEcoreEventHandler)
67 __pEcoreEventHandler->Deactivate();
68 __pEcoreEventHandler = null;
71 if (__pEcoreFdHandler)
73 __pEcoreFdHandler->Deactivate();
74 __pEcoreFdHandler = null;
77 if (__pInputServiceBinder)
79 __pInputServiceBinder->Unbind();
80 __pInputServiceBinder = null;
85 _InputMethodImpl::Construct(void)
89 __pInputServiceBinder = _InputServiceBinder::GetInstance();
91 SysTryReturnResult(NID_UI_IME, __pInputServiceBinder, r, "Propagating.");
93 BindingId bindingId = -1;
94 bindingId = __pInputServiceBinder->Bind();
96 SysTryCatch(NID_UI_IME, bindingId > -1, , r, "[%s] Propagating.", GetErrorMessage(r));
98 __pHelperAgent = __pInputServiceBinder->GetHelperAgent();
100 SetInputServiceSignalCallback();
102 r = SetInputPanelWindowAttribute();
103 SysTryCatch(NID_UI_IME, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
105 __pEcoreEventHandler = _EcoreEventHandler::GetInstance();
107 SysTryCatch(NID_UI_IME, __pEcoreEventHandler, , r, "[%s] Propagating.", GetErrorMessage(r));
109 r = __pEcoreEventHandler->Activate();
110 SysTryCatch(NID_UI_IME, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
112 __pEcoreFdHandler = _EcoreFdHandler::GetInstance(bindingId, *__pHelperAgent);
114 SysTryCatch(NID_UI_IME, __pEcoreFdHandler, , r, "[%s] Propagating.", GetErrorMessage(r));
116 r = __pEcoreFdHandler->Activate();
117 SysTryCatch(NID_UI_IME, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
122 __pInputServiceBinder->Unbind();
123 __pInputServiceBinder = null;
125 __pHelperAgent = null;
127 if (__pEcoreEventHandler)
129 __pEcoreEventHandler->Deactivate();
130 __pEcoreEventHandler = null;
133 if (__pEcoreFdHandler)
135 __pEcoreFdHandler->Deactivate();
136 __pEcoreFdHandler = null;
143 _InputMethodImpl::GetInstance(InputMethod& inputMethod)
145 return inputMethod.__pInputMethodImpl;
149 _InputMethodImpl::SetInputMethodProvider(IInputMethodProvider* pProvider)
151 _InputServiceSignalListener::SetInputMethodProvider(pProvider);
155 _InputMethodImpl::SetInputMethodProviderF(IInputMethodProviderF* pProvider)
157 _InputServiceSignalListener::SetInputMethodProviderF(pProvider);
161 _InputMethodImpl::SetInputMethodListener(IInputMethodListener* pListener)
163 _InputServiceSignalListener::SetInputMethodListener(pListener);
167 _InputMethodImpl::DeleteText(int cursorOffset, int length)
169 SysTryReturnResult(NID_UI_IME, length > 0, E_INVALID_ARG, "Invalid argument(s) is used. The length is not greater than 0.");
171 result r = E_SUCCESS;
173 __pHelperAgent->delete_surrounding_text(cursorOffset, length);
179 _InputMethodImpl::NotifyInputPanelBounds(const Tizen::Graphics::FloatRectangle& portraitBounds, const Tizen::Graphics::FloatRectangle& landscapeBounds)
181 result r = E_SUCCESS;
183 _EcoreEvasMgr* pEcoreEvasMgr = null;
184 pEcoreEvasMgr = GetEcoreEvasMgr();
186 SysTryReturnResult(NID_UI_IME, pEcoreEvasMgr, r, "Propagating.");
188 _EcoreEvas* pEcoreEvas = null;
189 pEcoreEvas = pEcoreEvasMgr->GetEcoreEvas();
191 SysTryReturnResult(NID_UI_IME, pEcoreEvas, r, "Propagating.");
193 Ecore_X_Window inputPanelWindow = pEcoreEvas->GetXWindow();
195 float width = CoordinateSystem::ConvertToPhysicalX(portraitBounds.width);
196 float height = CoordinateSystem::ConvertToPhysicalY(portraitBounds.height);
197 ecore_x_e_window_rotation_geometry_set(inputPanelWindow, 0, 0, 0, static_cast<int>(width), static_cast<int>(height));
198 ecore_x_e_window_rotation_geometry_set(inputPanelWindow, 180, 0, 0, static_cast<int>(width), static_cast<int>(height));
200 // give the size information according to the screen coordinates; the width should be replaced with the height and the reverse should be done in the same way
201 width = CoordinateSystem::ConvertToPhysicalX(landscapeBounds.width);
202 height = CoordinateSystem::ConvertToPhysicalY(landscapeBounds.height);
203 ecore_x_e_window_rotation_geometry_set(inputPanelWindow, 90, 0, 0, static_cast<int>(height), static_cast<int>(width));
204 ecore_x_e_window_rotation_geometry_set(inputPanelWindow, 270, 0, 0, static_cast<int>(height), static_cast<int>(width));
210 _InputMethodImpl::NotifyInputPanelState(InputPanelShowState state)
212 SysTryReturnResult(NID_UI_IME, (state == INPUT_PANEL_SHOW_STATE_SHOW) || (state == INPUT_PANEL_SHOW_STATE_HIDE), E_INVALID_ARG,
213 "Invalid argument(s) is used. The state is beyond the scope.");
215 result r = E_SUCCESS;
217 Ecore_IMF_Input_Panel_State inputPanelState;
221 case INPUT_PANEL_SHOW_STATE_SHOW:
222 inputPanelState = ECORE_IMF_INPUT_PANEL_STATE_SHOW;
224 case INPUT_PANEL_SHOW_STATE_HIDE:
225 inputPanelState = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
231 __pHelperAgent->update_input_context(ECORE_IMF_INPUT_PANEL_STATE_EVENT, inputPanelState);
237 _InputMethodImpl::NotifyLanguageChanged(void)
239 result r = E_SUCCESS;
241 __pHelperAgent->update_input_context(ECORE_IMF_INPUT_PANEL_LANGUAGE_EVENT, 0);
247 _InputMethodImpl::RequestSurroundingText(int lengthBeforeCursor, int lengthAfterCursor)
249 SysTryReturnResult(NID_UI_IME, (lengthBeforeCursor >= 0) && (lengthAfterCursor >= 0), E_INVALID_ARG,
250 "[E_INVALID_ARG] Invalid argument(s) is used. The length is not greater than or equal to 0.");
252 result r = E_SUCCESS;
254 _ImeInfo* pImeInfo = _ImeInfo::GetInstance();
255 scim::String uuid = pImeInfo->GetUuid();
257 __pHelperAgent->get_surrounding_text(uuid, lengthBeforeCursor, lengthAfterCursor);
263 _InputMethodImpl::SendCompositeText(const String& text)
265 result r = E_SUCCESS;
267 scim::WideString compositeText;
268 r = _ScimDataConverter::ConvertString(text, compositeText);
269 SysTryReturnResult(NID_UI_IME, r == E_SUCCESS, r, "Propagating.");
271 scim::AttributeList attributeList;
272 __pHelperAgent->update_preedit_string(-1, "", compositeText, attributeList);
278 _InputMethodImpl::SendKeyEvent(KeyCode code, KeyState state)
280 SysTryReturnResult(NID_UI_IME, (code > KEY_INVALID) && (code < KEY_HARDWARE_MAX), E_INVALID_ARG,
281 "Invalid argument(s) is used. The key code is beyond the scope.");
282 SysTryReturnResult(NID_UI_IME, (state >= KEY_PRESSED) && (state <= KEY_LONGPRESSED), E_INVALID_ARG,
283 "Invalid argument(s) is used. The key state is beyond the scope.");
285 result r = E_SUCCESS;
287 scim::KeyEvent keyEvent;
288 _ScimDataConverter::ConvertKey(code, state, keyEvent);
289 __pHelperAgent->forward_key_event(-1, "", keyEvent);
295 _InputMethodImpl::SendText(const String& text)
297 result r = E_SUCCESS;
299 scim::String scimText;
300 r = _ScimDataConverter::ConvertString(text, scimText);
301 SysTryReturnResult(NID_UI_IME, r == E_SUCCESS, r, "Propagating.");
303 scim::WideString wideString = scim::utf8_mbstowcs(scimText);
305 __pHelperAgent->commit_string(-1, "", wideString);
311 _InputMethodImpl::SetInputPanelWindowAttribute(void)
313 result r = E_SUCCESS;
315 _EcoreEvasMgr* pEcoreEvasMgr = null;
316 pEcoreEvasMgr = GetEcoreEvasMgr();
318 SysTryReturnResult(NID_UI_IME, pEcoreEvasMgr, r, "Propagating.");
320 _EcoreEvas* pEcoreEvas = null;
321 pEcoreEvas = pEcoreEvasMgr->GetEcoreEvas();
323 SysTryReturnResult(NID_UI_IME, pEcoreEvas, r, "Propagating.");
325 elm_win_keyboard_win_set(pEcoreEvas->GetWindowObject(), EINA_TRUE);
327 // for supporting rotation sync
328 Ecore_X_Window inputPanelWindow = elm_win_xwindow_get(pEcoreEvas->GetWindowObject());
329 SysLog(NID_UI_IME, "The handle of the input panel window is %x.", inputPanelWindow);
330 unsigned int value = 1;
331 ecore_x_window_prop_card32_set(inputPanelWindow, ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED, &value, 1);
334 const int _MAX_BUFFER_SIZE = 256;
335 char xId[_MAX_BUFFER_SIZE];
336 memset(xId, '\0', _MAX_BUFFER_SIZE);
337 snprintf(xId, _MAX_BUFFER_SIZE, "%d", inputPanelWindow);
338 scim::Property property(xId, "XID", "", "");
339 scim::PropertyList propertyList;
340 propertyList.push_back(property);
341 __pHelperAgent->register_properties(propertyList);
343 // set x window class name
344 ecore_x_icccm_name_class_set(inputPanelWindow, "Virtual Keyboard", "ISF");
346 // set hints in order not to get window focus
347 Eina_Bool accepts_focus = EINA_TRUE;
348 Ecore_X_Window_State_Hint initial_state = ECORE_X_WINDOW_STATE_HINT_NONE;
349 Ecore_X_Pixmap icon_pixmap = 0;
350 Ecore_X_Pixmap icon_mask = 0;
351 Ecore_X_Window icon_window = 0;
352 Ecore_X_Window window_group = 0;
353 Eina_Bool is_urgent = EINA_FALSE;
355 Eina_Bool result = EINA_FALSE;
356 result = ecore_x_icccm_hints_get(pEcoreEvas->GetXWindow(), &accepts_focus, &initial_state, &icon_pixmap, &icon_mask, &icon_window, &window_group, &is_urgent);
357 SysTryReturnResult(NID_UI_IME, result == EINA_TRUE, E_SYSTEM, "A failure occurs from the underlying system.");
359 ecore_x_icccm_hints_set(pEcoreEvas->GetXWindow(), EINA_FALSE, initial_state, icon_pixmap, icon_mask, icon_window, window_group, is_urgent);
365 _InputMethodImpl::SetInputServiceSignalCallback(void)
367 __pHelperAgent->signal_connect_get_geometry(scim::slot(_InputServiceSignalListener::GetInputPanelBounds));
368 __pHelperAgent->signal_connect_get_layout(scim::slot(_InputServiceSignalListener::GetInputPanelStyle));
369 __pHelperAgent->signal_connect_get_language_locale(scim::slot(_InputServiceSignalListener::GetLanguage));
370 __pHelperAgent->signal_connect_get_return_key_disable(scim::slot(_InputServiceSignalListener::IsEnterKeyActionEnabled));
371 __pHelperAgent->signal_connect_get_return_key_type(scim::slot(_InputServiceSignalListener::GetEnterKeyAction));
373 __pHelperAgent->signal_connect_set_caps_mode(scim::slot(_InputServiceSignalListener::SetCapsModeEnabled));
374 __pHelperAgent->signal_connect_set_language(scim::slot(_InputServiceSignalListener::SetLanguage));
375 __pHelperAgent->signal_connect_set_layout(scim::slot(_InputServiceSignalListener::SetInputPanelStyle));
376 __pHelperAgent->signal_connect_set_return_key_disable(scim::slot(_InputServiceSignalListener::SetEnterKeyActionEnabled));
377 __pHelperAgent->signal_connect_set_return_key_type(scim::slot(_InputServiceSignalListener::SetEnterKeyAction));
379 __pHelperAgent->signal_connect_ise_hide(scim::slot(_InputServiceSignalListener::HideInputPanel));
380 __pHelperAgent->signal_connect_ise_show(scim::slot(_InputServiceSignalListener::ShowInputPanel));
382 __pHelperAgent->signal_connect_update_cursor_position(scim::slot(_InputServiceSignalListener::OnCursorPositionChanged));
383 __pHelperAgent->signal_connect_set_imdata(scim::slot(_InputServiceSignalListener::OnOpaqueCommandReceived));
384 __pHelperAgent->signal_connect_update_surrounding_text(scim::slot(_InputServiceSignalListener::OnSurroundingTextReceived));
386 __pHelperAgent->signal_connect_exit(scim::slot(_InputServiceSignalListener::OnTerminate));
388 SysLog(NID_UI_IME, "The signal callback functions of the input service have been set");
392 _InputMethodImpl::HideInputPanel(void)
394 _EcoreEvasMgr* pEcoreEvasMgr = null;
395 pEcoreEvasMgr = GetEcoreEvasMgr();
396 SysTryReturnVoidResult(NID_UI_IME, pEcoreEvasMgr, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] The required instance does not exist.");
398 _EcoreEvas* pEcoreEvas = null;
399 pEcoreEvas = pEcoreEvasMgr->GetEcoreEvas();
400 SysTryReturnVoidResult(NID_UI_IME, pEcoreEvas, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] The required instance does not exist.");
402 Evas_Object* pEvasObject = null;
403 pEvasObject = pEcoreEvas->GetWindowObject();
404 SysTryReturnVoidResult(NID_UI_IME, pEvasObject, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] The required instance does not exist.");
406 if (evas_object_visible_get(pEvasObject))
408 evas_object_hide(pEvasObject);
413 _InputMethodImpl::ShowInputPanel(void)
415 _EcoreEvasMgr* pEcoreEvasMgr = null;
416 pEcoreEvasMgr = GetEcoreEvasMgr();
417 SysTryReturnVoidResult(NID_UI_IME, pEcoreEvasMgr, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] The required instance does not exist.");
419 _EcoreEvas* pEcoreEvas = null;
420 pEcoreEvas = pEcoreEvasMgr->GetEcoreEvas();
421 SysTryReturnVoidResult(NID_UI_IME, pEcoreEvas, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] The required instance does not exist.");
423 Evas_Object* pEvasObject = null;
424 pEvasObject = pEcoreEvas->GetWindowObject();
425 SysTryReturnVoidResult(NID_UI_IME, pEvasObject, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] The required instance does not exist.");
427 if (evas_object_visible_get(pEvasObject) == false)
429 evas_object_show(pEvasObject);
433 }}} // Tizen::Ui::Ime