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