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