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