Remove the wearable definition in Makefile.am
[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 BaseHandle Create()
213 {
214   return ImfManager::Get();
215 }
216
217 TypeRegistration IMF_MANAGER_TYPE( typeid(Dali::ImfManager), typeid(Dali::BaseHandle), Create );
218
219 } // unnamed namespace
220
221 bool ImfManager::IsAvailable()
222 {
223   bool available( false );
224
225   Dali::SingletonService service( SingletonService::Get() );
226   if ( service )
227   {
228     available = service.GetSingleton( typeid( Dali::ImfManager ) );
229   }
230
231   return available;
232 }
233
234 Dali::ImfManager ImfManager::Get()
235 {
236   Dali::ImfManager manager;
237
238   Dali::SingletonService service( SingletonService::Get() );
239   if ( service )
240   {
241     // Check whether the singleton is already created
242     Dali::BaseHandle handle = service.GetSingleton( typeid( Dali::ImfManager ) );
243     if( handle )
244     {
245       // If so, downcast the handle
246       manager = Dali::ImfManager( dynamic_cast< ImfManager* >( handle.GetObjectPtr() ) );
247     }
248     else if ( Adaptor::IsAvailable() )
249     {
250       // Create instance and register singleton only if the adaptor is available
251
252       Adaptor& adaptorImpl( Adaptor::GetImplementation( Adaptor::Get() ) );
253       Any nativeWindow = adaptorImpl.GetNativeWindowHandle();
254
255       // The Ecore_Wl_Window needs to use the ImfManager.
256       // Only when the render surface is window, we can get the Ecore_Wl_Window.
257       Ecore_Wl_Window *ecoreWwin( AnyCast< Ecore_Wl_Window* >( nativeWindow ) );
258       if (ecoreWwin)
259       {
260         // If we fail to get Ecore_Wl_Window, we can't use the ImfManager correctly.
261         // Thus you have to call "ecore_imf_context_client_window_set" somewhere.
262         // In EvasPlugIn, this function is called in EvasPlugin::ConnectEcoreEvent().
263
264         manager = Dali::ImfManager( new ImfManager( ecoreWwin ) );
265         service.Register( typeid( manager ), manager );
266       }
267       else
268       {
269         DALI_LOG_ERROR("Failed to get native window handle\n");
270       }
271     }
272   }
273
274   return manager;
275 }
276
277 ImfManager::ImfManager( Ecore_Wl_Window *ecoreWlwin )
278 : mIMFContext(),
279   mIMFCursorPosition( 0 ),
280   mSurroundingText(),
281   mRestoreAfterFocusLost( false ),
282   mIdleCallbackConnected( false )
283 {
284   ecore_imf_init();
285   CreateContext( ecoreWlwin );
286
287   ConnectCallbacks();
288 }
289
290 ImfManager::~ImfManager()
291 {
292   DisconnectCallbacks();
293
294   DeleteContext();
295   ecore_imf_shutdown();
296 }
297
298
299 void ImfManager::CreateContext( Ecore_Wl_Window *ecoreWlwin )
300 {
301   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::CreateContext\n" );
302
303   const char *contextId = ecore_imf_context_default_id_get();
304   if( contextId )
305   {
306     mIMFContext = ecore_imf_context_add( contextId );
307
308     if( mIMFContext )
309     {
310       if( ecoreWlwin )
311       {
312           ecore_imf_context_client_window_set( mIMFContext,
313             reinterpret_cast<void*>( ecore_wl_window_id_get(ecoreWlwin)) );
314       }
315     }
316     else
317     {
318       DALI_LOG_WARNING("IMF Unable to get IMF Context\n");
319     }
320   }
321   else
322   {
323     DALI_LOG_WARNING("IMF Unable to get IMF Context\n");
324   }
325 }
326
327 void ImfManager::DeleteContext()
328 {
329   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::DeleteContext\n" );
330
331   if ( mIMFContext )
332   {
333     mIMFContext = NULL;
334   }
335 }
336
337 // Callbacks for predicitive text support.
338 void ImfManager::ConnectCallbacks()
339 {
340   if ( mIMFContext )
341   {
342     DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::ConnectCallbacks\n" );
343
344     ecore_imf_context_event_callback_add( mIMFContext, ECORE_IMF_CALLBACK_PREEDIT_CHANGED,    PreEdit,    this );
345     ecore_imf_context_event_callback_add( mIMFContext, ECORE_IMF_CALLBACK_COMMIT,             Commit,     this );
346     ecore_imf_context_event_callback_add( mIMFContext, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, ImfDeleteSurrounding, this );
347
348     ecore_imf_context_input_panel_event_callback_add( mIMFContext, ECORE_IMF_INPUT_PANEL_STATE_EVENT,    InputPanelStateChangeCallback, this );
349     ecore_imf_context_input_panel_event_callback_add( mIMFContext, ECORE_IMF_INPUT_PANEL_LANGUAGE_EVENT, InputPanelLanguageChangeCallback, this );
350     ecore_imf_context_input_panel_event_callback_add( mIMFContext, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, InputPanelGeometryChangedCallback, this );
351
352     ecore_imf_context_retrieve_surrounding_callback_set( mIMFContext, ImfRetrieveSurrounding, this);
353   }
354 }
355
356 void ImfManager::DisconnectCallbacks()
357 {
358   if ( mIMFContext )
359   {
360     DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::DisconnectCallbacks\n" );
361
362     ecore_imf_context_event_callback_del( mIMFContext, ECORE_IMF_CALLBACK_PREEDIT_CHANGED,    PreEdit );
363     ecore_imf_context_event_callback_del( mIMFContext, ECORE_IMF_CALLBACK_COMMIT,             Commit );
364     ecore_imf_context_event_callback_del( mIMFContext, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, ImfDeleteSurrounding );
365
366     ecore_imf_context_input_panel_event_callback_del( mIMFContext, ECORE_IMF_INPUT_PANEL_STATE_EVENT,    InputPanelStateChangeCallback     );
367     ecore_imf_context_input_panel_event_callback_del( mIMFContext, ECORE_IMF_INPUT_PANEL_LANGUAGE_EVENT, InputPanelLanguageChangeCallback  );
368     ecore_imf_context_input_panel_event_callback_del( mIMFContext, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, InputPanelGeometryChangedCallback );
369
370     // We do not need to unset the retrieve surrounding callback.
371   }
372 }
373
374 void ImfManager::Activate()
375 {
376   // Reset mIdleCallbackConnected
377   mIdleCallbackConnected = false;
378
379   if ( mIMFContext )
380   {
381     DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::Activate\n" );
382
383     ecore_imf_context_focus_in( mIMFContext );
384
385     // emit keyboard activated signal
386     Dali::ImfManager handle( this );
387     mActivatedSignal.Emit( handle );
388   }
389 }
390
391 void ImfManager::Deactivate()
392 {
393   if( mIMFContext )
394   {
395     DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::Deactivate\n" );
396
397     Reset();
398     ecore_imf_context_focus_out( mIMFContext );
399   }
400
401   // Reset mIdleCallbackConnected
402   mIdleCallbackConnected = false;
403 }
404
405 void ImfManager::Reset()
406 {
407   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::Reset\n" );
408
409   if ( mIMFContext )
410   {
411     ecore_imf_context_reset( mIMFContext );
412   }
413 }
414
415 Ecore_IMF_Context* ImfManager::GetContext()
416 {
417   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetContext\n" );
418
419   return mIMFContext;
420 }
421
422 bool ImfManager::RestoreAfterFocusLost() const
423 {
424   return mRestoreAfterFocusLost;
425 }
426
427 void ImfManager::SetRestoreAfterFocusLost( bool toggle )
428 {
429   mRestoreAfterFocusLost = toggle;
430 }
431
432 /**
433  * Called when an IMF Pre-Edit changed event is received.
434  * We are still predicting what the user is typing.  The latest string is what the IMF module thinks
435  * the user wants to type.
436  */
437 void ImfManager::PreEditChanged( void*, Ecore_IMF_Context* imfContext, void* event_info )
438 {
439   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::PreEditChanged\n" );
440
441   char* preEditString( NULL );
442   int cursorPosition( 0 );
443   Eina_List* attrs = NULL;
444   Eina_List* l = NULL;
445
446   Ecore_IMF_Preedit_Attr* attr;
447
448   // Retrieves attributes as well as the string the cursor position offset from start of pre-edit string.
449   // the attributes (attrs) is used in languages that use the soft arrows keys to insert characters into a current pre-edit string.
450   ecore_imf_context_preedit_string_with_attributes_get( imfContext, &preEditString, &attrs, &cursorPosition );
451
452   if ( attrs )
453   {
454     // iterate through the list of attributes getting the type, start and end position.
455     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) ) ))
456     {
457 #ifdef DALI_PROFILE_UBUNTU
458       if ( attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB3 ) // (Ecore_IMF)
459 #else // DALI_PROFILE_UBUNTU
460       if ( attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB4 ) // (Ecore_IMF)
461 #endif // DALI_PROFILE_UBUNTU
462       {
463         // 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.
464
465         size_t visualCharacterIndex = 0;
466         size_t byteIndex = 0;
467
468         // iterate through null terminated string checking each character's position against the given byte position ( attr->end_index ).
469         const char leadByte = preEditString[byteIndex];
470         while( leadByte != '\0' )
471         {
472           // attr->end_index is provided as a byte position not character and we need to know the character position.
473           const size_t currentSequenceLength = Utf8SequenceLength( leadByte ); // returns number of bytes used to represent character.
474           if ( byteIndex == attr->end_index )
475           {
476             cursorPosition = visualCharacterIndex;
477             break;
478             // end loop as found cursor position that matches byte position
479           }
480           else
481           {
482             byteIndex += currentSequenceLength; // jump to next character
483             visualCharacterIndex++;  // increment character count so we know our position for when we get a match
484           }
485
486           DALI_ASSERT_DEBUG( visualCharacterIndex < strlen( preEditString ));
487         }
488       }
489     }
490   }
491
492   if ( Dali::Adaptor::IsAvailable() )
493   {
494     Dali::ImfManager handle( this );
495     Dali::ImfManager::ImfEventData imfEventData( Dali::ImfManager::PREEDIT, preEditString, cursorPosition, 0 );
496     Dali::ImfManager::ImfCallbackData callbackData = mEventSignal.Emit( handle, imfEventData );
497
498     if ( callbackData.update )
499     {
500       SetCursorPosition( callbackData.cursorPosition );
501       SetSurroundingText( callbackData.currentText );
502
503       NotifyCursorPosition();
504     }
505
506     if ( callbackData.preeditResetRequired )
507     {
508       Reset();
509     }
510   }
511   free( preEditString );
512 }
513
514 void ImfManager::CommitReceived( void*, Ecore_IMF_Context* imfContext, void* event_info )
515 {
516   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::CommitReceived\n" );
517
518   if ( Dali::Adaptor::IsAvailable() )
519   {
520     const std::string keyString( static_cast<char*>( event_info ) );
521
522     Dali::ImfManager handle( this );
523     Dali::ImfManager::ImfEventData imfEventData( Dali::ImfManager::COMMIT, keyString, 0, 0 );
524     Dali::ImfManager::ImfCallbackData callbackData = mEventSignal.Emit( handle, imfEventData );
525
526     if( callbackData.update )
527     {
528       SetCursorPosition( callbackData.cursorPosition );
529       SetSurroundingText( callbackData.currentText );
530
531       NotifyCursorPosition();
532     }
533   }
534 }
535
536 /**
537  * Called when an IMF retrieve surround event is received.
538  * Here the IMF module wishes to know the string we are working with and where within the string the cursor is
539  * We need to signal the application to tell us this information.
540  */
541 Eina_Bool ImfManager::RetrieveSurrounding( void* data, Ecore_IMF_Context* imfContext, char** text, int* cursorPosition )
542 {
543   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::RetrieveSurrounding\n" );
544
545   Dali::ImfManager::ImfEventData imfData( Dali::ImfManager::GETSURROUNDING, std::string(), 0, 0 );
546   Dali::ImfManager handle( this );
547   mEventSignal.Emit( handle, imfData );
548
549   if( text )
550   {
551     *text = strdup( mSurroundingText.c_str() );
552   }
553
554   if( cursorPosition )
555   {
556     *cursorPosition = mIMFCursorPosition;
557   }
558
559   return EINA_TRUE;
560 }
561
562 /**
563  * Called when an IMF delete surrounding event is received.
564  * Here we tell the application that it should delete a certain range.
565  */
566 void ImfManager::DeleteSurrounding( void* data, Ecore_IMF_Context* imfContext, void* event_info )
567 {
568   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::DeleteSurrounding\n" );
569
570   if( Dali::Adaptor::IsAvailable() )
571   {
572     Ecore_IMF_Event_Delete_Surrounding* deleteSurroundingEvent = static_cast<Ecore_IMF_Event_Delete_Surrounding*>( event_info );
573
574     Dali::ImfManager::ImfEventData imfData( Dali::ImfManager::DELETESURROUNDING, std::string(), deleteSurroundingEvent->offset, deleteSurroundingEvent->n_chars );
575     Dali::ImfManager handle( this );
576     mEventSignal.Emit( handle, imfData );
577   }
578 }
579
580 void ImfManager::NotifyCursorPosition()
581 {
582   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::NotifyCursorPosition\n" );
583
584   if( mIMFContext )
585   {
586     ecore_imf_context_cursor_position_set( mIMFContext, mIMFCursorPosition );
587   }
588 }
589
590 void ImfManager::SetCursorPosition( unsigned int cursorPosition )
591 {
592   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::SetCursorPosition\n" );
593
594   mIMFCursorPosition = static_cast<int>( cursorPosition );
595 }
596
597 unsigned int ImfManager::GetCursorPosition() const
598 {
599   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetCursorPosition\n" );
600
601   return static_cast<unsigned int>( mIMFCursorPosition );
602 }
603
604 void ImfManager::SetSurroundingText( const std::string& text )
605 {
606   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::SetSurroundingText\n" );
607
608   mSurroundingText = text;
609 }
610
611 const std::string& ImfManager::GetSurroundingText() const
612 {
613   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetSurroundingText\n" );
614
615   return mSurroundingText;
616 }
617
618 void ImfManager::NotifyTextInputMultiLine( bool multiLine )
619 {
620   Ecore_IMF_Input_Hints currentHint = ecore_imf_context_input_hint_get(mIMFContext);
621   ecore_imf_context_input_hint_set(mIMFContext, (Ecore_IMF_Input_Hints)(multiLine ?
622     (currentHint | ECORE_IMF_INPUT_HINT_MULTILINE) :
623     (currentHint & ~ECORE_IMF_INPUT_HINT_MULTILINE)));
624 }
625
626 Dali::ImfManager::TextDirection ImfManager::GetTextDirection()
627 {
628   Dali::ImfManager::TextDirection direction ( Dali::ImfManager::LeftToRight );
629
630   if ( ImfManager::IsAvailable() /* We do not want to create an instance of ImfManager */ )
631   {
632     if ( mIMFContext )
633     {
634       char* locale( NULL );
635       ecore_imf_context_input_panel_language_locale_get( mIMFContext, &locale );
636
637       if ( locale )
638       {
639         direction = Locale::GetTextDirection( std::string( locale ) );
640         free( locale );
641       }
642     }
643   }
644   return direction;
645 }
646
647 Rect<int> ImfManager::GetInputMethodArea()
648 {
649   int xPos, yPos, width, height;
650
651   width = height = xPos = yPos = 0;
652
653   if( mIMFContext )
654   {
655     ecore_imf_context_input_panel_geometry_get( mIMFContext, &xPos, &yPos, &width, &height );
656   }
657   else
658   {
659     DALI_LOG_WARNING("VKB Unable to get IMF Context so GetSize unavailable\n");
660   // return 0 as real size unknown.
661   }
662
663   return Rect<int>(xPos,yPos,width,height);
664 }
665
666 void ImfManager::ApplyOptions( const InputMethodOptions& options )
667 {
668   using namespace Dali::InputMethod::Category;
669
670   int index;
671
672   if (mIMFContext == NULL)
673   {
674     DALI_LOG_WARNING("VKB Unable to excute ApplyOptions with Null ImfContext\n");
675     return;
676   }
677
678   if ( mOptions.CompareAndSet(PANEL_LAYOUT, options, index) )
679   {
680     ecore_imf_context_input_panel_layout_set( mIMFContext, panelLayoutMap[index] );
681   }
682   if ( mOptions.CompareAndSet(AUTO_CAPITALISE, options, index) )
683   {
684     ecore_imf_context_autocapital_type_set( mIMFContext, autoCapitalMap[index] );
685   }
686   if ( mOptions.CompareAndSet(ACTION_BUTTON_TITLE, options, index) )
687   {
688     ecore_imf_context_input_panel_return_key_type_set( mIMFContext, returnKeyTypeMap[index] );
689   }
690   if ( mOptions.CompareAndSet(VARIATION, options, index) )
691   {
692     ecore_imf_context_input_panel_layout_variation_set( mIMFContext, index );
693   }
694 }
695
696 } // Adaptor
697
698 } // Internal
699
700 } // Dali