[dali_2.3.33] Merge branch 'devel/master'
[platform/core/uifw/dali-adaptor.git] / dali / internal / input / tizen-wayland / input-method-context-impl-ecore-wl.cpp
1 /*
2  * Copyright (c) 2024 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 /**
276  * Called when the input method sends a selection set.
277  */
278 void SelectionSet(void* data, Ecore_IMF_Context* imfContext, void* eventInfo)
279 {
280   if(data)
281   {
282     InputMethodContextEcoreWl* inputMethodContext = static_cast<InputMethodContextEcoreWl*>(data);
283     inputMethodContext->SendSelectionSet(data, imfContext, eventInfo);
284   }
285 }
286
287 int GetWindowIdFromActor(Dali::Actor actor)
288 {
289   int windowId = kUninitializedWindowId;
290
291   if(actor.GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE))
292   {
293     Any nativeWindowHandle = Dali::Integration::SceneHolder::Get(actor).GetNativeHandle();
294
295 #ifdef ECORE_WAYLAND2
296     windowId = ecore_wl2_window_id_get(AnyCast<Ecore_Wl2_Window*>(nativeWindowHandle));
297 #else
298     windowId = ecore_wl_window_id_get(AnyCast<Ecore_Wl_Window*>(nativeWindowHandle));
299 #endif
300   }
301
302   return windowId;
303 }
304
305 BaseHandle Create()
306 {
307   return Dali::InputMethodContext::New(Dali::Actor());
308 }
309
310 Dali::TypeRegistration type(typeid(Dali::InputMethodContext), typeid(Dali::BaseHandle), Create);
311
312 } // unnamed namespace
313
314 InputMethodContextPtr InputMethodContextEcoreWl::New(Dali::Actor actor)
315 {
316   InputMethodContextPtr inputMethodContext;
317
318   // Create instance only if the adaptor is available and the valid actor exists
319   if(actor && Dali::Adaptor::IsAvailable())
320   {
321     inputMethodContext = new InputMethodContextEcoreWl(actor);
322   }
323   return inputMethodContext;
324 }
325
326 void InputMethodContextEcoreWl::Finalize()
327 {
328   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContext::Finalize\n");
329
330   DisconnectCallbacks();
331   DeleteContext();
332 }
333
334 InputMethodContextEcoreWl::InputMethodContextEcoreWl(Dali::Actor actor)
335 : mIMFContext(),
336   mIMFCursorPosition(0),
337   mSurroundingText(),
338   mRestoreAfterFocusLost(false),
339   mIdleCallbackConnected(false),
340   mWindowId(GetWindowIdFromActor(actor))
341 {
342   ecore_imf_init();
343
344   actor.OnSceneSignal().Connect(this, &InputMethodContextEcoreWl::OnStaged);
345 }
346
347 InputMethodContextEcoreWl::~InputMethodContextEcoreWl()
348 {
349   Finalize();
350   try
351   {
352     ecore_imf_shutdown();
353   }
354   catch(std::bad_weak_ptr const& ex)
355   {
356     DALI_LOG_ERROR("InputMethodContextEcoreWl::~InputMethodContextEcoreWl() - std::bad_weak_ptr caught: %s\n", ex.what());
357   }
358 }
359
360 void InputMethodContextEcoreWl::Initialize()
361 {
362   CreateContext();
363   ConnectCallbacks();
364   ApplyBackupOperations();
365 }
366
367 void InputMethodContextEcoreWl::CreateContext()
368 {
369   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContext::CreateContext\n");
370
371   if(mWindowId == kUninitializedWindowId)
372   {
373     return;
374   }
375
376   const char* contextId = ecore_imf_context_default_id_get();
377   if(contextId)
378   {
379     mIMFContext = ecore_imf_context_add(contextId);
380
381     if(mIMFContext)
382     {
383       ecore_imf_context_client_window_set(mIMFContext, reinterpret_cast<void*>(mWindowId));
384     }
385     else
386     {
387       DALI_LOG_WARNING("InputMethodContext Unable to get IMFContext\n");
388     }
389   }
390   else
391   {
392     DALI_LOG_WARNING("InputMethodContext Unable to get IMFContext\n");
393   }
394 }
395
396 void InputMethodContextEcoreWl::DeleteContext()
397 {
398   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::DeleteContext\n");
399
400   if(mIMFContext)
401   {
402     ecore_imf_context_del(mIMFContext);
403     mIMFContext = NULL;
404   }
405 }
406
407 // Callbacks for predicitive text support.
408 void InputMethodContextEcoreWl::ConnectCallbacks()
409 {
410   if(mIMFContext)
411   {
412     DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::ConnectCallbacks\n");
413
414     ecore_imf_context_event_callback_add(mIMFContext, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, PreEdit, this);
415     ecore_imf_context_event_callback_add(mIMFContext, ECORE_IMF_CALLBACK_COMMIT, Commit, this);
416     ecore_imf_context_event_callback_add(mIMFContext, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, ImfDeleteSurrounding, this);
417     ecore_imf_context_event_callback_add(mIMFContext, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, PrivateCommand, this);
418     ecore_imf_context_event_callback_add(mIMFContext, ECORE_IMF_CALLBACK_COMMIT_CONTENT, CommitContent, this);
419     ecore_imf_context_event_callback_add(mIMFContext, ECORE_IMF_CALLBACK_SELECTION_SET, SelectionSet, this);
420
421     ecore_imf_context_input_panel_event_callback_add(mIMFContext, ECORE_IMF_INPUT_PANEL_STATE_EVENT, InputPanelStateChangeCallback, this);
422     ecore_imf_context_input_panel_event_callback_add(mIMFContext, ECORE_IMF_INPUT_PANEL_LANGUAGE_EVENT, InputPanelLanguageChangeCallback, this);
423     ecore_imf_context_input_panel_event_callback_add(mIMFContext, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, InputPanelGeometryChangedCallback, this);
424     ecore_imf_context_input_panel_event_callback_add(mIMFContext, ECORE_IMF_INPUT_PANEL_KEYBOARD_MODE_EVENT, InputPanelKeyboardTypeChangedCallback, this);
425
426     ecore_imf_context_retrieve_surrounding_callback_set(mIMFContext, ImfRetrieveSurrounding, this);
427   }
428 }
429
430 void InputMethodContextEcoreWl::DisconnectCallbacks()
431 {
432   if(mIMFContext)
433   {
434     DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::DisconnectCallbacks\n");
435
436     ecore_imf_context_event_callback_del(mIMFContext, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, PreEdit);
437     ecore_imf_context_event_callback_del(mIMFContext, ECORE_IMF_CALLBACK_COMMIT, Commit);
438     ecore_imf_context_event_callback_del(mIMFContext, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, ImfDeleteSurrounding);
439     ecore_imf_context_event_callback_del(mIMFContext, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, PrivateCommand);
440     ecore_imf_context_event_callback_del(mIMFContext, ECORE_IMF_CALLBACK_COMMIT_CONTENT, CommitContent);
441     ecore_imf_context_event_callback_del(mIMFContext, ECORE_IMF_CALLBACK_SELECTION_SET, SelectionSet);
442
443     ecore_imf_context_input_panel_event_callback_del(mIMFContext, ECORE_IMF_INPUT_PANEL_STATE_EVENT, InputPanelStateChangeCallback);
444     ecore_imf_context_input_panel_event_callback_del(mIMFContext, ECORE_IMF_INPUT_PANEL_LANGUAGE_EVENT, InputPanelLanguageChangeCallback);
445     ecore_imf_context_input_panel_event_callback_del(mIMFContext, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, InputPanelGeometryChangedCallback);
446     ecore_imf_context_input_panel_event_callback_del(mIMFContext, ECORE_IMF_INPUT_PANEL_KEYBOARD_MODE_EVENT, InputPanelKeyboardTypeChangedCallback);
447
448     // We do not need to unset the retrieve surrounding callback.
449   }
450 }
451
452 void InputMethodContextEcoreWl::Activate()
453 {
454   // Reset mIdleCallbackConnected
455   mIdleCallbackConnected = false;
456
457   if(mIMFContext)
458   {
459     DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::Activate\n");
460
461     ecore_imf_context_focus_in(mIMFContext);
462
463     // emit keyboard activated signal
464     Dali::InputMethodContext handle(this);
465     mActivatedSignal.Emit(handle);
466   }
467 }
468
469 void InputMethodContextEcoreWl::Deactivate()
470 {
471   if(mIMFContext)
472   {
473     DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::Deactivate\n");
474
475     Reset();
476     ecore_imf_context_focus_out(mIMFContext);
477   }
478
479   // Reset mIdleCallbackConnected
480   mIdleCallbackConnected = false;
481 }
482
483 void InputMethodContextEcoreWl::Reset()
484 {
485   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::Reset\n");
486
487   if(mIMFContext)
488   {
489     ecore_imf_context_reset(mIMFContext);
490   }
491 }
492
493 ImfContext* InputMethodContextEcoreWl::GetContext()
494 {
495   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetContext\n");
496
497   return mIMFContext;
498 }
499
500 bool InputMethodContextEcoreWl::RestoreAfterFocusLost() const
501 {
502   return mRestoreAfterFocusLost;
503 }
504
505 void InputMethodContextEcoreWl::SetRestoreAfterFocusLost(bool toggle)
506 {
507   mRestoreAfterFocusLost = toggle;
508 }
509
510 /**
511  * Called when an InputMethodContext Pre-Edit changed event is received.
512  * We are still predicting what the user is typing.  The latest string is what the InputMethodContext module thinks
513  * the user wants to type.
514  */
515 void InputMethodContextEcoreWl::PreEditChanged(void*, ImfContext* imfContext, void* eventInfo)
516 {
517   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::PreEditChanged\n");
518   auto context = static_cast<Ecore_IMF_Context*>(imfContext);
519
520   char*      preEditString(NULL);
521   int        cursorPosition(0);
522   Eina_List* attrs = NULL;
523   Eina_List* l     = NULL;
524
525   Ecore_IMF_Preedit_Attr* attr;
526
527   mPreeditAttrs.Clear();
528
529   // Retrieves attributes as well as the string the cursor position offset from start of pre-edit string.
530   // the attributes (attrs) is used in languages that use the soft arrows keys to insert characters into a current pre-edit string.
531   ecore_imf_context_preedit_string_with_attributes_get(context, &preEditString, &attrs, &cursorPosition);
532
533   if(attrs)
534   {
535     // iterate through the list of attributes getting the type, start and end position.
536     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))))
537     {
538       Dali::InputMethodContext::PreeditAttributeData data;
539       data.startIndex = 0;
540       data.endIndex   = 0;
541
542       uint32_t visualCharacterIndex = 0;
543       size_t   byteIndex            = 0;
544
545       // iterate through null terminated string checking each character's position against the given byte position ( attr->end_index ).
546       char leadByte = preEditString[byteIndex];
547
548       while(leadByte != '\0')
549       {
550         leadByte = preEditString[byteIndex]; // Update the character to get the number of its byte
551
552         // attr->end_index is provided as a byte position not character and we need to know the character position.
553         const size_t currentSequenceLength = Utf8SequenceLength(leadByte); // returns number of bytes used to represent character.
554         if(byteIndex <= attr->start_index)
555         {
556           data.startIndex = visualCharacterIndex;
557         }
558         if(byteIndex >= attr->end_index)
559         {
560           data.endIndex = visualCharacterIndex;
561           break;
562           // end loop as found cursor position that matches byte position
563         }
564         else
565         {
566           byteIndex += currentSequenceLength; // jump to next character
567           visualCharacterIndex++;             // increment character count so we know our position for when we get a match
568         }
569       }
570
571       switch(attr->preedit_type)
572       {
573         case ECORE_IMF_PREEDIT_TYPE_NONE:
574         {
575           data.preeditType = Dali::InputMethodContext::PreeditStyle::NONE;
576           break;
577         }
578         case ECORE_IMF_PREEDIT_TYPE_SUB1:
579         {
580           data.preeditType = Dali::InputMethodContext::PreeditStyle::UNDERLINE;
581           break;
582         }
583         case ECORE_IMF_PREEDIT_TYPE_SUB2:
584         {
585           data.preeditType = Dali::InputMethodContext::PreeditStyle::REVERSE;
586           break;
587         }
588         case ECORE_IMF_PREEDIT_TYPE_SUB3:
589         {
590           data.preeditType = Dali::InputMethodContext::PreeditStyle::HIGHLIGHT;
591           break;
592         }
593         case ECORE_IMF_PREEDIT_TYPE_SUB4:
594         {
595           data.preeditType = Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_1;
596           break;
597         }
598         case ECORE_IMF_PREEDIT_TYPE_SUB5:
599         {
600           data.preeditType = Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_2;
601           break;
602         }
603         case ECORE_IMF_PREEDIT_TYPE_SUB6:
604         {
605           data.preeditType = Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_3;
606           break;
607         }
608         case ECORE_IMF_PREEDIT_TYPE_SUB7:
609         {
610           data.preeditType = Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_4;
611           break;
612         }
613         default:
614         {
615           data.preeditType = Dali::InputMethodContext::PreeditStyle::NONE;
616           break;
617         }
618       }
619       mPreeditAttrs.PushBack(data);
620     }
621   }
622
623   if(Dali::Adaptor::IsAvailable())
624   {
625     Dali::InputMethodContext               handle(this);
626     Dali::InputMethodContext::EventData    eventData(Dali::InputMethodContext::PRE_EDIT, preEditString, cursorPosition, 0);
627     Dali::InputMethodContext::CallbackData callbackData = mEventSignal.Emit(handle, eventData);
628
629     if(callbackData.update)
630     {
631       SetCursorPosition(callbackData.cursorPosition);
632       SetSurroundingText(callbackData.currentText);
633
634       NotifyCursorPosition();
635     }
636
637     if(callbackData.preeditResetRequired)
638     {
639       Reset();
640     }
641   }
642   free(preEditString);
643 }
644
645 void InputMethodContextEcoreWl::CommitReceived(void*, ImfContext* imfContext, void* eventInfo)
646 {
647   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::CommitReceived\n");
648
649   if(Dali::Adaptor::IsAvailable())
650   {
651     const std::string keyString(static_cast<char*>(eventInfo));
652
653     Dali::InputMethodContext               handle(this);
654     Dali::InputMethodContext::EventData    eventData(Dali::InputMethodContext::COMMIT, keyString, 0, 0);
655     Dali::InputMethodContext::CallbackData callbackData = mEventSignal.Emit(handle, eventData);
656
657     if(callbackData.update)
658     {
659       SetCursorPosition(callbackData.cursorPosition);
660       SetSurroundingText(callbackData.currentText);
661
662       NotifyCursorPosition();
663     }
664   }
665 }
666
667 /**
668  * Called when an InputMethodContext retrieve surround event is received.
669  * Here the InputMethodContext module wishes to know the string we are working with and where within the string the cursor is
670  * We need to signal the application to tell us this information.
671  */
672 bool InputMethodContextEcoreWl::RetrieveSurrounding(void* data, ImfContext* imfContext, char** text, int* cursorPosition)
673 {
674   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::RetrieveSurrounding\n");
675
676   Dali::InputMethodContext::EventData    imfData(Dali::InputMethodContext::GET_SURROUNDING, std::string(), 0, 0);
677   Dali::InputMethodContext               handle(this);
678   Dali::InputMethodContext::CallbackData callbackData = mEventSignal.Emit(handle, imfData);
679
680   if(callbackData.update)
681   {
682     if(cursorPosition)
683     {
684       mIMFCursorPosition = static_cast<int>(callbackData.cursorPosition);
685       *cursorPosition    = mIMFCursorPosition;
686     }
687
688     if(text)
689     {
690       const char* plainText = callbackData.currentText.c_str();
691
692       if(plainText)
693       {
694         // The memory allocated by strdup() can be freed by ecore_imf_context_surrounding_get() internally.
695         *text = strdup(plainText);
696
697         // If the current input panel is password mode, dali should replace the plain text with '*' (Asterisk) character.
698         if((ecore_imf_context_input_hint_get(mIMFContext) & ECORE_IMF_INPUT_HINT_SENSITIVE_DATA) && *text)
699         {
700           for(char* iter = *text; *iter; ++iter)
701           {
702             *iter = '*';
703           }
704         }
705
706         return EINA_TRUE;
707       }
708     }
709   }
710
711   return EINA_FALSE;
712 }
713
714 /**
715  * Called when an InputMethodContext delete surrounding event is received.
716  * Here we tell the application that it should delete a certain range.
717  */
718 void InputMethodContextEcoreWl::DeleteSurrounding(void* data, ImfContext* imfContext, void* eventInfo)
719 {
720   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::DeleteSurrounding\n");
721
722   if(Dali::Adaptor::IsAvailable())
723   {
724     Ecore_IMF_Event_Delete_Surrounding* deleteSurroundingEvent = static_cast<Ecore_IMF_Event_Delete_Surrounding*>(eventInfo);
725
726     Dali::InputMethodContext::EventData imfData(Dali::InputMethodContext::DELETE_SURROUNDING, std::string(), deleteSurroundingEvent->offset, deleteSurroundingEvent->n_chars);
727     Dali::InputMethodContext            handle(this);
728     mEventSignal.Emit(handle, imfData);
729   }
730 }
731
732 /**
733  * Called when the input method sends a private command.
734  */
735 void InputMethodContextEcoreWl::SendPrivateCommand(void* data, ImfContext* imfContext, void* eventInfo)
736 {
737   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SendPrivateCommand\n");
738
739   if(Dali::Adaptor::IsAvailable())
740   {
741     const char* privateCommandSendEvent = static_cast<const char*>(eventInfo);
742
743     Dali::InputMethodContext::EventData imfData(Dali::InputMethodContext::PRIVATE_COMMAND, privateCommandSendEvent, 0, 0);
744     Dali::InputMethodContext            handle(this);
745     mEventSignal.Emit(handle, imfData);
746   }
747 }
748
749 /**
750  * Called when the input method commits content, such as an image.
751  */
752 void InputMethodContextEcoreWl::SendCommitContent(void* data, ImfContext* imfContext, void* eventInfo)
753 {
754   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SendCommitContent\n");
755
756   if(Dali::Adaptor::IsAvailable())
757   {
758     Ecore_IMF_Event_Commit_Content* commitContent = static_cast<Ecore_IMF_Event_Commit_Content*>(eventInfo);
759     if(commitContent)
760     {
761       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);
762       mContentReceivedSignal.Emit(commitContent->content_uri, commitContent->description, commitContent->mime_types);
763     }
764   }
765 }
766
767 /**
768  * Called when the input method selection set.
769  */
770 void InputMethodContextEcoreWl::SendSelectionSet(void* data, ImfContext* imfContext, void* eventInfo)
771 {
772   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SendCommitContent\n");
773
774   if(Dali::Adaptor::IsAvailable())
775   {
776     Ecore_IMF_Event_Selection* selection = static_cast<Ecore_IMF_Event_Selection*>(eventInfo);
777     if(selection)
778     {
779       DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SendSelectionSet selection start index : %d, end index : %d\n", selection->start, selection->end);
780       Dali::InputMethodContext::EventData imfData(Dali::InputMethodContext::SELECTION_SET, selection->start, selection->end);
781       Dali::InputMethodContext            handle(this);
782       mEventSignal.Emit(handle, imfData);
783     }
784   }
785 }
786
787 void InputMethodContextEcoreWl::NotifyCursorPosition()
788 {
789   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::NotifyCursorPosition\n");
790
791   if(mIMFContext)
792   {
793     ecore_imf_context_cursor_position_set(mIMFContext, mIMFCursorPosition);
794   }
795 }
796
797 void InputMethodContextEcoreWl::SetCursorPosition(unsigned int cursorPosition)
798 {
799   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SetCursorPosition\n");
800
801   mIMFCursorPosition = static_cast<int>(cursorPosition);
802 }
803
804 unsigned int InputMethodContextEcoreWl::GetCursorPosition() const
805 {
806   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetCursorPosition\n");
807
808   return static_cast<unsigned int>(mIMFCursorPosition);
809 }
810
811 void InputMethodContextEcoreWl::SetSurroundingText(const std::string& text)
812 {
813   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SetSurroundingText\n");
814
815   mSurroundingText = text;
816 }
817
818 const std::string& InputMethodContextEcoreWl::GetSurroundingText() const
819 {
820   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetSurroundingText\n");
821
822   return mSurroundingText;
823 }
824
825 void InputMethodContextEcoreWl::NotifyTextInputMultiLine(bool multiLine)
826 {
827   if(mIMFContext)
828   {
829     Ecore_IMF_Input_Hints currentHint = ecore_imf_context_input_hint_get(mIMFContext);
830     ecore_imf_context_input_hint_set(mIMFContext,
831                                      static_cast<Ecore_IMF_Input_Hints>(multiLine ? (currentHint | ECORE_IMF_INPUT_HINT_MULTILINE) : (currentHint & ~ECORE_IMF_INPUT_HINT_MULTILINE)));
832   }
833
834   mBackupOperations[Operation::NOTIFY_TEXT_INPUT_MULTILINE] = std::bind(&InputMethodContextEcoreWl::NotifyTextInputMultiLine, this, multiLine);
835 }
836
837 Dali::InputMethodContext::TextDirection InputMethodContextEcoreWl::GetTextDirection()
838 {
839   Dali::InputMethodContext::TextDirection direction(Dali::InputMethodContext::LEFT_TO_RIGHT);
840
841   if(mIMFContext)
842   {
843     char* locale(NULL);
844     ecore_imf_context_input_panel_language_locale_get(mIMFContext, &locale);
845
846     if(locale)
847     {
848       direction = static_cast<Dali::InputMethodContext::TextDirection>(Locale::GetDirection(std::string(locale)));
849       free(locale);
850     }
851   }
852
853   return direction;
854 }
855
856 Rect<int> InputMethodContextEcoreWl::GetInputMethodArea()
857 {
858   int xPos, yPos, width, height;
859
860   width = height = xPos = yPos = 0;
861
862   if(mIMFContext)
863   {
864     ecore_imf_context_input_panel_geometry_get(mIMFContext, &xPos, &yPos, &width, &height);
865   }
866   else
867   {
868     DALI_LOG_WARNING("VKB Unable to get IMFContext so GetSize unavailable\n");
869     // return 0 as real size unknown.
870   }
871
872   return Rect<int>(xPos, yPos, width, height);
873 }
874
875 void InputMethodContextEcoreWl::ApplyOptions(const InputMethodOptions& options)
876 {
877   using namespace Dali::InputMethod::Category;
878
879   int index;
880
881   if(mIMFContext == NULL)
882   {
883     DALI_LOG_WARNING("VKB Unable to excute ApplyOptions with Null ImfContext\n");
884     return;
885   }
886
887   if(mOptions.CompareAndSet(PANEL_LAYOUT, options, index))
888   {
889     ecore_imf_context_input_panel_layout_set(mIMFContext, panelLayoutMap[index]);
890
891     // Sets the input hint which allows input methods to fine-tune their behavior.
892     if(panelLayoutMap[index] == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD)
893     {
894       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));
895     }
896     else
897     {
898       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));
899     }
900   }
901   if(mOptions.CompareAndSet(BUTTON_ACTION, options, index))
902   {
903     ecore_imf_context_input_panel_return_key_type_set(mIMFContext, returnKeyTypeMap[index]);
904   }
905   if(mOptions.CompareAndSet(AUTO_CAPITALIZE, options, index))
906   {
907     ecore_imf_context_autocapital_type_set(mIMFContext, autoCapitalMap[index]);
908   }
909   if(mOptions.CompareAndSet(VARIATION, options, index))
910   {
911     ecore_imf_context_input_panel_layout_variation_set(mIMFContext, index);
912   }
913 }
914
915 void InputMethodContextEcoreWl::SetInputPanelData(const std::string& data)
916 {
917   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SetInputPanelData\n");
918
919   if(mIMFContext)
920   {
921     int length = data.length();
922     ecore_imf_context_input_panel_imdata_set(mIMFContext, data.c_str(), length);
923   }
924
925   mBackupOperations[Operation::SET_INPUT_PANEL_DATA] = std::bind(&InputMethodContextEcoreWl::SetInputPanelData, this, data);
926 }
927
928 void InputMethodContextEcoreWl::GetInputPanelData(std::string& data)
929 {
930   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetInputPanelData\n");
931
932   if(mIMFContext)
933   {
934     int                length = 4096; // The max length is 4096 bytes
935     Dali::Vector<char> buffer;
936     buffer.Resize(length);
937     ecore_imf_context_input_panel_imdata_get(mIMFContext, &buffer[0], &length);
938     data = std::string(buffer.Begin(), buffer.End());
939   }
940 }
941
942 Dali::InputMethodContext::State InputMethodContextEcoreWl::GetInputPanelState()
943 {
944   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetInputPanelState\n");
945
946   if(mIMFContext)
947   {
948     int value;
949     value = ecore_imf_context_input_panel_state_get(mIMFContext);
950
951     switch(value)
952     {
953       case ECORE_IMF_INPUT_PANEL_STATE_SHOW:
954       {
955         return Dali::InputMethodContext::SHOW;
956         break;
957       }
958
959       case ECORE_IMF_INPUT_PANEL_STATE_HIDE:
960       {
961         return Dali::InputMethodContext::HIDE;
962         break;
963       }
964
965       case ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW:
966       {
967         return Dali::InputMethodContext::WILL_SHOW;
968         break;
969       }
970
971       default:
972       {
973         return Dali::InputMethodContext::DEFAULT;
974       }
975     }
976   }
977   return Dali::InputMethodContext::DEFAULT;
978 }
979
980 void InputMethodContextEcoreWl::SetReturnKeyState(bool visible)
981 {
982   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SetReturnKeyState\n");
983
984   if(mIMFContext)
985   {
986     ecore_imf_context_input_panel_return_key_disabled_set(mIMFContext, !visible);
987   }
988
989   mBackupOperations[Operation::SET_RETURN_KEY_STATE] = std::bind(&InputMethodContextEcoreWl::SetReturnKeyState, this, visible);
990 }
991
992 void InputMethodContextEcoreWl::AutoEnableInputPanel(bool enabled)
993 {
994   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::AutoEnableInputPanel\n");
995
996   if(mIMFContext)
997   {
998     ecore_imf_context_input_panel_enabled_set(mIMFContext, enabled);
999   }
1000
1001   mBackupOperations[Operation::AUTO_ENABLE_INPUT_PANEL] = std::bind(&InputMethodContextEcoreWl::AutoEnableInputPanel, this, enabled);
1002 }
1003
1004 void InputMethodContextEcoreWl::ShowInputPanel()
1005 {
1006   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::ShowInputPanel\n");
1007
1008   if(mIMFContext)
1009   {
1010     ecore_imf_context_input_panel_show(mIMFContext);
1011   }
1012 }
1013
1014 void InputMethodContextEcoreWl::HideInputPanel()
1015 {
1016   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::HideInputPanel\n");
1017
1018   if(mIMFContext)
1019   {
1020     ecore_imf_context_input_panel_hide(mIMFContext);
1021   }
1022 }
1023
1024 Dali::InputMethodContext::KeyboardType InputMethodContextEcoreWl::GetKeyboardType()
1025 {
1026   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetKeyboardType\n");
1027
1028   if(mIMFContext)
1029   {
1030     int value;
1031     value = ecore_imf_context_keyboard_mode_get(mIMFContext);
1032
1033     switch(value)
1034     {
1035       case ECORE_IMF_INPUT_PANEL_SW_KEYBOARD_MODE:
1036       {
1037         return Dali::InputMethodContext::SOFTWARE_KEYBOARD;
1038         break;
1039       }
1040       case ECORE_IMF_INPUT_PANEL_HW_KEYBOARD_MODE:
1041       {
1042         return Dali::InputMethodContext::HARDWARE_KEYBOARD;
1043         break;
1044       }
1045     }
1046   }
1047
1048   return Dali::InputMethodContext::KeyboardType::SOFTWARE_KEYBOARD;
1049 }
1050
1051 std::string InputMethodContextEcoreWl::GetInputPanelLocale()
1052 {
1053   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetInputPanelLocale\n");
1054
1055   std::string locale = "";
1056
1057   if(mIMFContext)
1058   {
1059     char* value = NULL;
1060     ecore_imf_context_input_panel_language_locale_get(mIMFContext, &value);
1061
1062     if(value)
1063     {
1064       std::string valueCopy(value);
1065       locale = valueCopy;
1066
1067       // The locale string retrieved must be freed with free().
1068       free(value);
1069     }
1070   }
1071   return locale;
1072 }
1073
1074 void InputMethodContextEcoreWl::SetContentMIMETypes(const std::string& mimeTypes)
1075 {
1076   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SetContentMIMETypes\n");
1077
1078   if(mIMFContext)
1079   {
1080     ecore_imf_context_mime_type_accept_set(mIMFContext, mimeTypes.c_str());
1081   }
1082
1083   mBackupOperations[Operation::SET_CONTENT_MIME_TYPES] = std::bind(&InputMethodContextEcoreWl::SetContentMIMETypes, this, mimeTypes);
1084 }
1085
1086 bool InputMethodContextEcoreWl::FilterEventKey(const Dali::KeyEvent& keyEvent)
1087 {
1088   bool eventHandled(false);
1089
1090   // If a device key then skip ecore_imf_context_filter_event.
1091   if(!KeyLookup::IsDeviceButton(keyEvent.GetKeyName().c_str()))
1092   {
1093     //check whether it's key down or key up event
1094     if(keyEvent.GetState() == Dali::KeyEvent::DOWN)
1095     {
1096       eventHandled = ProcessEventKeyDown(keyEvent);
1097     }
1098     else if(keyEvent.GetState() == Dali::KeyEvent::UP)
1099     {
1100       eventHandled = ProcessEventKeyUp(keyEvent);
1101     }
1102   }
1103
1104   return eventHandled;
1105 }
1106
1107 void InputMethodContextEcoreWl::AllowTextPrediction(bool prediction)
1108 {
1109   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::AllowTextPrediction\n");
1110
1111   if(mIMFContext)
1112   {
1113     ecore_imf_context_prediction_allow_set(mIMFContext, prediction);
1114   }
1115
1116   mBackupOperations[Operation::ALLOW_TEXT_PREDICTION] = std::bind(&InputMethodContextEcoreWl::AllowTextPrediction, this, prediction);
1117 }
1118
1119 bool InputMethodContextEcoreWl::IsTextPredictionAllowed() const
1120 {
1121   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::IsTextPredictionAllowed\n");
1122   bool prediction = false;
1123   if(mIMFContext)
1124   {
1125     prediction = ecore_imf_context_prediction_allow_get(mIMFContext);
1126   }
1127   return prediction;
1128 }
1129
1130 void InputMethodContextEcoreWl::SetInputPanelLanguage(Dali::InputMethodContext::InputPanelLanguage language)
1131 {
1132   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SetInputPanelLanguage\n");
1133   if(mIMFContext)
1134   {
1135     switch(language)
1136     {
1137       case Dali::InputMethodContext::InputPanelLanguage::AUTOMATIC:
1138       {
1139         ecore_imf_context_input_panel_language_set(mIMFContext, ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC);
1140         break;
1141       }
1142       case Dali::InputMethodContext::InputPanelLanguage::ALPHABET:
1143       {
1144         ecore_imf_context_input_panel_language_set(mIMFContext, ECORE_IMF_INPUT_PANEL_LANG_ALPHABET);
1145         break;
1146       }
1147     }
1148   }
1149
1150   mBackupOperations[Operation::SET_INPUT_PANEL_LANGUAGE] = std::bind(&InputMethodContextEcoreWl::SetInputPanelLanguage, this, language);
1151 }
1152
1153 Dali::InputMethodContext::InputPanelLanguage InputMethodContextEcoreWl::GetInputPanelLanguage() const
1154 {
1155   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetInputPanelLanguage\n");
1156   if(mIMFContext)
1157   {
1158     int value;
1159     value = ecore_imf_context_input_panel_language_get(mIMFContext);
1160
1161     switch(value)
1162     {
1163       case ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC:
1164       {
1165         return Dali::InputMethodContext::InputPanelLanguage::AUTOMATIC;
1166         break;
1167       }
1168       case ECORE_IMF_INPUT_PANEL_LANG_ALPHABET:
1169       {
1170         return Dali::InputMethodContext::InputPanelLanguage::ALPHABET;
1171         break;
1172       }
1173     }
1174   }
1175   return Dali::InputMethodContext::InputPanelLanguage::AUTOMATIC;
1176 }
1177
1178 void InputMethodContextEcoreWl::SetInputPanelPosition(unsigned int x, unsigned int y)
1179 {
1180   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SetInputPanelPosition\n");
1181
1182   if(mIMFContext)
1183   {
1184     ecore_imf_context_input_panel_position_set(mIMFContext, x, y);
1185   }
1186
1187   mBackupOperations[Operation::SET_INPUT_PANEL_POSITION] = std::bind(&InputMethodContextEcoreWl::SetInputPanelPosition, this, x, y);
1188 }
1189
1190 void InputMethodContextEcoreWl::GetPreeditStyle(Dali::InputMethodContext::PreEditAttributeDataContainer& attrs) const
1191 {
1192   DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetPreeditStyle\n");
1193   attrs = mPreeditAttrs;
1194 }
1195
1196 bool InputMethodContextEcoreWl::ProcessEventKeyDown(const Dali::KeyEvent& keyEvent)
1197 {
1198   bool eventHandled(false);
1199   if(mIMFContext)
1200   {
1201     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());
1202     std::string           key = integKeyEvent.logicalKey;
1203
1204     std::string compose    = integKeyEvent.compose;
1205     std::string deviceName = integKeyEvent.deviceName;
1206
1207     // We're consuming key down event so we have to pass to InputMethodContext so that it can parse it as well.
1208     Ecore_IMF_Event_Key_Down ecoreKeyDownEvent;
1209     ecoreKeyDownEvent.keyname      = integKeyEvent.keyName.c_str();
1210     ecoreKeyDownEvent.key          = key.c_str();
1211     ecoreKeyDownEvent.string       = integKeyEvent.keyString.c_str();
1212     ecoreKeyDownEvent.compose      = compose.c_str();
1213     ecoreKeyDownEvent.timestamp    = static_cast<uint32_t>(integKeyEvent.time);
1214     ecoreKeyDownEvent.modifiers    = EcoreInputModifierToEcoreIMFModifier(integKeyEvent.keyModifier);
1215     ecoreKeyDownEvent.locks        = EcoreInputModifierToEcoreIMFLock(integKeyEvent.keyModifier);
1216     ecoreKeyDownEvent.dev_name     = deviceName.c_str();
1217     ecoreKeyDownEvent.dev_class    = static_cast<Ecore_IMF_Device_Class>(integKeyEvent.deviceClass);       //ECORE_IMF_DEVICE_CLASS_KEYBOARD;
1218     ecoreKeyDownEvent.dev_subclass = static_cast<Ecore_IMF_Device_Subclass>(integKeyEvent.deviceSubclass); //ECORE_IMF_DEVICE_SUBCLASS_NONE;
1219 #if defined(ECORE_VERSION_MAJOR) && (ECORE_VERSION_MAJOR >= 1) && defined(ECORE_VERSION_MINOR) && (ECORE_VERSION_MINOR >= 22)
1220     ecoreKeyDownEvent.keycode = integKeyEvent.keyCode; // Ecore_IMF_Event structure has added 'keycode' variable since ecore_imf 1.22 version.
1221 #endif                                                 // Since ecore_imf 1.22 version
1222
1223     // 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.
1224     if((integKeyEvent.deviceName == "ime") && ((!strncmp(integKeyEvent.keyName.c_str(), "Left", 4)) ||
1225                                                (!strncmp(integKeyEvent.keyName.c_str(), "Right", 5)) ||
1226                                                (!strncmp(integKeyEvent.keyName.c_str(), "Up", 2)) ||
1227                                                (!strncmp(integKeyEvent.keyName.c_str(), "Down", 4))))
1228     {
1229       eventHandled = 0;
1230     }
1231     else
1232     {
1233       eventHandled = ecore_imf_context_filter_event(mIMFContext,
1234                                                     ECORE_IMF_EVENT_KEY_DOWN,
1235                                                     reinterpret_cast<Ecore_IMF_Event*>(&ecoreKeyDownEvent));
1236     }
1237
1238     // If the event has not been handled by InputMethodContext then check if we should reset our input method context
1239     if(!eventHandled)
1240     {
1241       if(!strcmp(integKeyEvent.keyName.c_str(), "Escape") ||
1242          !strcmp(integKeyEvent.keyName.c_str(), "Return") ||
1243          !strcmp(integKeyEvent.keyName.c_str(), "KP_Enter"))
1244       {
1245         ecore_imf_context_reset(mIMFContext);
1246       }
1247     }
1248   }
1249   return eventHandled;
1250 }
1251
1252 bool InputMethodContextEcoreWl::ProcessEventKeyUp(const Dali::KeyEvent& keyEvent)
1253 {
1254   bool eventHandled(false);
1255   if(mIMFContext)
1256   {
1257     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());
1258     std::string           key = integKeyEvent.logicalKey;
1259
1260     std::string compose    = integKeyEvent.compose;
1261     std::string deviceName = integKeyEvent.deviceName;
1262
1263     // We're consuming key up event so we have to pass to InputMethodContext so that it can parse it as well.
1264     Ecore_IMF_Event_Key_Up ecoreKeyUpEvent;
1265     ecoreKeyUpEvent.keyname      = integKeyEvent.keyName.c_str();
1266     ecoreKeyUpEvent.key          = key.c_str();
1267     ecoreKeyUpEvent.string       = integKeyEvent.keyString.c_str();
1268     ecoreKeyUpEvent.compose      = compose.c_str();
1269     ecoreKeyUpEvent.timestamp    = static_cast<uint32_t>(integKeyEvent.time);
1270     ecoreKeyUpEvent.modifiers    = EcoreInputModifierToEcoreIMFModifier(integKeyEvent.keyModifier);
1271     ecoreKeyUpEvent.locks        = EcoreInputModifierToEcoreIMFLock(integKeyEvent.keyModifier);
1272     ecoreKeyUpEvent.dev_name     = deviceName.c_str();
1273     ecoreKeyUpEvent.dev_class    = static_cast<Ecore_IMF_Device_Class>(integKeyEvent.deviceClass);       //ECORE_IMF_DEVICE_CLASS_KEYBOARD;
1274     ecoreKeyUpEvent.dev_subclass = static_cast<Ecore_IMF_Device_Subclass>(integKeyEvent.deviceSubclass); //ECORE_IMF_DEVICE_SUBCLASS_NONE;
1275 #if defined(ECORE_VERSION_MAJOR) && (ECORE_VERSION_MAJOR >= 1) && defined(ECORE_VERSION_MINOR) && (ECORE_VERSION_MINOR >= 22)
1276     ecoreKeyUpEvent.keycode = integKeyEvent.keyCode; // Ecore_IMF_Event structure has added 'keycode' variable since ecore_imf 1.22 version.
1277 #endif                                               // Since ecore_imf 1.22 version
1278
1279     eventHandled = ecore_imf_context_filter_event(mIMFContext,
1280                                                   ECORE_IMF_EVENT_KEY_UP,
1281                                                   reinterpret_cast<Ecore_IMF_Event*>(&ecoreKeyUpEvent));
1282   }
1283   return eventHandled;
1284 }
1285
1286 Ecore_IMF_Keyboard_Modifiers InputMethodContextEcoreWl::EcoreInputModifierToEcoreIMFModifier(unsigned int ecoreModifier)
1287 {
1288   unsigned int modifier(ECORE_IMF_KEYBOARD_MODIFIER_NONE); // If no other matches returns NONE.
1289
1290   if(ecoreModifier & ECORE_EVENT_MODIFIER_SHIFT) // enums from ecore_input/Ecore_Input.h
1291   {
1292     modifier |= ECORE_IMF_KEYBOARD_MODIFIER_SHIFT; // enums from ecore_imf/ecore_imf.h
1293   }
1294
1295   if(ecoreModifier & ECORE_EVENT_MODIFIER_ALT)
1296   {
1297     modifier |= ECORE_IMF_KEYBOARD_MODIFIER_ALT;
1298   }
1299
1300   if(ecoreModifier & ECORE_EVENT_MODIFIER_CTRL)
1301   {
1302     modifier |= ECORE_IMF_KEYBOARD_MODIFIER_CTRL;
1303   }
1304
1305   if(ecoreModifier & ECORE_EVENT_MODIFIER_WIN)
1306   {
1307     modifier |= ECORE_IMF_KEYBOARD_MODIFIER_WIN;
1308   }
1309
1310   if(ecoreModifier & ECORE_EVENT_MODIFIER_ALTGR)
1311   {
1312     modifier |= ECORE_IMF_KEYBOARD_MODIFIER_ALTGR;
1313   }
1314
1315   return static_cast<Ecore_IMF_Keyboard_Modifiers>(modifier);
1316 }
1317
1318 Ecore_IMF_Keyboard_Locks InputMethodContextEcoreWl::EcoreInputModifierToEcoreIMFLock(unsigned int modifier)
1319 {
1320   unsigned int lock(ECORE_IMF_KEYBOARD_LOCK_NONE); // If no other matches, returns NONE.
1321
1322   if(modifier & ECORE_EVENT_LOCK_NUM)
1323   {
1324     lock |= ECORE_IMF_KEYBOARD_LOCK_NUM; // Num lock is active.
1325   }
1326
1327   if(modifier & ECORE_EVENT_LOCK_CAPS)
1328   {
1329     lock |= ECORE_IMF_KEYBOARD_LOCK_CAPS; // Caps lock is active.
1330   }
1331
1332   if(modifier & ECORE_EVENT_LOCK_SCROLL)
1333   {
1334     lock |= ECORE_IMF_KEYBOARD_LOCK_SCROLL; // Scroll lock is active.
1335   }
1336
1337   return static_cast<Ecore_IMF_Keyboard_Locks>(lock);
1338 }
1339
1340 void InputMethodContextEcoreWl::OnStaged(Dali::Actor actor)
1341 {
1342   int windowId = GetWindowIdFromActor(actor);
1343
1344   if(mWindowId != windowId)
1345   {
1346     mWindowId = windowId;
1347
1348     // Reset
1349     Finalize();
1350     Initialize();
1351   }
1352 }
1353
1354 } // namespace Adaptor
1355
1356 } // namespace Internal
1357
1358 } // namespace Dali