Merge "Support touch cancel event" into devel/master
[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     ecore_imf_context_input_panel_hide( mIMFContext );
415   }
416
417   // Reset mIdleCallbackConnected
418   mIdleCallbackConnected = false;
419 }
420
421 void ImfManager::Reset()
422 {
423   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::Reset\n" );
424
425   if ( mIMFContext )
426   {
427     ecore_imf_context_reset( mIMFContext );
428   }
429 }
430
431 Ecore_IMF_Context* ImfManager::GetContext()
432 {
433   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetContext\n" );
434
435   return mIMFContext;
436 }
437
438 bool ImfManager::RestoreAfterFocusLost() const
439 {
440   return mRestoreAfterFocusLost;
441 }
442
443 void ImfManager::SetRestoreAfterFocusLost( bool toggle )
444 {
445   mRestoreAfterFocusLost = toggle;
446 }
447
448 /**
449  * Called when an IMF Pre-Edit changed event is received.
450  * We are still predicting what the user is typing.  The latest string is what the IMF module thinks
451  * the user wants to type.
452  */
453 void ImfManager::PreEditChanged( void*, Ecore_IMF_Context* imfContext, void* event_info )
454 {
455   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::PreEditChanged\n" );
456
457   char* preEditString( NULL );
458   int cursorPosition( 0 );
459   Eina_List* attrs = NULL;
460   Eina_List* l = NULL;
461
462   Ecore_IMF_Preedit_Attr* attr;
463
464   // Retrieves attributes as well as the string the cursor position offset from start of pre-edit string.
465   // the attributes (attrs) is used in languages that use the soft arrows keys to insert characters into a current pre-edit string.
466   ecore_imf_context_preedit_string_with_attributes_get( imfContext, &preEditString, &attrs, &cursorPosition );
467
468   if ( attrs )
469   {
470     // iterate through the list of attributes getting the type, start and end position.
471     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) ) ))
472     {
473 #ifdef DALI_PROFILE_UBUNTU
474       if ( attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB3 ) // (Ecore_IMF)
475 #else // DALI_PROFILE_UBUNTU
476       if ( attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB4 ) // (Ecore_IMF)
477 #endif // DALI_PROFILE_UBUNTU
478       {
479         // 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.
480
481         size_t visualCharacterIndex = 0;
482         size_t byteIndex = 0;
483
484         // iterate through null terminated string checking each character's position against the given byte position ( attr->end_index ).
485         const char leadByte = preEditString[byteIndex];
486         while( leadByte != '\0' )
487         {
488           // attr->end_index is provided as a byte position not character and we need to know the character position.
489           const size_t currentSequenceLength = Utf8SequenceLength( leadByte ); // returns number of bytes used to represent character.
490           if ( byteIndex == attr->end_index )
491           {
492             cursorPosition = visualCharacterIndex;
493             break;
494             // end loop as found cursor position that matches byte position
495           }
496           else
497           {
498             byteIndex += currentSequenceLength; // jump to next character
499             visualCharacterIndex++;  // increment character count so we know our position for when we get a match
500           }
501
502           DALI_ASSERT_DEBUG( visualCharacterIndex < strlen( preEditString ));
503         }
504       }
505     }
506   }
507
508   if ( Dali::Adaptor::IsAvailable() )
509   {
510     Dali::ImfManager handle( this );
511     Dali::ImfManager::ImfEventData imfEventData( Dali::ImfManager::PREEDIT, preEditString, cursorPosition, 0 );
512     Dali::ImfManager::ImfCallbackData callbackData = mEventSignal.Emit( handle, imfEventData );
513
514     if ( callbackData.update )
515     {
516       SetCursorPosition( callbackData.cursorPosition );
517       SetSurroundingText( callbackData.currentText );
518
519       NotifyCursorPosition();
520     }
521
522     if ( callbackData.preeditResetRequired )
523     {
524       Reset();
525     }
526   }
527   free( preEditString );
528 }
529
530 void ImfManager::CommitReceived( void*, Ecore_IMF_Context* imfContext, void* event_info )
531 {
532   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::CommitReceived\n" );
533
534   if ( Dali::Adaptor::IsAvailable() )
535   {
536     const std::string keyString( static_cast<char*>( event_info ) );
537
538     Dali::ImfManager handle( this );
539     Dali::ImfManager::ImfEventData imfEventData( Dali::ImfManager::COMMIT, keyString, 0, 0 );
540     Dali::ImfManager::ImfCallbackData callbackData = mEventSignal.Emit( handle, imfEventData );
541
542     if( callbackData.update )
543     {
544       SetCursorPosition( callbackData.cursorPosition );
545       SetSurroundingText( callbackData.currentText );
546
547       NotifyCursorPosition();
548     }
549   }
550 }
551
552 /**
553  * Called when an IMF retrieve surround event is received.
554  * Here the IMF module wishes to know the string we are working with and where within the string the cursor is
555  * We need to signal the application to tell us this information.
556  */
557 Eina_Bool ImfManager::RetrieveSurrounding( void* data, Ecore_IMF_Context* imfContext, char** text, int* cursorPosition )
558 {
559   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::RetrieveSurrounding\n" );
560
561   Dali::ImfManager::ImfEventData imfData( Dali::ImfManager::GETSURROUNDING, std::string(), 0, 0 );
562   Dali::ImfManager handle( this );
563   mEventSignal.Emit( handle, imfData );
564
565   if( text )
566   {
567     *text = strdup( mSurroundingText.c_str() );
568   }
569
570   if( cursorPosition )
571   {
572     *cursorPosition = mIMFCursorPosition;
573   }
574
575   return EINA_TRUE;
576 }
577
578 /**
579  * Called when an IMF delete surrounding event is received.
580  * Here we tell the application that it should delete a certain range.
581  */
582 void ImfManager::DeleteSurrounding( void* data, Ecore_IMF_Context* imfContext, void* event_info )
583 {
584   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::DeleteSurrounding\n" );
585
586   if( Dali::Adaptor::IsAvailable() )
587   {
588     Ecore_IMF_Event_Delete_Surrounding* deleteSurroundingEvent = static_cast<Ecore_IMF_Event_Delete_Surrounding*>( event_info );
589
590     Dali::ImfManager::ImfEventData imfData( Dali::ImfManager::DELETESURROUNDING, std::string(), deleteSurroundingEvent->offset, deleteSurroundingEvent->n_chars );
591     Dali::ImfManager handle( this );
592     mEventSignal.Emit( handle, imfData );
593   }
594 }
595
596 /**
597  * Called when the input method sends a private command.
598  */
599 void ImfManager::SendPrivateCommand( void* data, Ecore_IMF_Context* imfContext, void* event_info )
600 {
601   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::SendPrivateCommand\n" );
602
603   if( Dali::Adaptor::IsAvailable() )
604   {
605     const char* privateCommandSendEvent = static_cast<const char*>( event_info );
606
607     Dali::ImfManager::ImfEventData imfData( Dali::ImfManager::PRIVATECOMMAND, privateCommandSendEvent, 0, 0 );
608     Dali::ImfManager handle( this );
609     mEventSignal.Emit( handle, imfData );
610   }
611 }
612
613 void ImfManager::NotifyCursorPosition()
614 {
615   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::NotifyCursorPosition\n" );
616
617   if( mIMFContext )
618   {
619     ecore_imf_context_cursor_position_set( mIMFContext, mIMFCursorPosition );
620   }
621 }
622
623 void ImfManager::SetCursorPosition( unsigned int cursorPosition )
624 {
625   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::SetCursorPosition\n" );
626
627   mIMFCursorPosition = static_cast<int>( cursorPosition );
628 }
629
630 unsigned int ImfManager::GetCursorPosition() const
631 {
632   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetCursorPosition\n" );
633
634   return static_cast<unsigned int>( mIMFCursorPosition );
635 }
636
637 void ImfManager::SetSurroundingText( const std::string& text )
638 {
639   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::SetSurroundingText\n" );
640
641   mSurroundingText = text;
642 }
643
644 const std::string& ImfManager::GetSurroundingText() const
645 {
646   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetSurroundingText\n" );
647
648   return mSurroundingText;
649 }
650
651 void ImfManager::NotifyTextInputMultiLine( bool multiLine )
652 {
653   Ecore_IMF_Input_Hints currentHint = ecore_imf_context_input_hint_get(mIMFContext);
654   ecore_imf_context_input_hint_set(mIMFContext, (Ecore_IMF_Input_Hints)(multiLine ?
655     (currentHint | ECORE_IMF_INPUT_HINT_MULTILINE) :
656     (currentHint & ~ECORE_IMF_INPUT_HINT_MULTILINE)));
657 }
658
659 Dali::ImfManager::TextDirection ImfManager::GetTextDirection()
660 {
661   Dali::ImfManager::TextDirection direction ( Dali::ImfManager::LeftToRight );
662
663   if ( ImfManager::IsAvailable() /* We do not want to create an instance of ImfManager */ )
664   {
665     if ( mIMFContext )
666     {
667       char* locale( NULL );
668       ecore_imf_context_input_panel_language_locale_get( mIMFContext, &locale );
669
670       if ( locale )
671       {
672         direction = Locale::GetTextDirection( std::string( locale ) );
673         free( locale );
674       }
675     }
676   }
677   return direction;
678 }
679
680 Rect<int> ImfManager::GetInputMethodArea()
681 {
682   int xPos, yPos, width, height;
683
684   width = height = xPos = yPos = 0;
685
686   if( mIMFContext )
687   {
688     ecore_imf_context_input_panel_geometry_get( mIMFContext, &xPos, &yPos, &width, &height );
689   }
690   else
691   {
692     DALI_LOG_WARNING("VKB Unable to get IMF Context so GetSize unavailable\n");
693   // return 0 as real size unknown.
694   }
695
696   return Rect<int>(xPos,yPos,width,height);
697 }
698
699 void ImfManager::ApplyOptions( const InputMethodOptions& options )
700 {
701   using namespace Dali::InputMethod::Category;
702
703   int index;
704
705   if (mIMFContext == NULL)
706   {
707     DALI_LOG_WARNING("VKB Unable to excute ApplyOptions with Null ImfContext\n");
708     return;
709   }
710
711   if ( mOptions.CompareAndSet(PANEL_LAYOUT, options, index) )
712   {
713     ecore_imf_context_input_panel_layout_set( mIMFContext, panelLayoutMap[index] );
714   }
715   if ( mOptions.CompareAndSet(AUTO_CAPITALISE, options, index) )
716   {
717     ecore_imf_context_autocapital_type_set( mIMFContext, autoCapitalMap[index] );
718   }
719   if ( mOptions.CompareAndSet(ACTION_BUTTON_TITLE, options, index) )
720   {
721     ecore_imf_context_input_panel_return_key_type_set( mIMFContext, returnKeyTypeMap[index] );
722   }
723   if ( mOptions.CompareAndSet(VARIATION, options, index) )
724   {
725     ecore_imf_context_input_panel_layout_variation_set( mIMFContext, index );
726   }
727 }
728
729 void ImfManager::SetInputPanelUserData( const std::string& data )
730 {
731   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::SetInputPanelUserData\n" );
732
733   if( mIMFContext )
734   {
735     int length = data.length();
736     ecore_imf_context_input_panel_imdata_set( mIMFContext, &data, length );
737   }
738 }
739
740 void ImfManager::GetInputPanelUserData( std::string& data )
741 {
742   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetInputPanelUserData\n" );
743
744   if( mIMFContext )
745   {
746     int* length = NULL;
747     ecore_imf_context_input_panel_imdata_get( mIMFContext, &data, length );
748   }
749 }
750
751 Dali::ImfManager::State ImfManager::GetInputPanelState()
752 {
753   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetInputPanelState\n" );
754
755   if( mIMFContext )
756   {
757     int value;
758     value = ecore_imf_context_input_panel_state_get( mIMFContext );
759
760     switch (value)
761     {
762       case ECORE_IMF_INPUT_PANEL_STATE_SHOW:
763       {
764         return Dali::ImfManager::SHOW;
765         break;
766       }
767
768       case ECORE_IMF_INPUT_PANEL_STATE_HIDE:
769       {
770         return Dali::ImfManager::HIDE;
771         break;
772       }
773
774       case ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW:
775       {
776         return Dali::ImfManager::WILL_SHOW;
777         break;
778       }
779
780       default:
781       {
782         return Dali::ImfManager::DEFAULT;
783       }
784     }
785   }
786   return Dali::ImfManager::DEFAULT;
787 }
788
789 void ImfManager::SetReturnKeyState( bool visible )
790 {
791   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::SetReturnKeyState\n" );
792
793   if( mIMFContext )
794   {
795     ecore_imf_context_input_panel_return_key_disabled_set( mIMFContext, !visible );
796   }
797 }
798
799 void ImfManager::AutoEnableInputPanel( bool enabled )
800 {
801   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::AutoEnableInputPanel\n" );
802
803   if( mIMFContext )
804   {
805     ecore_imf_context_input_panel_enabled_set( mIMFContext, enabled );
806   }
807 }
808
809 void ImfManager::ShowInputPanel()
810 {
811   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::ShowInputPanel\n" );
812
813   if( mIMFContext )
814   {
815     ecore_imf_context_input_panel_show( mIMFContext );
816   }
817 }
818
819 void ImfManager::HideInputPanel()
820 {
821   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::HideInputPanel\n" );
822
823   if( mIMFContext )
824   {
825     ecore_imf_context_focus_out( mIMFContext );
826     ecore_imf_context_input_panel_hide( mIMFContext );
827   }
828 }
829
830 } // Adaptor
831
832 } // Internal
833
834 } // Dali