[Tizen] Add DALi Autofill implementation
[platform/core/uifw/dali-adaptor.git] / dali / internal / input / tizen-wayland / input-method-context-impl-ecore-wl.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19
20 #include <dali/internal/input/tizen-wayland/input-method-context-impl-ecore-wl.h>
21
22 // EXTERNAL INCLUDES
23 #include <Ecore_Input.h>
24
25 #ifdef ECORE_WAYLAND2
26 #include <Ecore_Wl2.h>
27 #else
28 #include <Ecore_Wayland.h>
29 #endif
30
31 #include <dali/devel-api/common/singleton-service.h>
32 #include <dali/integration-api/debug.h>
33 #include <dali/public-api/adaptor-framework/key.h>
34 #include <dali/public-api/events/key-event.h>
35 #include <dali/public-api/object/type-registry.h>
36
37 // INTERNAL INCLUDES
38 #include <dali/integration-api/adaptor-framework/adaptor.h>
39 #include <dali/integration-api/adaptor-framework/scene-holder.h>
40 #include <dali/internal/input/common/key-impl.h>
41 #include <dali/internal/system/common/locale-utils.h>
42 #include <dali/internal/window-system/common/window-render-surface.h>
43 #include <dali/public-api/adaptor-framework/input-method.h>
44
45 Ecore_IMF_Input_Panel_Layout panelLayoutMap[] =
46   {
47     ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL,
48     ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBER,
49     ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL,
50     ECORE_IMF_INPUT_PANEL_LAYOUT_URL,
51     ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER,
52     ECORE_IMF_INPUT_PANEL_LAYOUT_IP,
53     ECORE_IMF_INPUT_PANEL_LAYOUT_MONTH,
54     ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY,
55     ECORE_IMF_INPUT_PANEL_LAYOUT_HEX,
56     ECORE_IMF_INPUT_PANEL_LAYOUT_TERMINAL,
57     ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD,
58     ECORE_IMF_INPUT_PANEL_LAYOUT_DATETIME,
59     ECORE_IMF_INPUT_PANEL_LAYOUT_EMOTICON,
60     ECORE_IMF_INPUT_PANEL_LAYOUT_VOICE};
61
62 Ecore_IMF_Autocapital_Type autoCapitalMap[] =
63   {
64     ECORE_IMF_AUTOCAPITAL_TYPE_NONE,
65     ECORE_IMF_AUTOCAPITAL_TYPE_WORD,
66     ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE,
67     ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER,
68 };
69
70 Ecore_IMF_Input_Panel_Return_Key_Type returnKeyTypeMap[] =
71   {
72     ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT,
73     ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DONE,
74     ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_GO,
75     ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_JOIN,
76     ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_LOGIN,
77     ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_NEXT,
78     ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SEARCH,
79     ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SEND,
80     ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SIGNIN};
81
82 namespace Dali
83 {
84 namespace Internal
85 {
86 namespace Adaptor
87 {
88 namespace
89 {
90 #if defined(DEBUG_ENABLED)
91 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_INPUT_METHOD_CONTEXT");
92 #endif
93
94 const int kUninitializedWindowId = 0;
95
96 // Currently this code is internal to dali/dali/internal/event/text/utf8.h but should be made Public and used from there instead.
97 size_t Utf8SequenceLength(const unsigned char leadByte)
98 {
99   size_t length = 0;
100
101   if((leadByte & 0x80) == 0) //ASCII character (lead bit zero)
102   {
103     length = 1;
104   }
105   else if((leadByte & 0xe0) == 0xc0) //110x xxxx
106   {
107     length = 2;
108   }
109   else if((leadByte & 0xf0) == 0xe0) //1110 xxxx
110   {
111     length = 3;
112   }
113   else if((leadByte & 0xf8) == 0xf0) //1111 0xxx
114   {
115     length = 4;
116   }
117   else if((leadByte & 0xfc) == 0xf8) //1111 10xx
118   {
119     length = 5;
120   }
121   else if((leadByte & 0xfe) == 0xfc) //1111 110x
122   {
123     length = 6;
124   }
125
126   return length;
127 }
128
129 // Static function calls used by ecore 'c' style callback registration
130 void Commit(void* data, Ecore_IMF_Context* imfContext, void* eventInfo)
131 {
132   if(data)
133   {
134     InputMethodContextEcoreWl* inputMethodContext = static_cast<InputMethodContextEcoreWl*>(data);
135     inputMethodContext->CommitReceived(data, imfContext, eventInfo);
136   }
137 }
138
139 void PreEdit(void* data, Ecore_IMF_Context* imfContext, void* eventInfo)
140 {
141   if(data)
142   {
143     InputMethodContextEcoreWl* inputMethodContext = static_cast<InputMethodContextEcoreWl*>(data);
144     inputMethodContext->PreEditChanged(data, imfContext, eventInfo);
145   }
146 }
147
148 Eina_Bool ImfRetrieveSurrounding(void* data, Ecore_IMF_Context* imfContext, char** text, int* cursorPosition)
149 {
150   if(data)
151   {
152     InputMethodContextEcoreWl* inputMethodContext = static_cast<InputMethodContextEcoreWl*>(data);
153     return inputMethodContext->RetrieveSurrounding(data, imfContext, text, cursorPosition);
154   }
155   else
156   {
157     return false;
158   }
159 }
160
161 void InputPanelStateChangeCallback(void* data, Ecore_IMF_Context* context, int value)
162 {
163   if(!data)
164   {
165     return;
166   }
167   InputMethodContextEcoreWl* inputMethodContext = static_cast<InputMethodContextEcoreWl*>(data);
168   switch(value)
169   {
170     case ECORE_IMF_INPUT_PANEL_STATE_SHOW:
171     {
172       inputMethodContext->StatusChangedSignal().Emit(true);
173       break;
174     }
175
176     case ECORE_IMF_INPUT_PANEL_STATE_HIDE:
177     {
178       inputMethodContext->StatusChangedSignal().Emit(false);
179       break;
180     }
181
182     case ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW:
183     default:
184     {
185       // Do nothing
186       break;
187     }
188   }
189 }
190
191 void InputPanelLanguageChangeCallback(void* data, Ecore_IMF_Context* context, int value)
192 {
193   if(!data)
194   {
195     return;
196   }
197   InputMethodContextEcoreWl* inputMethodContext = static_cast<InputMethodContextEcoreWl*>(data);
198   // Emit the signal that the language has changed
199   inputMethodContext->LanguageChangedSignal().Emit(value);
200 }
201
202 void InputPanelGeometryChangedCallback(void* data, Ecore_IMF_Context* context, int value)
203 {
204   if(!data)
205   {
206     return;
207   }
208   InputMethodContextEcoreWl* inputMethodContext = static_cast<InputMethodContextEcoreWl*>(data);
209   // Emit signal that the keyboard is resized
210   inputMethodContext->ResizedSignal().Emit(value);
211 }
212
213 void InputPanelKeyboardTypeChangedCallback(void* data, Ecore_IMF_Context* context, int value)
214 {
215   if(!data)
216   {
217     return;
218   }
219
220   InputMethodContextEcoreWl* inputMethodContext = static_cast<InputMethodContextEcoreWl*>(data);
221   switch(value)
222   {
223     case ECORE_IMF_INPUT_PANEL_SW_KEYBOARD_MODE:
224     {
225       // Emit Signal that the keyboard type is changed to Software Keyboard
226       inputMethodContext->KeyboardTypeChangedSignal().Emit(Dali::InputMethodContext::KeyboardType::SOFTWARE_KEYBOARD);
227       break;
228     }
229     case ECORE_IMF_INPUT_PANEL_HW_KEYBOARD_MODE:
230     {
231       // Emit Signal that the keyboard type is changed to Hardware Keyboard
232       inputMethodContext->KeyboardTypeChangedSignal().Emit(Dali::InputMethodContext::KeyboardType::HARDWARE_KEYBOARD);
233       break;
234     }
235   }
236 }
237
238 /**
239  * Called when an IMF delete surrounding event is received.
240  * Here we tell the application that it should delete a certain range.
241  */
242 void ImfDeleteSurrounding(void* data, Ecore_IMF_Context* imfContext, void* eventInfo)
243 {
244   if(data)
245   {
246     InputMethodContextEcoreWl* inputMethodContext = static_cast<InputMethodContextEcoreWl*>(data);
247     inputMethodContext->DeleteSurrounding(data, imfContext, eventInfo);
248   }
249 }
250
251 /**
252  * Called when the input method sends a private command.
253  */
254 void PrivateCommand(void* data, Ecore_IMF_Context* imfContext, void* eventInfo)
255 {
256   if(data)
257   {
258     InputMethodContextEcoreWl* inputMethodContext = static_cast<InputMethodContextEcoreWl*>(data);
259     inputMethodContext->SendPrivateCommand(data, imfContext, eventInfo);
260   }
261 }
262
263 /**
264  * Called when the input method commits content, such as an image.
265  */
266 void CommitContent(void* data, Ecore_IMF_Context* imfContext, void* eventInfo)
267 {
268   if(data)
269   {
270     InputMethodContextEcoreWl* inputMethodContext = static_cast<InputMethodContextEcoreWl*>(data);
271     inputMethodContext->SendCommitContent(data, imfContext, eventInfo);
272   }
273 }
274
275 int GetWindowIdFromActor(Dali::Actor actor)
276 {
277   int windowId = kUninitializedWindowId;
278
279   if(actor.GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE))
280   {
281     Any nativeWindowHandle = Dali::Integration::SceneHolder::Get(actor).GetNativeHandle();
282
283 #ifdef ECORE_WAYLAND2
284     windowId = ecore_wl2_window_id_get(AnyCast<Ecore_Wl2_Window*>(nativeWindowHandle));
285 #else
286     windowId = ecore_wl_window_id_get(AnyCast<Ecore_Wl_Window*>(nativeWindowHandle));
287 #endif
288   }
289
290   return windowId;
291 }
292
293 BaseHandle Create()
294 {
295   return Dali::InputMethodContext::New(Dali::Actor());
296 }
297
298 Dali::TypeRegistration type(typeid(Dali::InputMethodContext), typeid(Dali::BaseHandle), Create);
299
300 } // unnamed namespace
301
302 InputMethodContextPtr InputMethodContextEcoreWl::New(Dali::Actor actor)
303 {
304   InputMethodContextPtr inputMethodContext;
305
306   // Create instance only if the adaptor is available and the valid actor exists
307   if(actor && Dali::Adaptor::IsAvailable())
308   {
309     inputMethodContext = new InputMethodContextEcoreWl(actor);
310   }
311   return inputMethodContext;
312 }
313
314 void InputMethodContextEcoreWl::Finalize()
315 {
316   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContext::Finalize\n");
317
318   DisconnectCallbacks();
319   DeleteContext();
320 }
321
322 InputMethodContextEcoreWl::InputMethodContextEcoreWl(Dali::Actor actor)
323 : mIMFContext(),
324   mIMFCursorPosition(0),
325   mSurroundingText(),
326   mRestoreAfterFocusLost(false),
327   mIdleCallbackConnected(false),
328   mWindowId(GetWindowIdFromActor(actor))
329 {
330   ecore_imf_init();
331
332   actor.OnSceneSignal().Connect(this, &InputMethodContextEcoreWl::OnStaged);
333 }
334
335 InputMethodContextEcoreWl::~InputMethodContextEcoreWl()
336 {
337   Finalize();
338   ecore_imf_shutdown();
339 }
340
341 void InputMethodContextEcoreWl::Initialize()
342 {
343   CreateContext();
344   ConnectCallbacks();
345   ApplyBackupOperations();
346 }
347
348 void InputMethodContextEcoreWl::CreateContext()
349 {
350   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContext::CreateContext\n");
351
352   if(mWindowId == kUninitializedWindowId)
353   {
354     return;
355   }
356
357   const char* contextId = ecore_imf_context_default_id_get();
358   if(contextId)
359   {
360     mIMFContext = ecore_imf_context_add(contextId);
361
362     if(mIMFContext)
363     {
364       ecore_imf_context_client_window_set(mIMFContext, reinterpret_cast<void*>(mWindowId));
365     }
366     else
367     {
368       DALI_LOG_WARNING("InputMethodContext Unable to get IMFContext\n");
369     }
370   }
371   else
372   {
373     DALI_LOG_WARNING("InputMethodContext Unable to get IMFContext\n");
374   }
375 }
376
377 void InputMethodContextEcoreWl::DeleteContext()
378 {
379   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::DeleteContext\n");
380
381   if(mIMFContext)
382   {
383     ecore_imf_context_del(mIMFContext);
384     mIMFContext = NULL;
385   }
386 }
387
388 // Callbacks for predicitive text support.
389 void InputMethodContextEcoreWl::ConnectCallbacks()
390 {
391   if(mIMFContext)
392   {
393     DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::ConnectCallbacks\n");
394
395     ecore_imf_context_event_callback_add(mIMFContext, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, PreEdit, this);
396     ecore_imf_context_event_callback_add(mIMFContext, ECORE_IMF_CALLBACK_COMMIT, Commit, this);
397     ecore_imf_context_event_callback_add(mIMFContext, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, ImfDeleteSurrounding, this);
398     ecore_imf_context_event_callback_add(mIMFContext, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, PrivateCommand, this);
399     ecore_imf_context_event_callback_add(mIMFContext, ECORE_IMF_CALLBACK_COMMIT_CONTENT, CommitContent, this);
400
401     ecore_imf_context_input_panel_event_callback_add(mIMFContext, ECORE_IMF_INPUT_PANEL_STATE_EVENT, InputPanelStateChangeCallback, this);
402     ecore_imf_context_input_panel_event_callback_add(mIMFContext, ECORE_IMF_INPUT_PANEL_LANGUAGE_EVENT, InputPanelLanguageChangeCallback, this);
403     ecore_imf_context_input_panel_event_callback_add(mIMFContext, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, InputPanelGeometryChangedCallback, this);
404     ecore_imf_context_input_panel_event_callback_add(mIMFContext, ECORE_IMF_INPUT_PANEL_KEYBOARD_MODE_EVENT, InputPanelKeyboardTypeChangedCallback, this);
405
406     ecore_imf_context_retrieve_surrounding_callback_set(mIMFContext, ImfRetrieveSurrounding, this);
407   }
408 }
409
410 void InputMethodContextEcoreWl::DisconnectCallbacks()
411 {
412   if(mIMFContext)
413   {
414     DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::DisconnectCallbacks\n");
415
416     ecore_imf_context_event_callback_del(mIMFContext, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, PreEdit);
417     ecore_imf_context_event_callback_del(mIMFContext, ECORE_IMF_CALLBACK_COMMIT, Commit);
418     ecore_imf_context_event_callback_del(mIMFContext, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, ImfDeleteSurrounding);
419     ecore_imf_context_event_callback_del(mIMFContext, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, PrivateCommand);
420     ecore_imf_context_event_callback_del(mIMFContext, ECORE_IMF_CALLBACK_COMMIT_CONTENT, CommitContent);
421
422     ecore_imf_context_input_panel_event_callback_del(mIMFContext, ECORE_IMF_INPUT_PANEL_STATE_EVENT, InputPanelStateChangeCallback);
423     ecore_imf_context_input_panel_event_callback_del(mIMFContext, ECORE_IMF_INPUT_PANEL_LANGUAGE_EVENT, InputPanelLanguageChangeCallback);
424     ecore_imf_context_input_panel_event_callback_del(mIMFContext, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, InputPanelGeometryChangedCallback);
425     ecore_imf_context_input_panel_event_callback_del(mIMFContext, ECORE_IMF_INPUT_PANEL_KEYBOARD_MODE_EVENT, InputPanelKeyboardTypeChangedCallback);
426
427     // We do not need to unset the retrieve surrounding callback.
428   }
429 }
430
431 void InputMethodContextEcoreWl::Activate()
432 {
433   // Reset mIdleCallbackConnected
434   mIdleCallbackConnected = false;
435
436   if(mIMFContext)
437   {
438     DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::Activate\n");
439
440     ecore_imf_context_focus_in(mIMFContext);
441
442     // emit keyboard activated signal
443     Dali::InputMethodContext handle(this);
444     mActivatedSignal.Emit(handle);
445   }
446 }
447
448 void InputMethodContextEcoreWl::Deactivate()
449 {
450   if(mIMFContext)
451   {
452     DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::Deactivate\n");
453
454     Reset();
455     ecore_imf_context_focus_out(mIMFContext);
456   }
457
458   // Reset mIdleCallbackConnected
459   mIdleCallbackConnected = false;
460 }
461
462 void InputMethodContextEcoreWl::Reset()
463 {
464   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::Reset\n");
465
466   if(mIMFContext)
467   {
468     ecore_imf_context_reset(mIMFContext);
469   }
470 }
471
472 ImfContext* InputMethodContextEcoreWl::GetContext()
473 {
474   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetContext\n");
475
476   return mIMFContext;
477 }
478
479 bool InputMethodContextEcoreWl::RestoreAfterFocusLost() const
480 {
481   return mRestoreAfterFocusLost;
482 }
483
484 void InputMethodContextEcoreWl::SetRestoreAfterFocusLost(bool toggle)
485 {
486   mRestoreAfterFocusLost = toggle;
487 }
488
489 /**
490  * Called when an InputMethodContext Pre-Edit changed event is received.
491  * We are still predicting what the user is typing.  The latest string is what the InputMethodContext module thinks
492  * the user wants to type.
493  */
494 void InputMethodContextEcoreWl::PreEditChanged(void*, ImfContext* imfContext, void* eventInfo)
495 {
496   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::PreEditChanged\n");
497   auto context = static_cast<Ecore_IMF_Context*>(imfContext);
498
499   char*      preEditString(NULL);
500   int        cursorPosition(0);
501   Eina_List* attrs = NULL;
502   Eina_List* l     = NULL;
503
504   Ecore_IMF_Preedit_Attr* attr;
505
506   mPreeditAttrs.Clear();
507
508   // Retrieves attributes as well as the string the cursor position offset from start of pre-edit string.
509   // the attributes (attrs) is used in languages that use the soft arrows keys to insert characters into a current pre-edit string.
510   ecore_imf_context_preedit_string_with_attributes_get(context, &preEditString, &attrs, &cursorPosition);
511
512   if(attrs)
513   {
514     // iterate through the list of attributes getting the type, start and end position.
515     for(l = attrs, (attr = static_cast<Ecore_IMF_Preedit_Attr*>(eina_list_data_get(l))); l; l = eina_list_next(l), (attr = static_cast<Ecore_IMF_Preedit_Attr*>(eina_list_data_get(l))))
516     {
517       Dali::InputMethodContext::PreeditAttributeData data;
518       data.startIndex = 0;
519       data.endIndex   = 0;
520
521       size_t visualCharacterIndex = 0;
522       size_t byteIndex            = 0;
523
524       // iterate through null terminated string checking each character's position against the given byte position ( attr->end_index ).
525       char leadByte = preEditString[byteIndex];
526
527       while(leadByte != '\0')
528       {
529         leadByte = preEditString[byteIndex]; // Update the character to get the number of its byte
530
531         // attr->end_index is provided as a byte position not character and we need to know the character position.
532         const size_t currentSequenceLength = Utf8SequenceLength(leadByte); // returns number of bytes used to represent character.
533         if(byteIndex <= attr->start_index)
534         {
535           data.startIndex = visualCharacterIndex;
536         }
537         if(byteIndex >= attr->end_index)
538         {
539           data.endIndex = visualCharacterIndex;
540           break;
541           // end loop as found cursor position that matches byte position
542         }
543         else
544         {
545           byteIndex += currentSequenceLength; // jump to next character
546           visualCharacterIndex++;             // increment character count so we know our position for when we get a match
547         }
548       }
549
550       switch(attr->preedit_type)
551       {
552         case ECORE_IMF_PREEDIT_TYPE_NONE:
553         {
554           data.preeditType = Dali::InputMethodContext::PreeditStyle::NONE;
555           break;
556         }
557         case ECORE_IMF_PREEDIT_TYPE_SUB1:
558         {
559           data.preeditType = Dali::InputMethodContext::PreeditStyle::UNDERLINE;
560           break;
561         }
562         case ECORE_IMF_PREEDIT_TYPE_SUB2:
563         {
564           data.preeditType = Dali::InputMethodContext::PreeditStyle::REVERSE;
565           break;
566         }
567         case ECORE_IMF_PREEDIT_TYPE_SUB3:
568         {
569           data.preeditType = Dali::InputMethodContext::PreeditStyle::HIGHLIGHT;
570           break;
571         }
572         case ECORE_IMF_PREEDIT_TYPE_SUB4:
573         {
574           data.preeditType = Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_1;
575           break;
576         }
577         case ECORE_IMF_PREEDIT_TYPE_SUB5:
578         {
579           data.preeditType = Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_2;
580           break;
581         }
582         case ECORE_IMF_PREEDIT_TYPE_SUB6:
583         {
584           data.preeditType = Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_3;
585           break;
586         }
587         case ECORE_IMF_PREEDIT_TYPE_SUB7:
588         {
589           data.preeditType = Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_4;
590           break;
591         }
592         default:
593         {
594           data.preeditType = Dali::InputMethodContext::PreeditStyle::NONE;
595           break;
596         }
597       }
598       mPreeditAttrs.PushBack(data);
599     }
600   }
601
602   if(Dali::Adaptor::IsAvailable())
603   {
604     Dali::InputMethodContext               handle(this);
605     Dali::InputMethodContext::EventData    eventData(Dali::InputMethodContext::PRE_EDIT, preEditString, cursorPosition, 0);
606     Dali::InputMethodContext::CallbackData callbackData = mEventSignal.Emit(handle, eventData);
607
608     if(callbackData.update)
609     {
610       SetCursorPosition(callbackData.cursorPosition);
611       SetSurroundingText(callbackData.currentText);
612
613       NotifyCursorPosition();
614     }
615
616     if(callbackData.preeditResetRequired)
617     {
618       Reset();
619     }
620   }
621   free(preEditString);
622 }
623
624 void InputMethodContextEcoreWl::CommitReceived(void*, ImfContext* imfContext, void* eventInfo)
625 {
626   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::CommitReceived\n");
627
628   if(Dali::Adaptor::IsAvailable())
629   {
630     const std::string keyString(static_cast<char*>(eventInfo));
631
632     Dali::InputMethodContext               handle(this);
633     Dali::InputMethodContext::EventData    eventData(Dali::InputMethodContext::COMMIT, keyString, 0, 0);
634     Dali::InputMethodContext::CallbackData callbackData = mEventSignal.Emit(handle, eventData);
635
636     if(callbackData.update)
637     {
638       SetCursorPosition(callbackData.cursorPosition);
639       SetSurroundingText(callbackData.currentText);
640
641       NotifyCursorPosition();
642     }
643   }
644 }
645
646 /**
647  * Called when an InputMethodContext retrieve surround event is received.
648  * Here the InputMethodContext module wishes to know the string we are working with and where within the string the cursor is
649  * We need to signal the application to tell us this information.
650  */
651 bool InputMethodContextEcoreWl::RetrieveSurrounding(void* data, ImfContext* imfContext, char** text, int* cursorPosition)
652 {
653   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::RetrieveSurrounding\n");
654
655   Dali::InputMethodContext::EventData    imfData(Dali::InputMethodContext::GET_SURROUNDING, std::string(), 0, 0);
656   Dali::InputMethodContext               handle(this);
657   Dali::InputMethodContext::CallbackData callbackData = mEventSignal.Emit(handle, imfData);
658
659   if(callbackData.update)
660   {
661     if(cursorPosition)
662     {
663       mIMFCursorPosition = static_cast<int>(callbackData.cursorPosition);
664       *cursorPosition    = mIMFCursorPosition;
665     }
666
667     if(text)
668     {
669       const char* plainText = callbackData.currentText.c_str();
670
671       if(plainText)
672       {
673         // The memory allocated by strdup() can be freed by ecore_imf_context_surrounding_get() internally.
674         *text = strdup(plainText);
675
676         // If the current input panel is password mode, dali should replace the plain text with '*' (Asterisk) character.
677         if((ecore_imf_context_input_hint_get(mIMFContext) & ECORE_IMF_INPUT_HINT_SENSITIVE_DATA) && *text)
678         {
679           for(char* iter = *text; *iter; ++iter)
680           {
681             *iter = '*';
682           }
683         }
684
685         return EINA_TRUE;
686       }
687     }
688   }
689
690   return EINA_FALSE;
691 }
692
693 /**
694  * Called when an InputMethodContext delete surrounding event is received.
695  * Here we tell the application that it should delete a certain range.
696  */
697 void InputMethodContextEcoreWl::DeleteSurrounding(void* data, ImfContext* imfContext, void* eventInfo)
698 {
699   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::DeleteSurrounding\n");
700
701   if(Dali::Adaptor::IsAvailable())
702   {
703     Ecore_IMF_Event_Delete_Surrounding* deleteSurroundingEvent = static_cast<Ecore_IMF_Event_Delete_Surrounding*>(eventInfo);
704
705     Dali::InputMethodContext::EventData imfData(Dali::InputMethodContext::DELETE_SURROUNDING, std::string(), deleteSurroundingEvent->offset, deleteSurroundingEvent->n_chars);
706     Dali::InputMethodContext            handle(this);
707     mEventSignal.Emit(handle, imfData);
708   }
709 }
710
711 /**
712  * Called when the input method sends a private command.
713  */
714 void InputMethodContextEcoreWl::SendPrivateCommand(void* data, ImfContext* imfContext, void* eventInfo)
715 {
716   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SendPrivateCommand\n");
717
718   if(Dali::Adaptor::IsAvailable())
719   {
720     const char* privateCommandSendEvent = static_cast<const char*>(eventInfo);
721
722     Dali::InputMethodContext::EventData imfData(Dali::InputMethodContext::PRIVATE_COMMAND, privateCommandSendEvent, 0, 0);
723     Dali::InputMethodContext            handle(this);
724     mEventSignal.Emit(handle, imfData);
725   }
726 }
727
728 /**
729  * Called when the input method commits content, such as an image.
730  */
731 void InputMethodContextEcoreWl::SendCommitContent(void* data, ImfContext* imfContext, void* eventInfo)
732 {
733   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SendCommitContent\n");
734
735   if(Dali::Adaptor::IsAvailable())
736   {
737     Ecore_IMF_Event_Commit_Content* commitContent = static_cast<Ecore_IMF_Event_Commit_Content*>(eventInfo);
738     if(commitContent)
739     {
740       DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SendCommitContent commit content : %s, description : %s, mime type : %s\n", commitContent->content_uri, commitContent->description, commitContent->mime_types);
741       mContentReceivedSignal.Emit(commitContent->content_uri, commitContent->description, commitContent->mime_types);
742     }
743   }
744 }
745
746 void InputMethodContextEcoreWl::NotifyCursorPosition()
747 {
748   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::NotifyCursorPosition\n");
749
750   if(mIMFContext)
751   {
752     ecore_imf_context_cursor_position_set(mIMFContext, mIMFCursorPosition);
753   }
754 }
755
756 void InputMethodContextEcoreWl::SetCursorPosition(unsigned int cursorPosition)
757 {
758   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SetCursorPosition\n");
759
760   mIMFCursorPosition = static_cast<int>(cursorPosition);
761 }
762
763 unsigned int InputMethodContextEcoreWl::GetCursorPosition() const
764 {
765   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetCursorPosition\n");
766
767   return static_cast<unsigned int>(mIMFCursorPosition);
768 }
769
770 void InputMethodContextEcoreWl::SetSurroundingText(const std::string& text)
771 {
772   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SetSurroundingText\n");
773
774   mSurroundingText = text;
775 }
776
777 const std::string& InputMethodContextEcoreWl::GetSurroundingText() const
778 {
779   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetSurroundingText\n");
780
781   return mSurroundingText;
782 }
783
784 void InputMethodContextEcoreWl::NotifyTextInputMultiLine(bool multiLine)
785 {
786   if(mIMFContext)
787   {
788     Ecore_IMF_Input_Hints currentHint = ecore_imf_context_input_hint_get(mIMFContext);
789     ecore_imf_context_input_hint_set(mIMFContext,
790                                      static_cast<Ecore_IMF_Input_Hints>(multiLine ? (currentHint | ECORE_IMF_INPUT_HINT_MULTILINE) : (currentHint & ~ECORE_IMF_INPUT_HINT_MULTILINE)));
791   }
792
793   mBackupOperations[Operation::NOTIFY_TEXT_INPUT_MULTILINE] = std::bind(&InputMethodContextEcoreWl::NotifyTextInputMultiLine, this, multiLine);
794 }
795
796 Dali::InputMethodContext::TextDirection InputMethodContextEcoreWl::GetTextDirection()
797 {
798   Dali::InputMethodContext::TextDirection direction(Dali::InputMethodContext::LEFT_TO_RIGHT);
799
800   if(mIMFContext)
801   {
802     char* locale(NULL);
803     ecore_imf_context_input_panel_language_locale_get(mIMFContext, &locale);
804
805     if(locale)
806     {
807       direction = static_cast<Dali::InputMethodContext::TextDirection>(Locale::GetDirection(std::string(locale)));
808       free(locale);
809     }
810   }
811
812   return direction;
813 }
814
815 Rect<int> InputMethodContextEcoreWl::GetInputMethodArea()
816 {
817   int xPos, yPos, width, height;
818
819   width = height = xPos = yPos = 0;
820
821   if(mIMFContext)
822   {
823     ecore_imf_context_input_panel_geometry_get(mIMFContext, &xPos, &yPos, &width, &height);
824   }
825   else
826   {
827     DALI_LOG_WARNING("VKB Unable to get IMFContext so GetSize unavailable\n");
828     // return 0 as real size unknown.
829   }
830
831   return Rect<int>(xPos, yPos, width, height);
832 }
833
834 void InputMethodContextEcoreWl::ApplyOptions(const InputMethodOptions& options)
835 {
836   using namespace Dali::InputMethod::Category;
837
838   int index;
839
840   if(mIMFContext == NULL)
841   {
842     DALI_LOG_WARNING("VKB Unable to excute ApplyOptions with Null ImfContext\n");
843     return;
844   }
845
846   if(mOptions.CompareAndSet(PANEL_LAYOUT, options, index))
847   {
848     ecore_imf_context_input_panel_layout_set(mIMFContext, panelLayoutMap[index]);
849
850     // Sets the input hint which allows input methods to fine-tune their behavior.
851     if(panelLayoutMap[index] == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD)
852     {
853       ecore_imf_context_input_hint_set(mIMFContext, static_cast<Ecore_IMF_Input_Hints>(ecore_imf_context_input_hint_get(mIMFContext) | ECORE_IMF_INPUT_HINT_SENSITIVE_DATA));
854     }
855     else
856     {
857       ecore_imf_context_input_hint_set(mIMFContext, static_cast<Ecore_IMF_Input_Hints>(ecore_imf_context_input_hint_get(mIMFContext) & ~ECORE_IMF_INPUT_HINT_SENSITIVE_DATA));
858     }
859   }
860   if(mOptions.CompareAndSet(BUTTON_ACTION, options, index))
861   {
862     ecore_imf_context_input_panel_return_key_type_set(mIMFContext, returnKeyTypeMap[index]);
863   }
864   if(mOptions.CompareAndSet(AUTO_CAPITALIZE, options, index))
865   {
866     ecore_imf_context_autocapital_type_set(mIMFContext, autoCapitalMap[index]);
867   }
868   if(mOptions.CompareAndSet(VARIATION, options, index))
869   {
870     ecore_imf_context_input_panel_layout_variation_set(mIMFContext, index);
871   }
872 }
873
874 void InputMethodContextEcoreWl::SetInputPanelData(const std::string& data)
875 {
876   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SetInputPanelData\n");
877
878   if(mIMFContext)
879   {
880     int length = data.length();
881     ecore_imf_context_input_panel_imdata_set(mIMFContext, data.c_str(), length);
882   }
883
884   mBackupOperations[Operation::SET_INPUT_PANEL_DATA] = std::bind(&InputMethodContextEcoreWl::SetInputPanelData, this, data);
885 }
886
887 void InputMethodContextEcoreWl::GetInputPanelData(std::string& data)
888 {
889   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetInputPanelData\n");
890
891   if(mIMFContext)
892   {
893     int                length = 4096; // The max length is 4096 bytes
894     Dali::Vector<char> buffer;
895     buffer.Resize(length);
896     ecore_imf_context_input_panel_imdata_get(mIMFContext, &buffer[0], &length);
897     data = std::string(buffer.Begin(), buffer.End());
898   }
899 }
900
901 Dali::InputMethodContext::State InputMethodContextEcoreWl::GetInputPanelState()
902 {
903   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetInputPanelState\n");
904
905   if(mIMFContext)
906   {
907     int value;
908     value = ecore_imf_context_input_panel_state_get(mIMFContext);
909
910     switch(value)
911     {
912       case ECORE_IMF_INPUT_PANEL_STATE_SHOW:
913       {
914         return Dali::InputMethodContext::SHOW;
915         break;
916       }
917
918       case ECORE_IMF_INPUT_PANEL_STATE_HIDE:
919       {
920         return Dali::InputMethodContext::HIDE;
921         break;
922       }
923
924       case ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW:
925       {
926         return Dali::InputMethodContext::WILL_SHOW;
927         break;
928       }
929
930       default:
931       {
932         return Dali::InputMethodContext::DEFAULT;
933       }
934     }
935   }
936   return Dali::InputMethodContext::DEFAULT;
937 }
938
939 void InputMethodContextEcoreWl::SetReturnKeyState(bool visible)
940 {
941   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SetReturnKeyState\n");
942
943   if(mIMFContext)
944   {
945     ecore_imf_context_input_panel_return_key_disabled_set(mIMFContext, !visible);
946   }
947
948   mBackupOperations[Operation::SET_RETURN_KEY_STATE] = std::bind(&InputMethodContextEcoreWl::SetReturnKeyState, this, visible);
949 }
950
951 void InputMethodContextEcoreWl::AutoEnableInputPanel(bool enabled)
952 {
953   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::AutoEnableInputPanel\n");
954
955   if(mIMFContext)
956   {
957     ecore_imf_context_input_panel_enabled_set(mIMFContext, enabled);
958   }
959
960   mBackupOperations[Operation::AUTO_ENABLE_INPUT_PANEL] = std::bind(&InputMethodContextEcoreWl::AutoEnableInputPanel, this, enabled);
961 }
962
963 void InputMethodContextEcoreWl::ShowInputPanel()
964 {
965   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::ShowInputPanel\n");
966
967   if(mIMFContext)
968   {
969     ecore_imf_context_input_panel_show(mIMFContext);
970   }
971 }
972
973 void InputMethodContextEcoreWl::HideInputPanel()
974 {
975   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::HideInputPanel\n");
976
977   if(mIMFContext)
978   {
979     ecore_imf_context_input_panel_hide(mIMFContext);
980   }
981 }
982
983 Dali::InputMethodContext::KeyboardType InputMethodContextEcoreWl::GetKeyboardType()
984 {
985   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetKeyboardType\n");
986
987   if(mIMFContext)
988   {
989     int value;
990     value = ecore_imf_context_keyboard_mode_get(mIMFContext);
991
992     switch(value)
993     {
994       case ECORE_IMF_INPUT_PANEL_SW_KEYBOARD_MODE:
995       {
996         return Dali::InputMethodContext::SOFTWARE_KEYBOARD;
997         break;
998       }
999       case ECORE_IMF_INPUT_PANEL_HW_KEYBOARD_MODE:
1000       {
1001         return Dali::InputMethodContext::HARDWARE_KEYBOARD;
1002         break;
1003       }
1004     }
1005   }
1006
1007   return Dali::InputMethodContext::KeyboardType::SOFTWARE_KEYBOARD;
1008 }
1009
1010 std::string InputMethodContextEcoreWl::GetInputPanelLocale()
1011 {
1012   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetInputPanelLocale\n");
1013
1014   std::string locale = "";
1015
1016   if(mIMFContext)
1017   {
1018     char* value = NULL;
1019     ecore_imf_context_input_panel_language_locale_get(mIMFContext, &value);
1020
1021     if(value)
1022     {
1023       std::string valueCopy(value);
1024       locale = valueCopy;
1025
1026       // The locale string retrieved must be freed with free().
1027       free(value);
1028     }
1029   }
1030   return locale;
1031 }
1032
1033 void InputMethodContextEcoreWl::SetContentMIMETypes(const std::string& mimeTypes)
1034 {
1035   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SetContentMIMETypes\n");
1036
1037   if(mIMFContext)
1038   {
1039     ecore_imf_context_mime_type_accept_set(mIMFContext, mimeTypes.c_str());
1040   }
1041
1042   mBackupOperations[Operation::SET_CONTENT_MIME_TYPES] = std::bind(&InputMethodContextEcoreWl::SetContentMIMETypes, this, mimeTypes);
1043 }
1044
1045 bool InputMethodContextEcoreWl::FilterEventKey(const Dali::KeyEvent& keyEvent)
1046 {
1047   bool eventHandled(false);
1048
1049   // If a device key then skip ecore_imf_context_filter_event.
1050   if(!KeyLookup::IsDeviceButton(keyEvent.GetKeyName().c_str()))
1051   {
1052     //check whether it's key down or key up event
1053     if(keyEvent.GetState() == Dali::KeyEvent::DOWN)
1054     {
1055       eventHandled = ProcessEventKeyDown(keyEvent);
1056     }
1057     else if(keyEvent.GetState() == Dali::KeyEvent::UP)
1058     {
1059       eventHandled = ProcessEventKeyUp(keyEvent);
1060     }
1061   }
1062
1063   return eventHandled;
1064 }
1065
1066 void InputMethodContextEcoreWl::AllowTextPrediction(bool prediction)
1067 {
1068   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::AllowTextPrediction\n");
1069
1070   if(mIMFContext)
1071   {
1072     ecore_imf_context_prediction_allow_set(mIMFContext, prediction);
1073   }
1074
1075   mBackupOperations[Operation::ALLOW_TEXT_PREDICTION] = std::bind(&InputMethodContextEcoreWl::AllowTextPrediction, this, prediction);
1076 }
1077
1078 bool InputMethodContextEcoreWl::IsTextPredictionAllowed() const
1079 {
1080   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::IsTextPredictionAllowed\n");
1081   bool prediction = false;
1082   if(mIMFContext)
1083   {
1084     prediction = ecore_imf_context_prediction_allow_get(mIMFContext);
1085   }
1086   return prediction;
1087 }
1088
1089 void InputMethodContextEcoreWl::SetInputPanelLanguage(Dali::InputMethodContext::InputPanelLanguage language)
1090 {
1091   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SetInputPanelLanguage\n");
1092   if(mIMFContext)
1093   {
1094     switch(language)
1095     {
1096       case Dali::InputMethodContext::InputPanelLanguage::AUTOMATIC:
1097       {
1098         ecore_imf_context_input_panel_language_set(mIMFContext, ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC);
1099         break;
1100       }
1101       case Dali::InputMethodContext::InputPanelLanguage::ALPHABET:
1102       {
1103         ecore_imf_context_input_panel_language_set(mIMFContext, ECORE_IMF_INPUT_PANEL_LANG_ALPHABET);
1104         break;
1105       }
1106     }
1107   }
1108
1109   mBackupOperations[Operation::SET_INPUT_PANEL_LANGUAGE] = std::bind(&InputMethodContextEcoreWl::SetInputPanelLanguage, this, language);
1110 }
1111
1112 Dali::InputMethodContext::InputPanelLanguage InputMethodContextEcoreWl::GetInputPanelLanguage() const
1113 {
1114   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetInputPanelLanguage\n");
1115   if(mIMFContext)
1116   {
1117     int value;
1118     value = ecore_imf_context_input_panel_language_get(mIMFContext);
1119
1120     switch(value)
1121     {
1122       case ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC:
1123       {
1124         return Dali::InputMethodContext::InputPanelLanguage::AUTOMATIC;
1125         break;
1126       }
1127       case ECORE_IMF_INPUT_PANEL_LANG_ALPHABET:
1128       {
1129         return Dali::InputMethodContext::InputPanelLanguage::ALPHABET;
1130         break;
1131       }
1132     }
1133   }
1134   return Dali::InputMethodContext::InputPanelLanguage::AUTOMATIC;
1135 }
1136
1137 void InputMethodContextEcoreWl::SetInputPanelPosition(unsigned int x, unsigned int y)
1138 {
1139   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SetInputPanelPosition\n");
1140
1141   if(mIMFContext)
1142   {
1143     ecore_imf_context_input_panel_position_set(mIMFContext, x, y);
1144   }
1145
1146   mBackupOperations[Operation::SET_INPUT_PANEL_POSITION] = std::bind(&InputMethodContextEcoreWl::SetInputPanelPosition, this, x, y);
1147 }
1148
1149 void InputMethodContextEcoreWl::GetPreeditStyle(Dali::InputMethodContext::PreEditAttributeDataContainer& attrs) const
1150 {
1151   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetPreeditStyle\n");
1152   attrs = mPreeditAttrs;
1153 }
1154
1155 bool InputMethodContextEcoreWl::ProcessEventKeyDown(const Dali::KeyEvent& keyEvent)
1156 {
1157   bool eventHandled(false);
1158   if(mIMFContext)
1159   {
1160     Integration::KeyEvent integKeyEvent(keyEvent.GetKeyName(), keyEvent.GetLogicalKey(), keyEvent.GetKeyString(), keyEvent.GetKeyCode(), keyEvent.GetKeyModifier(), keyEvent.GetTime(), static_cast<Integration::KeyEvent::State>(keyEvent.GetState()), keyEvent.GetCompose(), keyEvent.GetDeviceName(), keyEvent.GetDeviceClass(), keyEvent.GetDeviceSubclass());
1161     std::string           key = integKeyEvent.logicalKey;
1162
1163     std::string compose    = integKeyEvent.compose;
1164     std::string deviceName = integKeyEvent.deviceName;
1165
1166     // We're consuming key down event so we have to pass to InputMethodContext so that it can parse it as well.
1167     Ecore_IMF_Event_Key_Down ecoreKeyDownEvent;
1168     ecoreKeyDownEvent.keyname      = integKeyEvent.keyName.c_str();
1169     ecoreKeyDownEvent.key          = key.c_str();
1170     ecoreKeyDownEvent.string       = integKeyEvent.keyString.c_str();
1171     ecoreKeyDownEvent.compose      = compose.c_str();
1172     ecoreKeyDownEvent.timestamp    = integKeyEvent.time;
1173     ecoreKeyDownEvent.modifiers    = EcoreInputModifierToEcoreIMFModifier(integKeyEvent.keyModifier);
1174     ecoreKeyDownEvent.locks        = EcoreInputModifierToEcoreIMFLock(integKeyEvent.keyModifier);
1175     ecoreKeyDownEvent.dev_name     = deviceName.c_str();
1176     ecoreKeyDownEvent.dev_class    = static_cast<Ecore_IMF_Device_Class>(integKeyEvent.deviceClass);       //ECORE_IMF_DEVICE_CLASS_KEYBOARD;
1177     ecoreKeyDownEvent.dev_subclass = static_cast<Ecore_IMF_Device_Subclass>(integKeyEvent.deviceSubclass); //ECORE_IMF_DEVICE_SUBCLASS_NONE;
1178 #if defined(ECORE_VERSION_MAJOR) && (ECORE_VERSION_MAJOR >= 1) && defined(ECORE_VERSION_MINOR) && (ECORE_VERSION_MINOR >= 22)
1179     ecoreKeyDownEvent.keycode = integKeyEvent.keyCode; // Ecore_IMF_Event structure has added 'keycode' variable since ecore_imf 1.22 version.
1180 #endif                                                 // Since ecore_imf 1.22 version
1181
1182     // If the device is IME and the focused key is the direction keys, then we should send a key event to move a key cursor.
1183     if((integKeyEvent.deviceName == "ime") && ((!strncmp(integKeyEvent.keyName.c_str(), "Left", 4)) ||
1184                                                (!strncmp(integKeyEvent.keyName.c_str(), "Right", 5)) ||
1185                                                (!strncmp(integKeyEvent.keyName.c_str(), "Up", 2)) ||
1186                                                (!strncmp(integKeyEvent.keyName.c_str(), "Down", 4))))
1187     {
1188       eventHandled = 0;
1189     }
1190     else
1191     {
1192       eventHandled = ecore_imf_context_filter_event(mIMFContext,
1193                                                     ECORE_IMF_EVENT_KEY_DOWN,
1194                                                     reinterpret_cast<Ecore_IMF_Event*>(&ecoreKeyDownEvent));
1195     }
1196
1197     // If the event has not been handled by InputMethodContext then check if we should reset our input method context
1198     if(!eventHandled)
1199     {
1200       if(!strcmp(integKeyEvent.keyName.c_str(), "Escape") ||
1201          !strcmp(integKeyEvent.keyName.c_str(), "Return") ||
1202          !strcmp(integKeyEvent.keyName.c_str(), "KP_Enter"))
1203       {
1204         ecore_imf_context_reset(mIMFContext);
1205       }
1206     }
1207   }
1208   return eventHandled;
1209 }
1210
1211 bool InputMethodContextEcoreWl::ProcessEventKeyUp(const Dali::KeyEvent& keyEvent)
1212 {
1213   bool eventHandled(false);
1214   if(mIMFContext)
1215   {
1216     Integration::KeyEvent integKeyEvent(keyEvent.GetKeyName(), keyEvent.GetLogicalKey(), keyEvent.GetKeyString(), keyEvent.GetKeyCode(), keyEvent.GetKeyModifier(), keyEvent.GetTime(), static_cast<Integration::KeyEvent::State>(keyEvent.GetState()), keyEvent.GetCompose(), keyEvent.GetDeviceName(), keyEvent.GetDeviceClass(), keyEvent.GetDeviceSubclass());
1217     std::string           key = integKeyEvent.logicalKey;
1218
1219     std::string compose    = integKeyEvent.compose;
1220     std::string deviceName = integKeyEvent.deviceName;
1221
1222     // We're consuming key up event so we have to pass to InputMethodContext so that it can parse it as well.
1223     Ecore_IMF_Event_Key_Up ecoreKeyUpEvent;
1224     ecoreKeyUpEvent.keyname      = integKeyEvent.keyName.c_str();
1225     ecoreKeyUpEvent.key          = key.c_str();
1226     ecoreKeyUpEvent.string       = integKeyEvent.keyString.c_str();
1227     ecoreKeyUpEvent.compose      = compose.c_str();
1228     ecoreKeyUpEvent.timestamp    = integKeyEvent.time;
1229     ecoreKeyUpEvent.modifiers    = EcoreInputModifierToEcoreIMFModifier(integKeyEvent.keyModifier);
1230     ecoreKeyUpEvent.locks        = EcoreInputModifierToEcoreIMFLock(integKeyEvent.keyModifier);
1231     ecoreKeyUpEvent.dev_name     = deviceName.c_str();
1232     ecoreKeyUpEvent.dev_class    = static_cast<Ecore_IMF_Device_Class>(integKeyEvent.deviceClass);       //ECORE_IMF_DEVICE_CLASS_KEYBOARD;
1233     ecoreKeyUpEvent.dev_subclass = static_cast<Ecore_IMF_Device_Subclass>(integKeyEvent.deviceSubclass); //ECORE_IMF_DEVICE_SUBCLASS_NONE;
1234 #if defined(ECORE_VERSION_MAJOR) && (ECORE_VERSION_MAJOR >= 1) && defined(ECORE_VERSION_MINOR) && (ECORE_VERSION_MINOR >= 22)
1235     ecoreKeyUpEvent.keycode = integKeyEvent.keyCode; // Ecore_IMF_Event structure has added 'keycode' variable since ecore_imf 1.22 version.
1236 #endif                                               // Since ecore_imf 1.22 version
1237
1238     eventHandled = ecore_imf_context_filter_event(mIMFContext,
1239                                                   ECORE_IMF_EVENT_KEY_UP,
1240                                                   reinterpret_cast<Ecore_IMF_Event*>(&ecoreKeyUpEvent));
1241   }
1242   return eventHandled;
1243 }
1244
1245 Ecore_IMF_Keyboard_Modifiers InputMethodContextEcoreWl::EcoreInputModifierToEcoreIMFModifier(unsigned int ecoreModifier)
1246 {
1247   unsigned int modifier(ECORE_IMF_KEYBOARD_MODIFIER_NONE); // If no other matches returns NONE.
1248
1249   if(ecoreModifier & ECORE_EVENT_MODIFIER_SHIFT) // enums from ecore_input/Ecore_Input.h
1250   {
1251     modifier |= ECORE_IMF_KEYBOARD_MODIFIER_SHIFT; // enums from ecore_imf/ecore_imf.h
1252   }
1253
1254   if(ecoreModifier & ECORE_EVENT_MODIFIER_ALT)
1255   {
1256     modifier |= ECORE_IMF_KEYBOARD_MODIFIER_ALT;
1257   }
1258
1259   if(ecoreModifier & ECORE_EVENT_MODIFIER_CTRL)
1260   {
1261     modifier |= ECORE_IMF_KEYBOARD_MODIFIER_CTRL;
1262   }
1263
1264   if(ecoreModifier & ECORE_EVENT_MODIFIER_WIN)
1265   {
1266     modifier |= ECORE_IMF_KEYBOARD_MODIFIER_WIN;
1267   }
1268
1269   if(ecoreModifier & ECORE_EVENT_MODIFIER_ALTGR)
1270   {
1271     modifier |= ECORE_IMF_KEYBOARD_MODIFIER_ALTGR;
1272   }
1273
1274   return static_cast<Ecore_IMF_Keyboard_Modifiers>(modifier);
1275 }
1276
1277 Ecore_IMF_Keyboard_Locks InputMethodContextEcoreWl::EcoreInputModifierToEcoreIMFLock(unsigned int modifier)
1278 {
1279   unsigned int lock(ECORE_IMF_KEYBOARD_LOCK_NONE); // If no other matches, returns NONE.
1280
1281   if(modifier & ECORE_EVENT_LOCK_NUM)
1282   {
1283     lock |= ECORE_IMF_KEYBOARD_LOCK_NUM; // Num lock is active.
1284   }
1285
1286   if(modifier & ECORE_EVENT_LOCK_CAPS)
1287   {
1288     lock |= ECORE_IMF_KEYBOARD_LOCK_CAPS; // Caps lock is active.
1289   }
1290
1291   if(modifier & ECORE_EVENT_LOCK_SCROLL)
1292   {
1293     lock |= ECORE_IMF_KEYBOARD_LOCK_SCROLL; // Scroll lock is active.
1294   }
1295
1296   return static_cast<Ecore_IMF_Keyboard_Locks>(lock);
1297 }
1298
1299 void InputMethodContextEcoreWl::OnStaged(Dali::Actor actor)
1300 {
1301   int windowId = GetWindowIdFromActor(actor);
1302
1303   if(mWindowId != windowId)
1304   {
1305     mWindowId = windowId;
1306
1307     // Reset
1308     Finalize();
1309     Initialize();
1310   }
1311 }
1312
1313 } // namespace Adaptor
1314
1315 } // namespace Internal
1316
1317 } // namespace Dali