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