(ImfManager) Initialise ImfManager only when required rather than at startup
[platform/core/uifw/dali-adaptor.git] / adaptors / x11 / event-handler-x.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 <events/event-handler.h>
20
21 // EXTERNAL INCLUDES
22 #include <Ecore.h>
23 #include <Ecore_Input.h>
24 #include <Ecore_X.h>
25
26 #include <cstring>
27
28 #include <sys/time.h>
29
30 #ifndef DALI_PROFILE_UBUNTU
31 #include <vconf.h>
32 #include <vconf-keys.h>
33 #endif // DALI_PROFILE_UBUNTU
34
35 #include <dali/public-api/common/vector-wrapper.h>
36 #include <dali/public-api/events/touch-point.h>
37 #include <dali/public-api/events/key-event.h>
38 #include <dali/public-api/events/mouse-wheel-event.h>
39 #include <dali/integration-api/debug.h>
40 #include <dali/integration-api/events/key-event-integ.h>
41 #include <dali/integration-api/events/touch-event-integ.h>
42 #include <dali/integration-api/events/hover-event-integ.h>
43 #include <dali/integration-api/events/mouse-wheel-event-integ.h>
44
45 // INTERNAL INCLUDES
46 #include <events/gesture-manager.h>
47 #include <window-render-surface.h>
48 #include <clipboard-impl.h>
49 #include <key-impl.h>
50 #include <physical-keyboard-impl.h>
51 #include <style-monitor-impl.h>
52 #include <base/core-event-interface.h>
53
54 using namespace std;
55
56 namespace Dali
57 {
58
59 namespace Internal
60 {
61
62 namespace Adaptor
63 {
64
65 #if defined(DEBUG_ENABLED)
66 namespace
67 {
68 Integration::Log::Filter* gTouchEventLogFilter  = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_TOUCH");
69 Integration::Log::Filter* gClientMessageLogFilter  = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_CLIENT_MESSAGE");
70 Integration::Log::Filter* gDragAndDropLogFilter = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_DND");
71 Integration::Log::Filter* gImfLogging  = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_IMF");
72 Integration::Log::Filter* gSelectionEventLogFilter = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_SELECTION");
73 } // unnamed namespace
74 #endif
75
76
77 namespace
78 {
79 #ifndef DALI_PROFILE_UBUNTU
80 const char * DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_NAME = "db/setting/accessibility/font_name"; // It will be update at vconf-key.h and replaced.
81 #endif // DALI_PROFILE_UBUNTU
82
83 const unsigned int PRIMARY_TOUCH_BUTTON_ID( 1 );
84
85 #ifndef DALI_PROFILE_UBUNTU
86 const char * CLIPBOARD_ATOM                = "CBHM_MSG";
87 const char * CLIPBOARD_SET_OWNER_MESSAGE   = "SET_OWNER";
88 #endif // DALI_PROFILE_UBUNTU
89
90 /// The atoms required by Ecore for Drag & Drop behaviour.
91 Ecore_X_Atom DRAG_AND_DROP_ATOMS[] =
92 {
93   ECORE_X_ATOM_XDND_ACTION_COPY,
94 };
95
96 /// The types that we support.
97 const char * DRAG_AND_DROP_TYPES[] =
98 {
99   ECORE_X_SELECTION_TARGET_UTF8_STRING,
100 };
101
102 const unsigned int DRAG_AND_DROP_ATOMS_NUMBER = sizeof( DRAG_AND_DROP_ATOMS ) / sizeof( Ecore_X_Atom );
103 const unsigned int DRAG_AND_DROP_TYPES_NUMBER = sizeof( DRAG_AND_DROP_TYPES ) / sizeof( const char * );
104
105 const unsigned int BYTES_PER_CHARACTER_FOR_ATTRIBUTES = 3;
106
107 /**
108  * Ecore_Event_Modifier enums in Ecore_Input.h do not match Ecore_IMF_Keyboard_Modifiers in Ecore_IMF.h.
109  * This function converts from Ecore_Event_Modifier to Ecore_IMF_Keyboard_Modifiers enums.
110  * @param[in] ecoreModifier the Ecore_Event_Modifier input.
111  * @return the Ecore_IMF_Keyboard_Modifiers output.
112  */
113 Ecore_IMF_Keyboard_Modifiers EcoreInputModifierToEcoreIMFModifier(unsigned int ecoreModifier)
114 {
115    int modifier( ECORE_IMF_KEYBOARD_MODIFIER_NONE );  // If no other matches returns NONE.
116
117
118    if ( ecoreModifier & ECORE_EVENT_MODIFIER_SHIFT )  // enums from ecore_input/Ecore_Input.h
119    {
120      modifier |= ECORE_IMF_KEYBOARD_MODIFIER_SHIFT;  // enums from ecore_imf/ecore_imf.h
121    }
122
123    if ( ecoreModifier & ECORE_EVENT_MODIFIER_ALT )
124    {
125      modifier |= ECORE_IMF_KEYBOARD_MODIFIER_ALT;
126    }
127
128    if ( ecoreModifier & ECORE_EVENT_MODIFIER_CTRL )
129    {
130      modifier |= ECORE_IMF_KEYBOARD_MODIFIER_CTRL;
131    }
132
133    if ( ecoreModifier & ECORE_EVENT_MODIFIER_WIN )
134    {
135      modifier |= ECORE_IMF_KEYBOARD_MODIFIER_WIN;
136    }
137
138    if ( ecoreModifier & ECORE_EVENT_MODIFIER_ALTGR )
139    {
140      modifier |= ECORE_IMF_KEYBOARD_MODIFIER_ALTGR;
141    }
142
143    return static_cast<Ecore_IMF_Keyboard_Modifiers>( modifier );
144 }
145
146
147 // Copied from x server
148 static unsigned int GetCurrentMilliSeconds(void)
149 {
150   struct timeval tv;
151
152   struct timespec tp;
153   static clockid_t clockid;
154
155   if (!clockid)
156   {
157 #ifdef CLOCK_MONOTONIC_COARSE
158     if (clock_getres(CLOCK_MONOTONIC_COARSE, &tp) == 0 &&
159       (tp.tv_nsec / 1000) <= 1000 && clock_gettime(CLOCK_MONOTONIC_COARSE, &tp) == 0)
160     {
161       clockid = CLOCK_MONOTONIC_COARSE;
162     }
163     else
164 #endif
165     if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
166     {
167       clockid = CLOCK_MONOTONIC;
168     }
169     else
170     {
171       clockid = ~0L;
172     }
173   }
174   if (clockid != ~0L && clock_gettime(clockid, &tp) == 0)
175   {
176     return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
177   }
178
179   gettimeofday(&tv, NULL);
180   return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
181 }
182
183 } // unnamed namespace
184
185 // Impl to hide EFL implementation.
186 struct EventHandler::Impl
187 {
188   // Construction & Destruction
189
190   /**
191    * Constructor
192    */
193   Impl( EventHandler* handler, Ecore_X_Window window )
194   : mHandler( handler ),
195     mEcoreEventHandler(),
196     mWindow( window )
197   {
198     // Only register for touch and key events if we have a window
199     if ( window != 0 )
200     {
201       // Register Touch events
202       mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_EVENT_MOUSE_BUTTON_DOWN,  EcoreEventMouseButtonDown, handler ) );
203       mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_EVENT_MOUSE_BUTTON_UP,    EcoreEventMouseButtonUp,   handler ) );
204       mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_EVENT_MOUSE_MOVE,         EcoreEventMouseButtonMove, handler ) );
205       mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_EVENT_MOUSE_OUT,          EcoreEventMouseButtonUp,   handler ) ); // process mouse out event like up event
206
207       // Register Mouse wheel events
208       mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_EVENT_MOUSE_WHEEL,        EcoreEventMouseWheel,      handler ) );
209
210       // Register Key events
211       mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_EVENT_KEY_DOWN,           EcoreEventKeyDown,         handler ) );
212       mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_EVENT_KEY_UP,             EcoreEventKeyUp,           handler ) );
213
214       // Register Focus events
215       mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_X_EVENT_WINDOW_FOCUS_IN,  EcoreEventWindowFocusIn,   handler ) );
216       mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_X_EVENT_WINDOW_FOCUS_OUT, EcoreEventWindowFocusOut,  handler ) );
217
218       // Register Window damage events
219       mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_X_EVENT_WINDOW_DAMAGE,    EcoreEventWindowDamaged, handler ) );
220
221       // Enable Drag & Drop and register DnD events
222       ecore_x_dnd_aware_set( window, EINA_TRUE );
223       mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_X_EVENT_XDND_ENTER,       EcoreEventDndEnter,            handler) );
224       mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_X_EVENT_XDND_POSITION,    EcoreEventDndPosition,         handler) );
225       mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_X_EVENT_XDND_LEAVE,       EcoreEventDndLeave,            handler) );
226       mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_X_EVENT_XDND_DROP,        EcoreEventDndDrop,             handler) );
227       mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_X_EVENT_XDND_FINISHED,    EcoreEventDndFinished,         handler) );
228       mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_X_EVENT_XDND_STATUS,      EcoreEventDndStatus,           handler) );
229
230       // Register Client message events - accessibility etc.
231       mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_X_EVENT_CLIENT_MESSAGE,  EcoreEventClientMessage, handler ) );
232
233       // Register Selection event - clipboard selection, Drag & Drop selection etc.
234       mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_X_EVENT_SELECTION_CLEAR, EcoreEventSelectionClear, handler ) );
235       mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_X_EVENT_SELECTION_NOTIFY, EcoreEventSelectionNotify, handler ) );
236
237 #ifndef DALI_PROFILE_UBUNTU
238       // Register Vconf notify - font name, font size and style
239       vconf_notify_key_changed( DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_NAME, VconfNotifyFontNameChanged, handler );
240       vconf_notify_key_changed( VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, VconfNotifyFontSizeChanged, handler );
241 #if defined(DALI_PROFILE_MOBILE) || defined(DALI_PROFILE_LITE)
242       vconf_notify_key_changed( VCONFKEY_SETAPPL_CHANGE_UI_THEME_INT, VconfNotifyThemeChanged, handler );
243 #endif
244 #endif // DALI_PROFILE_UBUNTU
245     }
246   }
247
248   /**
249    * Destructor
250    */
251   ~Impl()
252   {
253 #ifndef DALI_PROFILE_UBUNTU
254 #if defined(DALI_PROFILE_MOBILE) || defined(DALI_PROFILE_LITE)
255     vconf_ignore_key_changed( VCONFKEY_SETAPPL_CHANGE_UI_THEME_INT, VconfNotifyThemeChanged );
256 #endif
257     vconf_ignore_key_changed( VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, VconfNotifyFontSizeChanged );
258     vconf_ignore_key_changed( DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_NAME, VconfNotifyFontNameChanged );
259 #endif // DALI_PROFILE_UBUNTU
260
261     for( std::vector<Ecore_Event_Handler*>::iterator iter = mEcoreEventHandler.begin(), endIter = mEcoreEventHandler.end(); iter != endIter; ++iter )
262     {
263       ecore_event_handler_del( *iter );
264     }
265   }
266
267   // Static methods
268
269   /////////////////////////////////////////////////////////////////////////////////////////////////
270   // Touch Callbacks
271   /////////////////////////////////////////////////////////////////////////////////////////////////
272
273   /**
274    * Called when a touch down is received.
275    */
276   static Eina_Bool EcoreEventMouseButtonDown( void* data, int type, void* event )
277   {
278     Ecore_Event_Mouse_Button *touchEvent( (Ecore_Event_Mouse_Button*)event );
279     EventHandler* handler( (EventHandler*)data );
280
281     if ( touchEvent->window == handler->mImpl->mWindow )
282     {
283       TouchPoint::State state ( TouchPoint::Down );
284
285       // Check if the buttons field is set and ensure it's the primary touch button.
286       // If this event was triggered by buttons other than the primary button (used for touch), then
287       // just send an interrupted event to Core.
288       if ( touchEvent->buttons && (touchEvent->buttons != PRIMARY_TOUCH_BUTTON_ID ) )
289       {
290         state = TouchPoint::Interrupted;
291       }
292
293       TouchPoint point( touchEvent->multi.device, state, touchEvent->x, touchEvent->y );
294       handler->SendEvent( point, touchEvent->timestamp );
295     }
296
297     return ECORE_CALLBACK_PASS_ON;
298   }
299
300   /**
301    * Called when a touch up is received.
302    */
303   static Eina_Bool EcoreEventMouseButtonUp( void* data, int type, void* event )
304   {
305     Ecore_Event_Mouse_Button *touchEvent( (Ecore_Event_Mouse_Button*)event );
306     EventHandler* handler( (EventHandler*)data );
307
308     if ( touchEvent->window == handler->mImpl->mWindow )
309     {
310       TouchPoint point( touchEvent->multi.device, TouchPoint::Up, touchEvent->x, touchEvent->y );
311       handler->SendEvent( point, touchEvent->timestamp );
312     }
313
314     return ECORE_CALLBACK_PASS_ON;
315   }
316
317   /**
318    * Called when a touch up is received.
319    */
320   static Eina_Bool EcoreEventMouseWheel( void* data, int type, void* event )
321   {
322     Ecore_Event_Mouse_Wheel *mouseWheelEvent( (Ecore_Event_Mouse_Wheel*)event );
323
324     DALI_LOG_INFO( gImfLogging, Debug::General, "EVENT Ecore_Event_Mouse_Wheel: direction: %d, modifiers: %d, x: %d, y: %d, z: %d\n", mouseWheelEvent->direction, mouseWheelEvent->modifiers, mouseWheelEvent->x, mouseWheelEvent->y, mouseWheelEvent->z);
325
326     EventHandler* handler( (EventHandler*)data );
327     if ( mouseWheelEvent->window == handler->mImpl->mWindow )
328     {
329       MouseWheelEvent wheelEvent(mouseWheelEvent->direction, mouseWheelEvent->modifiers, Vector2(mouseWheelEvent->x, mouseWheelEvent->y), mouseWheelEvent->z, mouseWheelEvent->timestamp);
330       handler->SendMouseWheelEvent( wheelEvent );
331     }
332     return ECORE_CALLBACK_PASS_ON;
333   }
334
335   /**
336    * Called when a touch motion is received.
337    */
338   static Eina_Bool EcoreEventMouseButtonMove( void* data, int type, void* event )
339   {
340     Ecore_Event_Mouse_Move *touchEvent( (Ecore_Event_Mouse_Move*)event );
341     EventHandler* handler( (EventHandler*)data );
342
343     if ( touchEvent->window == handler->mImpl->mWindow )
344     {
345       TouchPoint point( touchEvent->multi.device, TouchPoint::Motion, touchEvent->x, touchEvent->y );
346       handler->SendEvent( point, touchEvent->timestamp );
347     }
348
349     return ECORE_CALLBACK_PASS_ON;
350   }
351
352   /////////////////////////////////////////////////////////////////////////////////////////////////
353   // Key Callbacks
354   /////////////////////////////////////////////////////////////////////////////////////////////////
355
356   /**
357    * Called when a key down is received.
358    */
359   static Eina_Bool EcoreEventKeyDown( void* data, int type, void* event )
360   {
361     DALI_LOG_INFO( gImfLogging, Debug::General, "EVENT >>EcoreEventKeyDown \n" );
362
363     EventHandler* handler( (EventHandler*)data );
364     Ecore_Event_Key *keyEvent( (Ecore_Event_Key*)event );
365     bool eventHandled( false );
366
367     // If a device key then skip ecore_imf_context_filter_event.
368     if ( ! KeyLookup::IsDeviceButton( keyEvent->keyname ) )
369     {
370       Ecore_IMF_Context* imfContext = NULL;
371       Dali::ImfManager imfManager( ImfManager::Get() );
372       if ( imfManager )
373       {
374         imfContext = reinterpret_cast<Ecore_IMF_Context*>( imfManager.GetContext() );
375       }
376
377       if ( imfContext )
378       {
379         // We're consuming key down event so we have to pass to IMF so that it can parse it as well.
380         Ecore_IMF_Event_Key_Down ecoreKeyDownEvent;
381         ecoreKeyDownEvent.keyname   = keyEvent->keyname;
382         ecoreKeyDownEvent.key       = keyEvent->key;
383         ecoreKeyDownEvent.string    = keyEvent->string;
384         ecoreKeyDownEvent.compose   = keyEvent->compose;
385         ecoreKeyDownEvent.timestamp = keyEvent->timestamp;
386         ecoreKeyDownEvent.modifiers = EcoreInputModifierToEcoreIMFModifier ( keyEvent->modifiers );
387         ecoreKeyDownEvent.locks     = (Ecore_IMF_Keyboard_Locks) ECORE_IMF_KEYBOARD_LOCK_NONE;
388
389         eventHandled = ecore_imf_context_filter_event( imfContext,
390                                                        ECORE_IMF_EVENT_KEY_DOWN,
391                                                        (Ecore_IMF_Event *) &ecoreKeyDownEvent );
392
393         // If the event has not been handled by IMF then check if we should reset our IMF context
394         if( !eventHandled )
395         {
396           if ( !strcmp( keyEvent->keyname, "Escape"   ) ||
397                !strcmp( keyEvent->keyname, "Return"   ) ||
398                !strcmp( keyEvent->keyname, "KP_Enter" ) )
399           {
400             ecore_imf_context_reset( imfContext );
401           }
402         }
403       }
404     }
405
406     // If the event wasn't handled then we should send a key event.
407     if ( !eventHandled )
408     {
409       if ( keyEvent->window == handler->mImpl->mWindow )
410       {
411         std::string keyName( keyEvent->keyname );
412         std::string keyString( "" );
413         int keyCode = ecore_x_keysym_keycode_get(keyEvent->keyname);
414         int modifier( keyEvent->modifiers );
415         unsigned long time = keyEvent->timestamp;
416
417         // Ensure key event string is not NULL as keys like SHIFT have a null string.
418         if ( keyEvent->string )
419         {
420           keyString = keyEvent->string;
421         }
422
423         KeyEvent keyEvent(keyName, keyString, keyCode, modifier, time, KeyEvent::Down);
424         handler->SendEvent( keyEvent );
425       }
426     }
427
428     return ECORE_CALLBACK_PASS_ON;
429   }
430
431   /**
432    * Called when a key up is received.
433    */
434   static Eina_Bool EcoreEventKeyUp( void* data, int type, void* event )
435   {
436     DALI_LOG_INFO( gImfLogging, Debug::General, "EVENT >>EcoreEventKeyUp \n" );
437
438     EventHandler* handler( (EventHandler*)data );
439     Ecore_Event_Key *keyEvent( (Ecore_Event_Key*)event );
440     bool eventHandled( false );
441
442     // XF86Stop and XF86Send must skip ecore_imf_context_filter_event.
443     if ( strcmp( keyEvent->keyname, "XF86Send"  ) &&
444          strcmp( keyEvent->keyname, "XF86Phone" ) &&
445          strcmp( keyEvent->keyname, "XF86Stop"  ) )
446     {
447       Ecore_IMF_Context* imfContext = NULL;
448       Dali::ImfManager imfManager( ImfManager::Get() );
449       if ( imfManager )
450       {
451         imfContext = reinterpret_cast<Ecore_IMF_Context*>( imfManager.GetContext() );
452       }
453
454       if ( imfContext )
455       {
456         // We're consuming key up event so we have to pass to IMF so that it can parse it as well.
457         Ecore_IMF_Event_Key_Up ecoreKeyUpEvent;
458         ecoreKeyUpEvent.keyname   = keyEvent->keyname;
459         ecoreKeyUpEvent.key       = keyEvent->key;
460         ecoreKeyUpEvent.string    = keyEvent->string;
461         ecoreKeyUpEvent.compose   = keyEvent->compose;
462         ecoreKeyUpEvent.timestamp = keyEvent->timestamp;
463         ecoreKeyUpEvent.modifiers = EcoreInputModifierToEcoreIMFModifier ( keyEvent->modifiers );
464         ecoreKeyUpEvent.locks     = (Ecore_IMF_Keyboard_Locks) ECORE_IMF_KEYBOARD_LOCK_NONE;
465
466         eventHandled = ecore_imf_context_filter_event( imfContext,
467                                                        ECORE_IMF_EVENT_KEY_UP,
468                                                        (Ecore_IMF_Event *) &ecoreKeyUpEvent );
469       }
470     }
471
472     // If the event wasn't handled then we should send a key event.
473     if ( !eventHandled )
474     {
475       if ( keyEvent->window == handler->mImpl->mWindow )
476       {
477         std::string keyName( keyEvent->keyname );
478         std::string keyString( "" );
479         int keyCode = ecore_x_keysym_keycode_get(keyEvent->keyname);
480         int modifier( keyEvent->modifiers );
481         unsigned long time( keyEvent->timestamp );
482
483         // Ensure key event string is not NULL as keys like SHIFT have a null string.
484         if ( keyEvent->string )
485         {
486           keyString = keyEvent->string;
487         }
488
489         KeyEvent keyEvent(keyName, keyString, keyCode, modifier, time, KeyEvent::Up);
490         handler->SendEvent( keyEvent );
491
492       }
493     }
494
495     return ECORE_CALLBACK_PASS_ON;
496   }
497
498   /////////////////////////////////////////////////////////////////////////////////////////////////
499   // Window Callbacks
500   /////////////////////////////////////////////////////////////////////////////////////////////////
501
502   /**
503    * Called when the window gains focus.
504    */
505   static Eina_Bool EcoreEventWindowFocusIn( void* data, int type, void* event )
506   {
507     Ecore_X_Event_Window_Focus_In* focusInEvent( (Ecore_X_Event_Window_Focus_In*)event );
508     EventHandler* handler( (EventHandler*)data );
509
510     DALI_LOG_INFO( gImfLogging, Debug::General, "EVENT >>EcoreEventWindowFocusIn \n" );
511
512     // If the window gains focus and we hid the keyboard then show it again.
513     if ( focusInEvent->win == handler->mImpl->mWindow )
514     {
515       DALI_LOG_INFO( gImfLogging, Debug::General, "EVENT EcoreEventWindowFocusIn - >>WindowFocusGained \n" );
516
517       if ( ImfManager::IsAvailable() /* Only get the ImfManager if it's available as we do not want to create it */ )
518       {
519         Dali::ImfManager imfManager( ImfManager::Get() );
520         if ( imfManager )
521         {
522           ImfManager& imfManagerImpl( ImfManager::GetImplementation( imfManager ) );
523           if( imfManagerImpl.RestoreAfterFocusLost() )
524           {
525             imfManagerImpl.Activate();
526           }
527         }
528       }
529       // No need to connect callbacks as KeyboardStatusChanged will be called.
530     }
531
532     return ECORE_CALLBACK_PASS_ON;
533   }
534
535   /**
536    * Called when the window loses focus.
537    */
538   static Eina_Bool EcoreEventWindowFocusOut( void* data, int type, void* event )
539   {
540     Ecore_X_Event_Window_Focus_Out* focusOutEvent( (Ecore_X_Event_Window_Focus_Out*)event );
541     EventHandler* handler( (EventHandler*)data );
542
543     DALI_LOG_INFO( gImfLogging, Debug::General, "EVENT >>EcoreEventWindowFocusOut \n" );
544
545     // If the window loses focus then hide the keyboard.
546     if ( focusOutEvent->win == handler->mImpl->mWindow )
547     {
548       if ( ImfManager::IsAvailable() /* Only get the ImfManager if it's available as we do not want to create it */ )
549       {
550         Dali::ImfManager imfManager( ImfManager::Get() );
551         if ( imfManager )
552         {
553           ImfManager& imfManagerImpl( ImfManager::GetImplementation( imfManager ) );
554           if( imfManagerImpl.RestoreAfterFocusLost() )
555           {
556             imfManagerImpl.Deactivate();
557           }
558         }
559       }
560
561       // Clipboard don't support that whether clipboard is shown or not. Hide clipboard.
562       Dali::Clipboard clipboard = Clipboard::Get();
563       clipboard.HideClipboard();
564     }
565
566     return ECORE_CALLBACK_PASS_ON;
567   }
568
569   /**
570    * Called when the window is damaged.
571    */
572   static Eina_Bool EcoreEventWindowDamaged(void *data, int type, void *event)
573   {
574     Ecore_X_Event_Window_Damage* windowDamagedEvent( (Ecore_X_Event_Window_Damage*)event );
575     EventHandler* handler( (EventHandler*)data );
576
577     if( windowDamagedEvent->win == handler->mImpl->mWindow )
578     {
579       DamageArea area;
580       area.x = windowDamagedEvent->x;
581       area.y = windowDamagedEvent->y;
582       area.width = windowDamagedEvent->w;
583       area.height = windowDamagedEvent->h;
584
585       handler->SendEvent( area );
586     }
587
588     return ECORE_CALLBACK_PASS_ON;
589   }
590
591   /**
592    * Called when the window properties are changed.
593    * We are only interested in the font change.
594    */
595
596
597   /////////////////////////////////////////////////////////////////////////////////////////////////
598   // Drag & Drop Callbacks
599   /////////////////////////////////////////////////////////////////////////////////////////////////
600
601   /**
602    * Called when a dragged item enters our window's bounds.
603    * This is when items are dragged INTO our window.
604    */
605   static Eina_Bool EcoreEventDndEnter( void* data, int type, void* event )
606   {
607     DALI_LOG_INFO( gDragAndDropLogFilter, Debug::Concise, "EcoreEventDndEnter\n" );
608
609     Ecore_X_Event_Xdnd_Enter* enterEvent( (Ecore_X_Event_Xdnd_Enter*) event );
610     EventHandler* handler( (EventHandler*)data );
611     Ecore_X_Window window ( handler->mImpl->mWindow );
612
613     if ( enterEvent->win == window )
614     {
615       DragAndDropDetectorPtr dndDetector( handler->mDragAndDropDetector );
616
617       // Check whether the Drag & Drop detector has Drag & Drop behaviour enabled before we accept.
618       if ( dndDetector && dndDetector->IsEnabled() )
619       {
620         // Tell Ecore that we want to enable drop in the entire window.
621         Ecore_X_Rectangle rect;
622         rect.x = rect.y = 0;
623         ecore_x_window_geometry_get( window, NULL, NULL, (int*)&rect.width, (int*)&rect.height );
624
625         // Tell Ecore that we are able to process a drop.
626         ecore_x_dnd_send_status( EINA_TRUE, EINA_FALSE, rect, ECORE_X_ATOM_XDND_DROP );
627
628         // Register the required atoms and types.
629         ecore_x_dnd_actions_set( window, DRAG_AND_DROP_ATOMS, DRAG_AND_DROP_ATOMS_NUMBER );
630         ecore_x_dnd_types_set(   window, DRAG_AND_DROP_TYPES, DRAG_AND_DROP_TYPES_NUMBER );
631
632         // Request to get the content from Ecore.
633         ecore_x_selection_xdnd_request( window, ECORE_X_SELECTION_TARGET_UTF8_STRING );
634
635         DALI_LOG_INFO( gDragAndDropLogFilter, Debug::General, "EcoreEventDndEnter: Requesting Drag & Drop\n" );
636
637         // Clear the previous content
638         dndDetector->ClearContent();
639
640         // Emit the entered signal
641         dndDetector->EmitEnteredSignal();
642       }
643     }
644
645     return ECORE_CALLBACK_PASS_ON;
646   }
647
648   /**
649    * Called when a dragged item is moved within our window.
650    * This is when items are dragged INTO our window.
651    */
652   static Eina_Bool EcoreEventDndPosition( void* data, int type, void* event )
653   {
654     DALI_LOG_INFO(gDragAndDropLogFilter, Debug::Concise, "EcoreEventDndPosition\n" );
655
656     Ecore_X_Event_Xdnd_Position* positionEvent( (Ecore_X_Event_Xdnd_Position*) event );
657     EventHandler* handler( (EventHandler*)data );
658
659     if ( positionEvent->win == handler->mImpl->mWindow )
660     {
661       DragAndDropDetectorPtr dndDetector( handler->mDragAndDropDetector );
662
663       // If we have a detector then update its latest position.
664       if ( dndDetector )
665       {
666         DALI_LOG_INFO(gDragAndDropLogFilter, Debug::General, "EcoreEventDndPosition: position ( %d x %d )\n", positionEvent->position.x, positionEvent->position.y );
667         dndDetector->SetPosition( Vector2( positionEvent->position.x, positionEvent->position.y ));
668         dndDetector->EmitMovedSignal();
669       }
670     }
671
672     return ECORE_CALLBACK_PASS_ON;
673   }
674
675   /**
676    * Called when a dragged item leaves our window's bounds.
677    * This is when items are dragged INTO our window.
678    */
679   static Eina_Bool EcoreEventDndLeave( void* data, int type, void* event )
680   {
681     DALI_LOG_INFO(gDragAndDropLogFilter, Debug::Concise, "EcoreEventDndLeave\n" );
682
683     Ecore_X_Event_Xdnd_Leave* leaveEvent( (Ecore_X_Event_Xdnd_Leave*) event );
684     EventHandler* handler( (EventHandler*)data );
685
686     if ( leaveEvent->win == handler->mImpl->mWindow )
687     {
688       DragAndDropDetectorPtr dndDetector( handler->mDragAndDropDetector );
689
690       // If we have a detector then clear its content and emit the exited-signal. Also tell Ecore that we have finished.
691       if ( dndDetector )
692       {
693         dndDetector->ClearContent();
694         dndDetector->EmitExitedSignal();
695
696         ecore_x_dnd_send_finished();
697
698         DALI_LOG_INFO( gDragAndDropLogFilter, Debug::General, "EcoreEventDndLeave: Finished\n" );
699       }
700     }
701
702     return ECORE_CALLBACK_PASS_ON;
703   }
704
705   /**
706    * Called when the dragged item is dropped within our window's bounds.
707    * This is when items are dragged INTO our window.
708    */
709   static Eina_Bool EcoreEventDndDrop( void* data, int type, void* event )
710   {
711     DALI_LOG_INFO(gDragAndDropLogFilter, Debug::Concise, "EcoreEventDndDrop\n" );
712
713     Ecore_X_Event_Xdnd_Drop* dropEvent ( (Ecore_X_Event_Xdnd_Drop*) event);
714     EventHandler* handler( (EventHandler*)data );
715
716     if ( dropEvent->win == handler->mImpl->mWindow )
717     {
718       DragAndDropDetectorPtr dndDetector( handler->mDragAndDropDetector );
719
720       // Something has been dropped, inform the detector (if we have one) and tell Ecore that we have finished.
721       if ( dndDetector )
722       {
723         DALI_LOG_INFO(gDragAndDropLogFilter, Debug::General, "EcoreEventDndDrop: position ( %d x %d )\n", dropEvent->position.x, dropEvent->position.y );
724
725         dndDetector->SetPosition( Vector2( dropEvent->position.x, dropEvent->position.y ) );
726         dndDetector->EmitDroppedSignal();
727         ecore_x_dnd_send_finished();
728
729         DALI_LOG_INFO( gDragAndDropLogFilter, Debug::General, "EcoreEventDndDrop: Finished\n" );
730       }
731     }
732
733     return ECORE_CALLBACK_PASS_ON;
734   }
735
736   /**
737    * Called when a dragged item is moved from our window and the target window has done processing it.
738    * This is when items are dragged FROM our window.
739    */
740   static Eina_Bool EcoreEventDndFinished( void* data, int type, void* event )
741   {
742     DALI_LOG_INFO(gDragAndDropLogFilter, Debug::Concise, "EcoreEventDndFinished\n" );
743     return ECORE_CALLBACK_PASS_ON;
744   }
745
746   /**
747    * Called when a dragged item is moved from our window and the target window has sent us a status.
748    * This is when items are dragged FROM our window.
749    */
750   static Eina_Bool EcoreEventDndStatus( void* data, int type, void* event )
751   {
752     DALI_LOG_INFO(gDragAndDropLogFilter, Debug::Concise, "EcoreEventDndStatus\n" );
753     return ECORE_CALLBACK_PASS_ON;
754   }
755
756   /**
757    * Called when the client messages (i.e. the accessibility events) are received.
758    */
759   static Eina_Bool EcoreEventClientMessage( void* data, int type, void* event )
760   {
761 #ifndef DALI_PROFILE_UBUNTU
762     Ecore_X_Event_Client_Message* clientMessageEvent( (Ecore_X_Event_Client_Message*)event );
763     EventHandler* handler( (EventHandler*)data );
764
765     if (clientMessageEvent->message_type == ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL)
766     {
767       if ( ( (unsigned int)clientMessageEvent->data.l[0] == handler->mImpl->mWindow ) && handler->mAccessibilityManager )
768       {
769         AccessibilityManager* accessibilityManager( &AccessibilityManager::GetImplementation( handler->mAccessibilityManager ) );
770
771         if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_SCROLL)
772         {
773           // 2 finger touch & move, 2 finger flick
774
775           // mouse state : e->data.l[2] (0: mouse down, 1: mouse move, 2: mouse up)
776           // x : e->data.l[3]
777           // y : e->data.l[4]
778           TouchPoint::State state(TouchPoint::Down);
779
780           if ((unsigned int)clientMessageEvent->data.l[2] == 0)
781           {
782             state = TouchPoint::Down; // mouse down
783           }
784           else if ((unsigned int)clientMessageEvent->data.l[2] == 1)
785           {
786             state = TouchPoint::Motion; // mouse move
787           }
788           else if ((unsigned int)clientMessageEvent->data.l[2] == 2)
789           {
790             state = TouchPoint::Up; // mouse up
791           }
792           else
793           {
794             state = TouchPoint::Interrupted; // error
795           }
796
797           DALI_LOG_INFO(gClientMessageLogFilter, Debug::General,
798             "[%s:%d] [%d] %d, %d\n", __FUNCTION__, __LINE__,
799             (unsigned int)clientMessageEvent->data.l[2],
800             (unsigned int)clientMessageEvent->data.l[3], (unsigned int)clientMessageEvent->data.l[4]);
801
802           // Send touch event to accessibility manager.
803           TouchPoint point( 0, state, (float)clientMessageEvent->data.l[3], (float)clientMessageEvent->data.l[4] );
804
805           // In accessibility mode, scroll action should be handled when the currently focused actor is contained in scrollable control
806           accessibilityManager->HandleActionScrollEvent( point, GetCurrentMilliSeconds() );
807         }
808         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_MOUSE)
809         {
810           // 1 finger double tap and hold
811
812           // mouse state : e->data.l[2] (0: mouse down, 1: mouse move, 2: mouse up)
813           // x : e->data.l[3]
814           // y : e->data.l[4]
815           TouchPoint::State state(TouchPoint::Down);
816
817           if ((unsigned int)clientMessageEvent->data.l[2] == 0)
818           {
819             state = TouchPoint::Down; // mouse down
820           }
821           else if ((unsigned int)clientMessageEvent->data.l[2] == 1)
822           {
823             state = TouchPoint::Motion; // mouse move
824           }
825           else if ((unsigned int)clientMessageEvent->data.l[2] == 2)
826           {
827             state = TouchPoint::Up; // mouse up
828           }
829           else
830           {
831             state = TouchPoint::Interrupted; // error
832           }
833
834           DALI_LOG_INFO(gClientMessageLogFilter, Debug::General,
835             "[%s:%d] [%d] %d, %d\n", __FUNCTION__, __LINE__,
836             (unsigned int)clientMessageEvent->data.l[2],
837             (unsigned int)clientMessageEvent->data.l[3], (unsigned int)clientMessageEvent->data.l[4]);
838
839           // Send touch event to accessibility manager.
840           TouchPoint point( 0, state, (float)clientMessageEvent->data.l[3], (float)clientMessageEvent->data.l[4] );
841
842           // In accessibility mode, scroll action should be handled when the currently focused actor is contained in scrollable control
843           accessibilityManager->HandleActionTouchEvent( point, GetCurrentMilliSeconds() );
844         }
845         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_BACK)
846         {
847           // 2 finger circle draw, do back
848           accessibilityManager->HandleActionBackEvent();
849         }
850         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_NEXT)
851         {
852           // one finger flick down
853           // focus next object
854           if(accessibilityManager)
855           {
856             accessibilityManager->HandleActionNextEvent();
857           }
858         }
859         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_PREV)
860         {
861           // one finger flick up
862           // focus previous object
863           if(accessibilityManager)
864           {
865             accessibilityManager->HandleActionPreviousEvent();
866           }
867         }
868         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_ACTIVATE)
869         {
870           // one finger double tap
871           // same as one finger tap in normal mode (i.e. execute focused actor)
872           if(accessibilityManager)
873           {
874             accessibilityManager->HandleActionActivateEvent();
875           }
876         }
877         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ)
878         {
879           // one finger tap
880           // focus & read an actor at ( e->data.l[2], e->data.l[3] ) position according to finger
881           if(accessibilityManager)
882           {
883             accessibilityManager->HandleActionReadEvent((unsigned int)clientMessageEvent->data.l[2], (unsigned int)clientMessageEvent->data.l[3], true /* allow read again*/);
884           }
885         }
886 #if defined(DALI_PROFILE_MOBILE)
887         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_OVER)
888         {
889           // one finger tap & move
890           // mouse state : e->data.l[2] (0: mouse down, 1: mouse move, 2: mouse up)
891           // x : e->data.l[3]
892           // y : e->data.l[4]
893           // focus & read an actor at (x, y) position according to finger
894           if(accessibilityManager && (unsigned int)clientMessageEvent->data.l[2] == 1 /*only work for move event*/)
895           {
896             accessibilityManager->HandleActionReadEvent((unsigned int)clientMessageEvent->data.l[3], (unsigned int)clientMessageEvent->data.l[4], false /* not allow read again*/);
897           }
898         }
899 #endif
900         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_NEXT)
901         {
902           // one finger flick right
903           // focus next object
904            if(accessibilityManager)
905           {
906             accessibilityManager->HandleActionReadNextEvent();
907           }
908         }
909         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_PREV)
910         {
911           // one finger flick left
912           // focus previous object
913           if(accessibilityManager)
914           {
915             accessibilityManager->HandleActionReadPreviousEvent();
916           }
917         }
918         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_UP)
919         {
920           // double down and move (right, up)
921           // change slider value
922           if(accessibilityManager)
923           {
924             accessibilityManager->HandleActionUpEvent();
925           }
926         }
927         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_DOWN)
928         {
929           // double down and move (left, down)
930           // change slider value
931           if(accessibilityManager)
932           {
933             accessibilityManager->HandleActionDownEvent();
934           }
935         }
936         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_ENABLE)
937         {
938            if(accessibilityManager)
939           {
940             accessibilityManager->HandleActionEnableEvent();
941           }
942         }
943         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_DISABLE)
944         {
945           if(accessibilityManager)
946           {
947             accessibilityManager->HandleActionDisableEvent();
948           }
949         }
950         // TODO: some more actions could be added later
951       }
952     }
953     else if(clientMessageEvent->message_type == ecore_x_atom_get(CLIPBOARD_ATOM))
954     {
955       std::string message(clientMessageEvent->data.b);
956       if( message == CLIPBOARD_SET_OWNER_MESSAGE)
957       {
958         // Claim the ownership of the SECONDARY selection.
959         ecore_x_selection_secondary_set(handler->mImpl->mWindow, "", 1);
960
961         // Show the clipboard window
962         Dali::Clipboard clipboard = Dali::Clipboard::Get();
963         clipboard.ShowClipboard();
964       }
965     }
966     else if( clientMessageEvent->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE )
967     {
968       RotationEvent rotationEvent;
969       rotationEvent.angle      = static_cast<int>(clientMessageEvent->data.l[1]);
970       rotationEvent.winResize  = static_cast<int>(clientMessageEvent->data.l[2]);
971       rotationEvent.width      = static_cast<int>(clientMessageEvent->data.l[3]);
972       rotationEvent.height     = static_cast<int>(clientMessageEvent->data.l[4]);
973       handler->SendRotationPrepareEvent( rotationEvent );
974     }
975     else if( clientMessageEvent->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST )
976     {
977       handler->SendRotationRequestEvent();
978     }
979
980 #endif // DALI_PROFILE_UBUNTU
981     return ECORE_CALLBACK_PASS_ON;
982   }
983
984   /**
985    * Called when the source window notifies us the content in clipboard is selected.
986    */
987   static Eina_Bool EcoreEventSelectionClear( void* data, int type, void* event )
988   {
989     DALI_LOG_INFO(gSelectionEventLogFilter, Debug::Concise, "EcoreEventSelectionClear\n" );
990     Ecore_X_Event_Selection_Clear* selectionClearEvent( (Ecore_X_Event_Selection_Clear*) event );
991     EventHandler* handler( (EventHandler*)data );
992
993     if ( selectionClearEvent->win == handler->mImpl->mWindow )
994     {
995       if ( selectionClearEvent->selection == ECORE_X_SELECTION_SECONDARY )
996       {
997         // Request to get the content from Ecore.
998         ecore_x_selection_secondary_request(selectionClearEvent->win, ECORE_X_SELECTION_TARGET_TEXT);
999       }
1000     }
1001     return ECORE_CALLBACK_PASS_ON;
1002   }
1003
1004   /**
1005    * Called when the source window sends us about the selected content.
1006    * For example, when dragged items are dragged INTO our window or when items are selected in the clipboard.
1007    */
1008   static Eina_Bool EcoreEventSelectionNotify( void* data, int type, void* event )
1009   {
1010     DALI_LOG_INFO(gSelectionEventLogFilter, Debug::Concise, "EcoreEventSelectionNotify\n" );
1011
1012     Ecore_X_Event_Selection_Notify* selectionNotifyEvent( (Ecore_X_Event_Selection_Notify*) event );
1013     EventHandler* handler( (EventHandler*)data );
1014
1015     if ( selectionNotifyEvent->win == handler->mImpl->mWindow )
1016     {
1017       Ecore_X_Selection_Data* selectionData( (Ecore_X_Selection_Data*) selectionNotifyEvent->data );
1018       if ( selectionData->data )
1019       {
1020         if ( selectionNotifyEvent->selection == ECORE_X_SELECTION_XDND )
1021         {
1022           DragAndDropDetectorPtr dndDetector( handler->mDragAndDropDetector );
1023
1024           // We have got the content that is to be dropped, inform the DndListener (if we have one).
1025           if ( dndDetector )
1026           {
1027             std::string content( (char*) selectionData->data, selectionData->length );
1028             dndDetector->SetContent( content );
1029
1030             DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "EcoreEventSelectionNotify: Content(%d):\n" , selectionData->length );
1031             DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "======================================\n" );
1032             DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "%s\n", selectionData->data );
1033             DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "======================================\n" );
1034           }
1035         }
1036         else if ( selectionNotifyEvent->selection == ECORE_X_SELECTION_SECONDARY )
1037         {
1038           // We have got the selected content, inform the clipboard event listener (if we have one).
1039           if ( handler->mClipboardEventNotifier )
1040           {
1041             ClipboardEventNotifier& clipboardEventNotifier( ClipboardEventNotifier::GetImplementation( handler->mClipboardEventNotifier ) );
1042             std::string content( (char*) selectionData->data, selectionData->length );
1043             clipboardEventNotifier.SetContent( content );
1044             clipboardEventNotifier.EmitContentSelectedSignal();
1045           }
1046
1047           // Claim the ownership of the SECONDARY selection.
1048           ecore_x_selection_secondary_set(handler->mImpl->mWindow, "", 1);
1049
1050           DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "EcoreEventSelectionNotify: Content(%d):\n" , selectionData->length );
1051           DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "======================================\n" );
1052           DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "%s\n", selectionData->data );
1053           DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "======================================\n" );
1054         }
1055       }
1056     }
1057     return ECORE_CALLBACK_PASS_ON;
1058   }
1059
1060
1061 #ifndef DALI_PROFILE_UBUNTU
1062   /////////////////////////////////////////////////////////////////////////////////////////////////
1063   // Font Callbacks
1064   /////////////////////////////////////////////////////////////////////////////////////////////////
1065   /**
1066    * Called when a font name is changed.
1067    */
1068   static void VconfNotifyFontNameChanged( keynode_t* node, void* data )
1069   {
1070     EventHandler* handler = static_cast<EventHandler*>( data );
1071
1072     StyleChange fontChange;
1073     fontChange.defaultFontChange = true;
1074
1075     handler->SendEvent( fontChange );
1076   }
1077
1078   /**
1079    * Called when a font size is changed.
1080    */
1081   static void VconfNotifyFontSizeChanged( keynode_t* node, void* data )
1082   {
1083     EventHandler* handler = static_cast<EventHandler*>( data );
1084
1085     StyleChange fontChange;
1086     fontChange.defaultFontSizeChange = true;
1087
1088     handler->SendEvent( fontChange );
1089   }
1090
1091   /**
1092    * Called when style is changed
1093    */
1094   static void VconfNotifyThemeChanged( keynode_t* node, void* data )
1095   {
1096     EventHandler* handler( static_cast<EventHandler*>(data) );
1097
1098     StyleChange themeChange;
1099     themeChange.themeChange = true;
1100
1101     handler->SendEvent( themeChange );
1102   }
1103 #endif // DALI_PROFILE_UBUNTU
1104
1105   // Data
1106   EventHandler* mHandler;
1107   std::vector<Ecore_Event_Handler*> mEcoreEventHandler;
1108   Ecore_X_Window mWindow;
1109 };
1110
1111 EventHandler::EventHandler( RenderSurface* surface, CoreEventInterface& coreEventInterface, GestureManager& gestureManager, DamageObserver& damageObserver, DragAndDropDetectorPtr dndDetector )
1112 : mCoreEventInterface(coreEventInterface),
1113   mGestureManager( gestureManager ),
1114   mStyleMonitor( StyleMonitor::Get() ),
1115   mDamageObserver( damageObserver ),
1116   mRotationObserver( NULL ),
1117   mDragAndDropDetector( dndDetector ),
1118   mAccessibilityManager( AccessibilityManager::Get() ),
1119   mClipboardEventNotifier( ClipboardEventNotifier::Get() ),
1120   mClipboard(Clipboard::Get()),
1121   mImpl( NULL )
1122 {
1123   Ecore_X_Window window = 0;
1124
1125   if( surface->GetType() == Dali::RenderSurface::WINDOW )
1126   {
1127     // this code only works with the EcoreX11 RenderSurface so need to downcast
1128     ECore::WindowRenderSurface* ecoreSurface = dynamic_cast< ECore::WindowRenderSurface* >( surface );
1129     if( ecoreSurface )
1130     {
1131       // enable multi touch
1132       window = ecoreSurface->GetXWindow();
1133       ecore_x_input_multi_select( window );
1134     }
1135   }
1136
1137   mImpl = new Impl(this, window);
1138 }
1139
1140 EventHandler::~EventHandler()
1141 {
1142   if(mImpl)
1143   {
1144     delete mImpl;
1145   }
1146
1147   mGestureManager.Stop();
1148 }
1149
1150 void EventHandler::SendEvent(TouchPoint& point, unsigned long timeStamp)
1151 {
1152   if(timeStamp < 1)
1153   {
1154     timeStamp = GetCurrentMilliSeconds();
1155   }
1156
1157   Integration::TouchEvent touchEvent;
1158   Integration::HoverEvent hoverEvent;
1159   Integration::TouchEventCombiner::EventDispatchType type = mCombiner.GetNextTouchEvent(point, timeStamp, touchEvent, hoverEvent);
1160   if(type != Integration::TouchEventCombiner::DispatchNone )
1161   {
1162     DALI_LOG_INFO(gTouchEventLogFilter, Debug::General, "%d: Device %d: Button state %d (%.2f, %.2f)\n", timeStamp, point.deviceId, point.state, point.local.x, point.local.y);
1163
1164     // First the touch and/or hover event & related gesture events are queued
1165     if(type == Integration::TouchEventCombiner::DispatchTouch || type == Integration::TouchEventCombiner::DispatchBoth)
1166     {
1167       mCoreEventInterface.QueueCoreEvent( touchEvent );
1168       mGestureManager.SendEvent(touchEvent);
1169     }
1170
1171     if(type == Integration::TouchEventCombiner::DispatchHover || type == Integration::TouchEventCombiner::DispatchBoth)
1172     {
1173       mCoreEventInterface.QueueCoreEvent( hoverEvent );
1174     }
1175
1176     // Next the events are processed with a single call into Core
1177     mCoreEventInterface.ProcessCoreEvents();
1178   }
1179 }
1180
1181 void EventHandler::SendEvent(KeyEvent& keyEvent)
1182 {
1183   Dali::PhysicalKeyboard physicalKeyboard = PhysicalKeyboard::Get();
1184   if ( physicalKeyboard )
1185   {
1186     if ( ! KeyLookup::IsDeviceButton( keyEvent.keyPressedName.c_str() ) )
1187     {
1188       GetImplementation( physicalKeyboard ).KeyReceived( keyEvent.time > 1 );
1189     }
1190   }
1191
1192   // Create KeyEvent and send to Core.
1193   Integration::KeyEvent event(keyEvent.keyPressedName, keyEvent.keyPressed, keyEvent.keyCode,
1194   keyEvent.keyModifier, keyEvent.time, static_cast<Integration::KeyEvent::State>(keyEvent.state));
1195   mCoreEventInterface.QueueCoreEvent( event );
1196   mCoreEventInterface.ProcessCoreEvents();
1197 }
1198
1199 void EventHandler::SendMouseWheelEvent( MouseWheelEvent& wheelEvent )
1200 {
1201   // Create MouseWheelEvent and send to Core.
1202   Integration::MouseWheelEvent event(wheelEvent.direction, wheelEvent.modifiers, wheelEvent.point, wheelEvent.z, wheelEvent.timeStamp);
1203   mCoreEventInterface.QueueCoreEvent( event );
1204   mCoreEventInterface.ProcessCoreEvents();
1205 }
1206
1207 void EventHandler::SendEvent(StyleChange styleChange)
1208 {
1209   DALI_ASSERT_DEBUG( mStyleMonitor && "StyleMonitor Not Available" );
1210   GetImplementation( mStyleMonitor ).StyleChanged(styleChange);
1211 }
1212
1213 void EventHandler::SendEvent( const DamageArea& area )
1214 {
1215   mDamageObserver.OnDamaged( area );
1216 }
1217
1218 void EventHandler::SendRotationPrepareEvent( const RotationEvent& event )
1219 {
1220   if( mRotationObserver != NULL )
1221   {
1222     mRotationObserver->OnRotationPrepare( event );
1223   }
1224 }
1225
1226 void EventHandler::SendRotationRequestEvent( )
1227 {
1228   if( mRotationObserver != NULL )
1229   {
1230     mRotationObserver->OnRotationRequest( );
1231   }
1232 }
1233
1234 void EventHandler::FeedTouchPoint( TouchPoint& point, int timeStamp)
1235 {
1236   SendEvent(point, timeStamp);
1237 }
1238
1239 void EventHandler::FeedWheelEvent( MouseWheelEvent& wheelEvent )
1240 {
1241   SendMouseWheelEvent( wheelEvent );
1242 }
1243
1244 void EventHandler::FeedKeyEvent( KeyEvent& event )
1245 {
1246   SendEvent( event );
1247 }
1248
1249 void EventHandler::FeedEvent( Integration::Event& event )
1250 {
1251   mCoreEventInterface.QueueCoreEvent( event );
1252   mCoreEventInterface.ProcessCoreEvents();
1253 }
1254
1255 void EventHandler::Reset()
1256 {
1257   mCombiner.Reset();
1258
1259   // Any touch listeners should be told of the interruption.
1260   Integration::TouchEvent event;
1261   TouchPoint point(0, TouchPoint::Interrupted, 0, 0);
1262   event.AddPoint( point );
1263
1264   // First the touch event & related gesture events are queued
1265   mCoreEventInterface.QueueCoreEvent( event );
1266   mGestureManager.SendEvent( event );
1267
1268   // Next the events are processed with a single call into Core
1269   mCoreEventInterface.ProcessCoreEvents();
1270 }
1271
1272 void EventHandler::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
1273 {
1274   mDragAndDropDetector = detector;
1275 }
1276
1277 void EventHandler::SetRotationObserver( RotationObserver* observer )
1278 {
1279   mRotationObserver = observer;
1280 }
1281
1282 } // namespace Adaptor
1283
1284 } // namespace Internal
1285
1286 } // namespace Dali