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