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