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