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