[Tizen] Fix Set and Get InputPanelUserData()
[platform/core/uifw/dali-adaptor.git] / adaptors / ecore / wayland / imf-manager-impl-ecore-wl.cpp
1 /*
2  * Copyright (c) 2017 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 // Ecore is littered with C style cast
20 #pragma GCC diagnostic push
21 #pragma GCC diagnostic ignored "-Wold-style-cast"
22 #include <imf-manager-impl.h>
23
24 // EXTERNAL INCLUDES
25 #include <dali/public-api/events/key-event.h>
26 #include <dali/public-api/object/type-registry.h>
27 #include <dali/integration-api/debug.h>
28
29 // INTERNAL INCLUDES
30 #include <input-method-devel.h>
31 #include <adaptor.h>
32 #include <locale-utils.h>
33 #include <window-render-surface.h>
34 #include <adaptor-impl.h>
35 #include <singleton-service-impl.h>
36
37 #define TOKEN_STRING(x) #x
38
39 Ecore_IMF_Input_Panel_Layout panelLayoutMap[] =
40 {
41    ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL,
42    ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBER,
43    ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL,
44    ECORE_IMF_INPUT_PANEL_LAYOUT_URL,
45    ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER,
46    ECORE_IMF_INPUT_PANEL_LAYOUT_IP,
47    ECORE_IMF_INPUT_PANEL_LAYOUT_MONTH,
48    ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY,
49    ECORE_IMF_INPUT_PANEL_LAYOUT_HEX,
50    ECORE_IMF_INPUT_PANEL_LAYOUT_TERMINAL,
51    ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD,
52    ECORE_IMF_INPUT_PANEL_LAYOUT_DATETIME,
53    ECORE_IMF_INPUT_PANEL_LAYOUT_EMOTICON,
54    ECORE_IMF_INPUT_PANEL_LAYOUT_VOICE
55 };
56
57 Ecore_IMF_Autocapital_Type autoCapitalMap[] =
58 {
59    ECORE_IMF_AUTOCAPITAL_TYPE_NONE,
60    ECORE_IMF_AUTOCAPITAL_TYPE_WORD,
61    ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE,
62    ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER,
63 };
64
65 Ecore_IMF_Input_Panel_Return_Key_Type returnKeyTypeMap[] =
66 {
67    ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT,
68    ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DONE,
69    ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_GO,
70    ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_JOIN,
71    ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_LOGIN,
72    ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_NEXT,
73    ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SEARCH,
74    ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SEND,
75    ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SIGNIN
76 };
77
78 namespace Dali
79 {
80
81 namespace Internal
82 {
83
84 namespace Adaptor
85 {
86
87 namespace
88 {
89 #if defined(DEBUG_ENABLED)
90 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_IMF_MANAGER");
91 #endif
92
93 // Currently this code is internal to dali/dali/internal/event/text/utf8.h but should be made Public and used from there instead.
94 size_t Utf8SequenceLength(const unsigned char leadByte)
95 {
96   size_t length = 0;
97
98   if ((leadByte & 0x80) == 0 )          //ASCII character (lead bit zero)
99   {
100     length = 1;
101   }
102   else if (( leadByte & 0xe0 ) == 0xc0 ) //110x xxxx
103   {
104     length = 2;
105   }
106   else if (( leadByte & 0xf0 ) == 0xe0 ) //1110 xxxx
107   {
108     length = 3;
109   }
110   else if (( leadByte & 0xf8 ) == 0xf0 ) //1111 0xxx
111   {
112     length = 4;
113   }
114
115   return length;
116 }
117
118 // Static function calls used by ecore 'c' style callback registration
119 void Commit( void *data, Ecore_IMF_Context *imfContext, void *event_info )
120 {
121   if ( data )
122   {
123     ImfManager* imfManager = reinterpret_cast< ImfManager* > ( data );
124     imfManager->CommitReceived( data, imfContext, event_info );
125   }
126 }
127
128 void PreEdit( void *data, Ecore_IMF_Context *imfContext, void *event_info )
129 {
130   if ( data )
131   {
132     ImfManager* imfManager = reinterpret_cast< ImfManager* > ( data );
133     imfManager->PreEditChanged( data, imfContext, event_info );
134   }
135 }
136
137 Eina_Bool ImfRetrieveSurrounding(void *data, Ecore_IMF_Context *imfContext, char** text, int* cursorPosition )
138 {
139   if ( data )
140   {
141     ImfManager* imfManager = reinterpret_cast< ImfManager* > ( data );
142     return imfManager->RetrieveSurrounding( data, imfContext, text, cursorPosition );
143   }
144   else
145   {
146     return false;
147   }
148 }
149
150 void InputPanelStateChangeCallback( void* data, Ecore_IMF_Context* context, int value )
151 {
152   if (!data)
153   {
154     return;
155   }
156   ImfManager* imfManager = reinterpret_cast< ImfManager* > ( data );
157   switch (value)
158   {
159     case ECORE_IMF_INPUT_PANEL_STATE_SHOW:
160     {
161       imfManager->StatusChangedSignal().Emit( true );
162       break;
163     }
164
165     case ECORE_IMF_INPUT_PANEL_STATE_HIDE:
166     {
167       imfManager->StatusChangedSignal().Emit( false );
168       break;
169     }
170
171     case ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW:
172     default:
173     {
174       // Do nothing
175       break;
176     }
177   }
178 }
179
180 void InputPanelLanguageChangeCallback( void* data, Ecore_IMF_Context* context, int value )
181 {
182   if (!data)
183   {
184     return;
185   }
186   ImfManager* imfManager = reinterpret_cast< ImfManager* > ( data );
187   // Emit the signal that the language has changed
188   imfManager->LanguageChangedSignal().Emit();
189 }
190
191 void InputPanelGeometryChangedCallback ( void *data, Ecore_IMF_Context *context, int value )
192 {
193   if (!data)
194   {
195     return;
196   }
197   ImfManager* imfManager = reinterpret_cast< ImfManager* > ( data );
198   // Emit signal that the keyboard is resized
199   imfManager->ResizedSignal().Emit();
200 }
201
202 void InputPanelKeyboardTypeChangedCallback( void *data, Ecore_IMF_Context *context, int value )
203 {
204   if( !data )
205   {
206     return;
207   }
208
209   ImfManager* imfManager = reinterpret_cast< ImfManager* > ( data );
210   switch (value)
211   {
212     case ECORE_IMF_INPUT_PANEL_SW_KEYBOARD_MODE:
213     {
214       // Emit Signal that the keyboard type is changed to Software Keyboard
215       imfManager->KeyboardTypeChangedSignal().Emit( Dali::ImfManager::KeyboardType::SOFTWARE_KEYBOARD );
216       break;
217     }
218     case ECORE_IMF_INPUT_PANEL_HW_KEYBOARD_MODE:
219     {
220       // Emit Signal that the keyboard type is changed to Hardware Keyboard
221       imfManager->KeyboardTypeChangedSignal().Emit( Dali::ImfManager::KeyboardType::HARDWARE_KEYBOARD );
222       break;
223     }
224   }
225 }
226
227 /**
228  * Called when an IMF delete surrounding event is received.
229  * Here we tell the application that it should delete a certain range.
230  */
231 void ImfDeleteSurrounding( void *data, Ecore_IMF_Context *imfContext, void *event_info )
232 {
233   if ( data )
234   {
235     ImfManager* imfManager = reinterpret_cast< ImfManager* > ( data );
236     imfManager->DeleteSurrounding( data, imfContext, event_info );
237   }
238 }
239
240 /**
241  * Called when the input method sends a private command.
242  */
243 void PrivateCommand( void *data, Ecore_IMF_Context *imfContext, void *event_info )
244 {
245   if ( data )
246   {
247     ImfManager* imfManager = reinterpret_cast< ImfManager* > ( data );
248     imfManager->SendPrivateCommand( data, imfContext, event_info );
249   }
250 }
251
252 BaseHandle Create()
253 {
254   return ImfManager::Get();
255 }
256
257 TypeRegistration IMF_MANAGER_TYPE( typeid(Dali::ImfManager), typeid(Dali::BaseHandle), Create );
258
259 } // unnamed namespace
260
261 bool ImfManager::IsAvailable()
262 {
263   bool available( false );
264
265   Dali::SingletonService service( SingletonService::Get() );
266   if ( service )
267   {
268     available = service.GetSingleton( typeid( Dali::ImfManager ) );
269   }
270
271   return available;
272 }
273
274 Dali::ImfManager ImfManager::Get()
275 {
276   Dali::ImfManager manager;
277
278   Dali::SingletonService service( SingletonService::Get() );
279   if ( service )
280   {
281     // Check whether the singleton is already created
282     Dali::BaseHandle handle = service.GetSingleton( typeid( Dali::ImfManager ) );
283     if( handle )
284     {
285       // If so, downcast the handle
286       manager = Dali::ImfManager( dynamic_cast< ImfManager* >( handle.GetObjectPtr() ) );
287     }
288     else if ( Adaptor::IsAvailable() )
289     {
290       // Create instance and register singleton only if the adaptor is available
291
292       Adaptor& adaptorImpl( Adaptor::GetImplementation( Adaptor::Get() ) );
293       Any nativeWindow = adaptorImpl.GetNativeWindowHandle();
294
295       // The Ecore_Wl_Window needs to use the ImfManager.
296       // Only when the render surface is window, we can get the Ecore_Wl_Window.
297       Ecore_Wl_Window *ecoreWwin( AnyCast< Ecore_Wl_Window* >( nativeWindow ) );
298       if (ecoreWwin)
299       {
300         // If we fail to get Ecore_Wl_Window, we can't use the ImfManager correctly.
301         // Thus you have to call "ecore_imf_context_client_window_set" somewhere.
302         // In EvasPlugIn, this function is called in EvasPlugin::ConnectEcoreEvent().
303
304         manager = Dali::ImfManager( new ImfManager( ecoreWwin ) );
305         service.Register( typeid( manager ), manager );
306       }
307       else
308       {
309         DALI_LOG_ERROR("Failed to get native window handle\n");
310       }
311     }
312   }
313
314   return manager;
315 }
316
317 ImfManager::ImfManager( Ecore_Wl_Window *ecoreWlwin )
318 : mIMFContext(),
319   mIMFCursorPosition( 0 ),
320   mSurroundingText(),
321   mRestoreAfterFocusLost( false ),
322   mIdleCallbackConnected( false )
323 {
324   ecore_imf_init();
325   CreateContext( ecoreWlwin );
326
327   ConnectCallbacks();
328 }
329
330 ImfManager::~ImfManager()
331 {
332   DisconnectCallbacks();
333
334   DeleteContext();
335   ecore_imf_shutdown();
336 }
337
338
339 void ImfManager::CreateContext( Ecore_Wl_Window *ecoreWlwin )
340 {
341   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::CreateContext\n" );
342
343   const char *contextId = ecore_imf_context_default_id_get();
344   if( contextId )
345   {
346     mIMFContext = ecore_imf_context_add( contextId );
347
348     if( mIMFContext )
349     {
350       if( ecoreWlwin )
351       {
352           ecore_imf_context_client_window_set( mIMFContext,
353             reinterpret_cast<void*>( ecore_wl_window_id_get(ecoreWlwin)) );
354       }
355     }
356     else
357     {
358       DALI_LOG_WARNING("IMF Unable to get IMF Context\n");
359     }
360   }
361   else
362   {
363     DALI_LOG_WARNING("IMF Unable to get IMF Context\n");
364   }
365 }
366
367 void ImfManager::DeleteContext()
368 {
369   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::DeleteContext\n" );
370
371   if ( mIMFContext )
372   {
373     ecore_imf_context_del( mIMFContext );
374     mIMFContext = NULL;
375   }
376 }
377
378 // Callbacks for predicitive text support.
379 void ImfManager::ConnectCallbacks()
380 {
381   if ( mIMFContext )
382   {
383     DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::ConnectCallbacks\n" );
384
385     ecore_imf_context_event_callback_add( mIMFContext, ECORE_IMF_CALLBACK_PREEDIT_CHANGED,      PreEdit,    this );
386     ecore_imf_context_event_callback_add( mIMFContext, ECORE_IMF_CALLBACK_COMMIT,               Commit,     this );
387     ecore_imf_context_event_callback_add( mIMFContext, ECORE_IMF_CALLBACK_DELETE_SURROUNDING,   ImfDeleteSurrounding, this );
388     ecore_imf_context_event_callback_add( mIMFContext, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, PrivateCommand, this );
389
390     ecore_imf_context_input_panel_event_callback_add( mIMFContext, ECORE_IMF_INPUT_PANEL_STATE_EVENT,    InputPanelStateChangeCallback, this );
391     ecore_imf_context_input_panel_event_callback_add( mIMFContext, ECORE_IMF_INPUT_PANEL_LANGUAGE_EVENT, InputPanelLanguageChangeCallback, this );
392     ecore_imf_context_input_panel_event_callback_add( mIMFContext, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, InputPanelGeometryChangedCallback, this );
393     ecore_imf_context_input_panel_event_callback_add( mIMFContext, ECORE_IMF_INPUT_PANEL_KEYBOARD_MODE_EVENT, InputPanelKeyboardTypeChangedCallback, this );
394
395     ecore_imf_context_retrieve_surrounding_callback_set( mIMFContext, ImfRetrieveSurrounding, this);
396   }
397 }
398
399 void ImfManager::DisconnectCallbacks()
400 {
401   if ( mIMFContext )
402   {
403     DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::DisconnectCallbacks\n" );
404
405     ecore_imf_context_event_callback_del( mIMFContext, ECORE_IMF_CALLBACK_PREEDIT_CHANGED,      PreEdit );
406     ecore_imf_context_event_callback_del( mIMFContext, ECORE_IMF_CALLBACK_COMMIT,               Commit );
407     ecore_imf_context_event_callback_del( mIMFContext, ECORE_IMF_CALLBACK_DELETE_SURROUNDING,   ImfDeleteSurrounding );
408     ecore_imf_context_event_callback_del( mIMFContext, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, PrivateCommand );
409
410     ecore_imf_context_input_panel_event_callback_del( mIMFContext, ECORE_IMF_INPUT_PANEL_STATE_EVENT,    InputPanelStateChangeCallback     );
411     ecore_imf_context_input_panel_event_callback_del( mIMFContext, ECORE_IMF_INPUT_PANEL_LANGUAGE_EVENT, InputPanelLanguageChangeCallback  );
412     ecore_imf_context_input_panel_event_callback_del( mIMFContext, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, InputPanelGeometryChangedCallback );
413     ecore_imf_context_input_panel_event_callback_del( mIMFContext, ECORE_IMF_INPUT_PANEL_KEYBOARD_MODE_EVENT, InputPanelKeyboardTypeChangedCallback );
414
415     // We do not need to unset the retrieve surrounding callback.
416   }
417 }
418
419 void ImfManager::Activate()
420 {
421   // Reset mIdleCallbackConnected
422   mIdleCallbackConnected = false;
423
424   if ( mIMFContext )
425   {
426     DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::Activate\n" );
427
428     ecore_imf_context_focus_in( mIMFContext );
429
430     // emit keyboard activated signal
431     Dali::ImfManager handle( this );
432     mActivatedSignal.Emit( handle );
433   }
434 }
435
436 void ImfManager::Deactivate()
437 {
438   if( mIMFContext )
439   {
440     DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::Deactivate\n" );
441
442     Reset();
443     ecore_imf_context_focus_out( mIMFContext );
444   }
445
446   // Reset mIdleCallbackConnected
447   mIdleCallbackConnected = false;
448 }
449
450 void ImfManager::Reset()
451 {
452   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::Reset\n" );
453
454   if ( mIMFContext )
455   {
456     ecore_imf_context_reset( mIMFContext );
457   }
458 }
459
460 Ecore_IMF_Context* ImfManager::GetContext()
461 {
462   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetContext\n" );
463
464   return mIMFContext;
465 }
466
467 bool ImfManager::RestoreAfterFocusLost() const
468 {
469   return mRestoreAfterFocusLost;
470 }
471
472 void ImfManager::SetRestoreAfterFocusLost( bool toggle )
473 {
474   mRestoreAfterFocusLost = toggle;
475 }
476
477 /**
478  * Called when an IMF Pre-Edit changed event is received.
479  * We are still predicting what the user is typing.  The latest string is what the IMF module thinks
480  * the user wants to type.
481  */
482 void ImfManager::PreEditChanged( void*, Ecore_IMF_Context* imfContext, void* event_info )
483 {
484   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::PreEditChanged\n" );
485
486   char* preEditString( NULL );
487   int cursorPosition( 0 );
488   Eina_List* attrs = NULL;
489   Eina_List* l = NULL;
490
491   Ecore_IMF_Preedit_Attr* attr;
492
493   // Retrieves attributes as well as the string the cursor position offset from start of pre-edit string.
494   // the attributes (attrs) is used in languages that use the soft arrows keys to insert characters into a current pre-edit string.
495   ecore_imf_context_preedit_string_with_attributes_get( imfContext, &preEditString, &attrs, &cursorPosition );
496
497   if ( attrs )
498   {
499     // iterate through the list of attributes getting the type, start and end position.
500     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) ) ))
501     {
502 #ifdef DALI_PROFILE_UBUNTU
503       if ( attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB3 ) // (Ecore_IMF)
504 #else // DALI_PROFILE_UBUNTU
505       if ( attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB4 ) // (Ecore_IMF)
506 #endif // DALI_PROFILE_UBUNTU
507       {
508         // 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.
509
510         size_t visualCharacterIndex = 0;
511         size_t byteIndex = 0;
512
513         // iterate through null terminated string checking each character's position against the given byte position ( attr->end_index ).
514         const char leadByte = preEditString[byteIndex];
515         while( leadByte != '\0' )
516         {
517           // attr->end_index is provided as a byte position not character and we need to know the character position.
518           const size_t currentSequenceLength = Utf8SequenceLength( leadByte ); // returns number of bytes used to represent character.
519           if ( byteIndex == attr->end_index )
520           {
521             cursorPosition = visualCharacterIndex;
522             break;
523             // end loop as found cursor position that matches byte position
524           }
525           else
526           {
527             byteIndex += currentSequenceLength; // jump to next character
528             visualCharacterIndex++;  // increment character count so we know our position for when we get a match
529           }
530
531           DALI_ASSERT_DEBUG( visualCharacterIndex < strlen( preEditString ));
532         }
533       }
534     }
535   }
536
537   if ( Dali::Adaptor::IsAvailable() )
538   {
539     Dali::ImfManager handle( this );
540     Dali::ImfManager::ImfEventData imfEventData( Dali::ImfManager::PREEDIT, preEditString, cursorPosition, 0 );
541     Dali::ImfManager::ImfCallbackData callbackData = mEventSignal.Emit( handle, imfEventData );
542
543     if ( callbackData.update )
544     {
545       SetCursorPosition( callbackData.cursorPosition );
546       SetSurroundingText( callbackData.currentText );
547
548       NotifyCursorPosition();
549     }
550
551     if ( callbackData.preeditResetRequired )
552     {
553       Reset();
554     }
555   }
556   free( preEditString );
557 }
558
559 void ImfManager::CommitReceived( void*, Ecore_IMF_Context* imfContext, void* event_info )
560 {
561   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::CommitReceived\n" );
562
563   if ( Dali::Adaptor::IsAvailable() )
564   {
565     const std::string keyString( static_cast<char*>( event_info ) );
566
567     Dali::ImfManager handle( this );
568     Dali::ImfManager::ImfEventData imfEventData( Dali::ImfManager::COMMIT, keyString, 0, 0 );
569     Dali::ImfManager::ImfCallbackData callbackData = mEventSignal.Emit( handle, imfEventData );
570
571     if( callbackData.update )
572     {
573       SetCursorPosition( callbackData.cursorPosition );
574       SetSurroundingText( callbackData.currentText );
575
576       NotifyCursorPosition();
577     }
578   }
579 }
580
581 /**
582  * Called when an IMF retrieve surround event is received.
583  * Here the IMF module wishes to know the string we are working with and where within the string the cursor is
584  * We need to signal the application to tell us this information.
585  */
586 Eina_Bool ImfManager::RetrieveSurrounding( void* data, Ecore_IMF_Context* imfContext, char** text, int* cursorPosition )
587 {
588   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::RetrieveSurrounding\n" );
589
590   Dali::ImfManager::ImfEventData imfData( Dali::ImfManager::GETSURROUNDING, std::string(), 0, 0 );
591   Dali::ImfManager handle( this );
592   mEventSignal.Emit( handle, imfData );
593
594   if( text )
595   {
596     *text = strdup( mSurroundingText.c_str() );
597   }
598
599   if( cursorPosition )
600   {
601     *cursorPosition = mIMFCursorPosition;
602   }
603
604   return EINA_TRUE;
605 }
606
607 /**
608  * Called when an IMF delete surrounding event is received.
609  * Here we tell the application that it should delete a certain range.
610  */
611 void ImfManager::DeleteSurrounding( void* data, Ecore_IMF_Context* imfContext, void* event_info )
612 {
613   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::DeleteSurrounding\n" );
614
615   if( Dali::Adaptor::IsAvailable() )
616   {
617     Ecore_IMF_Event_Delete_Surrounding* deleteSurroundingEvent = static_cast<Ecore_IMF_Event_Delete_Surrounding*>( event_info );
618
619     Dali::ImfManager::ImfEventData imfData( Dali::ImfManager::DELETESURROUNDING, std::string(), deleteSurroundingEvent->offset, deleteSurroundingEvent->n_chars );
620     Dali::ImfManager handle( this );
621     mEventSignal.Emit( handle, imfData );
622   }
623 }
624
625 /**
626  * Called when the input method sends a private command.
627  */
628 void ImfManager::SendPrivateCommand( void* data, Ecore_IMF_Context* imfContext, void* event_info )
629 {
630   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::SendPrivateCommand\n" );
631
632   if( Dali::Adaptor::IsAvailable() )
633   {
634     const char* privateCommandSendEvent = static_cast<const char*>( event_info );
635
636     Dali::ImfManager::ImfEventData imfData( Dali::ImfManager::PRIVATECOMMAND, privateCommandSendEvent, 0, 0 );
637     Dali::ImfManager handle( this );
638     mEventSignal.Emit( handle, imfData );
639   }
640 }
641
642 void ImfManager::NotifyCursorPosition()
643 {
644   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::NotifyCursorPosition\n" );
645
646   if( mIMFContext )
647   {
648     ecore_imf_context_cursor_position_set( mIMFContext, mIMFCursorPosition );
649   }
650 }
651
652 void ImfManager::SetCursorPosition( unsigned int cursorPosition )
653 {
654   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::SetCursorPosition\n" );
655
656   mIMFCursorPosition = static_cast<int>( cursorPosition );
657 }
658
659 unsigned int ImfManager::GetCursorPosition() const
660 {
661   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetCursorPosition\n" );
662
663   return static_cast<unsigned int>( mIMFCursorPosition );
664 }
665
666 void ImfManager::SetSurroundingText( const std::string& text )
667 {
668   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::SetSurroundingText\n" );
669
670   mSurroundingText = text;
671 }
672
673 const std::string& ImfManager::GetSurroundingText() const
674 {
675   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetSurroundingText\n" );
676
677   return mSurroundingText;
678 }
679
680 void ImfManager::NotifyTextInputMultiLine( bool multiLine )
681 {
682   Ecore_IMF_Input_Hints currentHint = ecore_imf_context_input_hint_get(mIMFContext);
683   ecore_imf_context_input_hint_set( mIMFContext,
684                                     static_cast< Ecore_IMF_Input_Hints >( multiLine ?
685                                       (currentHint | ECORE_IMF_INPUT_HINT_MULTILINE) :
686                                       (currentHint & ~ECORE_IMF_INPUT_HINT_MULTILINE)));
687 }
688
689 Dali::ImfManager::TextDirection ImfManager::GetTextDirection()
690 {
691   Dali::ImfManager::TextDirection direction ( Dali::ImfManager::LeftToRight );
692
693   if ( ImfManager::IsAvailable() /* We do not want to create an instance of ImfManager */ )
694   {
695     if ( mIMFContext )
696     {
697       char* locale( NULL );
698       ecore_imf_context_input_panel_language_locale_get( mIMFContext, &locale );
699
700       if ( locale )
701       {
702         direction = Locale::GetTextDirection( std::string( locale ) );
703         free( locale );
704       }
705     }
706   }
707   return direction;
708 }
709
710 Rect<int> ImfManager::GetInputMethodArea()
711 {
712   int xPos, yPos, width, height;
713
714   width = height = xPos = yPos = 0;
715
716   if( mIMFContext )
717   {
718     ecore_imf_context_input_panel_geometry_get( mIMFContext, &xPos, &yPos, &width, &height );
719   }
720   else
721   {
722     DALI_LOG_WARNING("VKB Unable to get IMF Context so GetSize unavailable\n");
723   // return 0 as real size unknown.
724   }
725
726   return Rect<int>(xPos,yPos,width,height);
727 }
728
729 void ImfManager::ApplyOptions( const InputMethodOptions& options )
730 {
731   using namespace Dali::InputMethod::Category;
732
733   int index;
734
735   if (mIMFContext == NULL)
736   {
737     DALI_LOG_WARNING("VKB Unable to excute ApplyOptions with Null ImfContext\n");
738     return;
739   }
740
741   if ( mOptions.CompareAndSet(PANEL_LAYOUT, options, index) )
742   {
743     ecore_imf_context_input_panel_layout_set( mIMFContext, panelLayoutMap[index] );
744   }
745   if ( mOptions.CompareAndSet(AUTO_CAPITALISE, options, index) )
746   {
747     ecore_imf_context_autocapital_type_set( mIMFContext, autoCapitalMap[index] );
748   }
749   if ( mOptions.CompareAndSet(ACTION_BUTTON_TITLE, options, index) )
750   {
751     ecore_imf_context_input_panel_return_key_type_set( mIMFContext, returnKeyTypeMap[index] );
752   }
753   if ( mOptions.CompareAndSet(VARIATION, options, index) )
754   {
755     ecore_imf_context_input_panel_layout_variation_set( mIMFContext, index );
756   }
757 }
758
759 void ImfManager::SetInputPanelUserData( const std::string& data )
760 {
761   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::SetInputPanelUserData\n" );
762
763   if( mIMFContext )
764   {
765     int length = data.length();
766     ecore_imf_context_input_panel_imdata_set( mIMFContext, data.c_str(), length );
767   }
768 }
769
770 void ImfManager::GetInputPanelUserData( std::string& data )
771 {
772   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetInputPanelUserData\n" );
773
774   if( mIMFContext )
775   {
776     int length = 256;
777     char* buffer = reinterpret_cast< char* >( calloc ( 1, length * sizeof ( char ) ) );
778     if( buffer != NULL )
779     {
780       ecore_imf_context_input_panel_imdata_get( mIMFContext, buffer, &length );
781       data = buffer;
782       free( buffer );
783     }
784   }
785 }
786
787 Dali::ImfManager::State ImfManager::GetInputPanelState()
788 {
789   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetInputPanelState\n" );
790
791   if( mIMFContext )
792   {
793     int value;
794     value = ecore_imf_context_input_panel_state_get( mIMFContext );
795
796     switch (value)
797     {
798       case ECORE_IMF_INPUT_PANEL_STATE_SHOW:
799       {
800         return Dali::ImfManager::SHOW;
801         break;
802       }
803
804       case ECORE_IMF_INPUT_PANEL_STATE_HIDE:
805       {
806         return Dali::ImfManager::HIDE;
807         break;
808       }
809
810       case ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW:
811       {
812         return Dali::ImfManager::WILL_SHOW;
813         break;
814       }
815
816       default:
817       {
818         return Dali::ImfManager::DEFAULT;
819       }
820     }
821   }
822   return Dali::ImfManager::DEFAULT;
823 }
824
825 void ImfManager::SetReturnKeyState( bool visible )
826 {
827   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::SetReturnKeyState\n" );
828
829   if( mIMFContext )
830   {
831     ecore_imf_context_input_panel_return_key_disabled_set( mIMFContext, !visible );
832   }
833 }
834
835 void ImfManager::AutoEnableInputPanel( bool enabled )
836 {
837   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::AutoEnableInputPanel\n" );
838
839   if( mIMFContext )
840   {
841     ecore_imf_context_input_panel_enabled_set( mIMFContext, enabled );
842   }
843 }
844
845 void ImfManager::ShowInputPanel()
846 {
847   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::ShowInputPanel\n" );
848
849   if( mIMFContext )
850   {
851     ecore_imf_context_input_panel_show( mIMFContext );
852   }
853 }
854
855 void ImfManager::HideInputPanel()
856 {
857   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::HideInputPanel\n" );
858
859   if( mIMFContext )
860   {
861     ecore_imf_context_input_panel_hide( mIMFContext );
862   }
863 }
864
865 Dali::ImfManager::KeyboardType ImfManager::GetKeyboardType()
866 {
867   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetKeyboardType\n" );
868
869 #ifdef OVER_TIZEN_VERSION_4
870   if( mIMFContext )
871   {
872     int value;
873     value = ecore_imf_context_keyboard_mode_get( mIMFContext );
874
875     switch (value)
876     {
877       case ECORE_IMF_INPUT_PANEL_SW_KEYBOARD_MODE:
878       {
879         return Dali::ImfManager::SOFTWARE_KEYBOARD;
880         break;
881       }
882       case ECORE_IMF_INPUT_PANEL_HW_KEYBOARD_MODE:
883       {
884         return Dali::ImfManager::HARDWARE_KEYBOARD;
885         break;
886       }
887     }
888   }
889 #endif // OVER_TIZEN_VERSION_4
890   return Dali::ImfManager::KeyboardType::SOFTWARE_KEYBOARD;
891 }
892
893 std::string ImfManager::GetInputPanelLocale()
894 {
895   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetInputPanelLocale\n" );
896
897   std::string locale = "";
898
899   if( mIMFContext )
900   {
901     char* value = NULL;
902     ecore_imf_context_input_panel_language_locale_get( mIMFContext, &value );
903
904     if( value )
905     {
906       std::string valueCopy( value );
907       locale = valueCopy;
908
909       // The locale string retrieved must be freed with free().
910       free( value );
911     }
912   }
913   return locale;
914 }
915
916 } // Adaptor
917
918 } // Internal
919
920 } // Dali
921
922 #pragma GCC diagnostic pop