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