Move window-extension.h from public-api to devel-api
[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             free( xiEventMask.mask );
297
298             if( deviceInfo != NULL )
299             {
300               XIFreeDeviceInfo( deviceInfo );
301             }
302           }
303         }
304         else
305         {
306           DALI_LOG_INFO( gImfLogging, Debug::General, "Failed to query XI Version\n" );
307         }
308       }
309       else
310       {
311         DALI_LOG_INFO( gImfLogging, Debug::General, "Failed to query XInputExtension\n" );
312       }
313
314 #ifndef DALI_PROFILE_UBUNTU
315       // Register Vconf notify - font name, font size and style
316       vconf_notify_key_changed( DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_NAME, VconfNotifyFontNameChanged, handler );
317       vconf_notify_key_changed( VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, VconfNotifyFontSizeChanged, handler );
318 #endif // DALI_PROFILE_UBUNTU
319     }
320   }
321
322   /**
323    * Destructor
324    */
325   ~Impl()
326   {
327 #ifndef DALI_PROFILE_UBUNTU
328     vconf_ignore_key_changed( VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, VconfNotifyFontSizeChanged );
329     vconf_ignore_key_changed( DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_NAME, VconfNotifyFontNameChanged );
330 #endif // DALI_PROFILE_UBUNTU
331
332     for( std::vector<Ecore_Event_Handler*>::iterator iter = mEcoreEventHandler.begin(), endIter = mEcoreEventHandler.end(); iter != endIter; ++iter )
333     {
334       ecore_event_handler_del( *iter );
335     }
336   }
337
338   // Static methods
339
340   /////////////////////////////////////////////////////////////////////////////////////////////////
341   // Touch Callbacks
342   /////////////////////////////////////////////////////////////////////////////////////////////////
343
344   /**
345    * Called when a touch down is received.
346    */
347   static Eina_Bool EcoreEventMouseButtonDown( void* data, int type, void* event )
348   {
349     Ecore_Event_Mouse_Button *touchEvent( (Ecore_Event_Mouse_Button*)event );
350     EventHandler* handler( (EventHandler*)data );
351
352     if ( touchEvent->window == handler->mImpl->mWindow )
353     {
354       TouchPoint::State state ( TouchPoint::Down );
355
356       // Check if the buttons field is set and ensure it's the primary touch button.
357       // If this event was triggered by buttons other than the primary button (used for touch), then
358       // just send an interrupted event to Core.
359       if ( touchEvent->buttons && (touchEvent->buttons != PRIMARY_TOUCH_BUTTON_ID ) )
360       {
361         state = TouchPoint::Interrupted;
362       }
363
364       TouchPoint point( touchEvent->multi.device, state, touchEvent->x, touchEvent->y );
365       handler->SendEvent( point, touchEvent->timestamp );
366     }
367
368     return ECORE_CALLBACK_PASS_ON;
369   }
370
371   /**
372    * Called when a touch up is received.
373    */
374   static Eina_Bool EcoreEventMouseButtonUp( void* data, int type, void* event )
375   {
376     Ecore_Event_Mouse_Button *touchEvent( (Ecore_Event_Mouse_Button*)event );
377     EventHandler* handler( (EventHandler*)data );
378
379     if ( touchEvent->window == handler->mImpl->mWindow )
380     {
381       TouchPoint point( touchEvent->multi.device, TouchPoint::Up, touchEvent->x, touchEvent->y );
382       handler->SendEvent( point, touchEvent->timestamp );
383     }
384
385     return ECORE_CALLBACK_PASS_ON;
386   }
387
388   /**
389    * Called when a touch motion is received.
390    */
391   static Eina_Bool EcoreEventMouseButtonMove( void* data, int type, void* event )
392   {
393     Ecore_Event_Mouse_Move *touchEvent( (Ecore_Event_Mouse_Move*)event );
394     EventHandler* handler( (EventHandler*)data );
395
396     if ( touchEvent->window == handler->mImpl->mWindow )
397     {
398       TouchPoint point( touchEvent->multi.device, TouchPoint::Motion, touchEvent->x, touchEvent->y );
399       handler->SendEvent( point, touchEvent->timestamp );
400     }
401
402     return ECORE_CALLBACK_PASS_ON;
403   }
404
405   /////////////////////////////////////////////////////////////////////////////////////////////////
406   // Wheel Callbacks
407   /////////////////////////////////////////////////////////////////////////////////////////////////
408
409   /**
410    * Called when a mouse wheel is received.
411    */
412   static Eina_Bool EcoreEventMouseWheel( void* data, int type, void* event )
413   {
414     Ecore_Event_Mouse_Wheel *mouseWheelEvent( (Ecore_Event_Mouse_Wheel*)event );
415
416     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 );
417
418     EventHandler* handler( (EventHandler*)data );
419     if ( mouseWheelEvent->window == handler->mImpl->mWindow )
420     {
421       WheelEvent wheelEvent( WheelEvent::MOUSE_WHEEL, mouseWheelEvent->direction, mouseWheelEvent->modifiers, Vector2(mouseWheelEvent->x, mouseWheelEvent->y), mouseWheelEvent->z, mouseWheelEvent->timestamp );
422       handler->SendWheelEvent( wheelEvent );
423     }
424     return ECORE_CALLBACK_PASS_ON;
425   }
426
427   /**
428    * Called when a custom wheel is received.
429    */
430   static Eina_Bool EcoreEventCustomWheel( void* data, int type, void* event )
431   {
432     Ecore_X_Event_Generic *genericEvent( (Ecore_X_Event_Generic*)event );
433     EventHandler* handler( (EventHandler*)data );
434
435     switch( genericEvent->evtype )
436     {
437       case XI_RawMotion:
438       {
439         XIRawEvent* xiRawEvent = static_cast< XIRawEvent* >( genericEvent->data );
440         unsigned int timeStamp = 0;
441
442         if( xiRawEvent->deviceid != handler->mImpl->mXiDeviceId )
443         {
444           return ECORE_CALLBACK_PASS_ON;
445         }
446
447         // X(0): rotate: NOT USED
448         // Y(1): timestamp
449         // Z(2): direction
450
451         double* value = xiRawEvent->raw_values;
452
453         if( XIMaskIsSet( xiRawEvent->valuators.mask, 1) )
454         {
455           timeStamp = static_cast< unsigned int >( *(value + 1) );
456         }
457
458         if( XIMaskIsSet( xiRawEvent->valuators.mask, 2) )
459         {
460           // if z == 1, clockwise
461           // otherwise counter-clockwise
462           int z = static_cast< int >( *(value + 2) );
463
464           // In DALi, positive value means clockwise, and negative value means counter-clockwise
465           if( z == 0 )
466           {
467             z = -1;
468           }
469
470           DALI_LOG_INFO( gImfLogging, Debug::General, "EVENT EcoreEventCustomWheel: z: %d\n", z );
471
472           WheelEvent wheelEvent( WheelEvent::CUSTOM_WHEEL, 0, 0, Vector2(0.0f, 0.0f), z, timeStamp );
473           handler->SendWheelEvent( wheelEvent );
474         }
475         break;
476       }
477       default:
478       {
479         break;
480       }
481     }
482
483     return ECORE_CALLBACK_PASS_ON;
484   }
485
486   /////////////////////////////////////////////////////////////////////////////////////////////////
487   // Key Callbacks
488   /////////////////////////////////////////////////////////////////////////////////////////////////
489
490   /**
491    * Called when a key down is received.
492    */
493   static Eina_Bool EcoreEventKeyDown( void* data, int type, void* event )
494   {
495     DALI_LOG_INFO( gImfLogging, Debug::General, "EVENT >>EcoreEventKeyDown \n" );
496
497     EventHandler* handler( (EventHandler*)data );
498     Ecore_Event_Key *keyEvent( (Ecore_Event_Key*)event );
499     bool eventHandled( false );
500
501     // If a device key then skip ecore_imf_context_filter_event.
502     if ( ! KeyLookup::IsDeviceButton( keyEvent->keyname ) )
503     {
504       Ecore_IMF_Context* imfContext = NULL;
505       Dali::ImfManager imfManager( ImfManager::Get() );
506       if ( imfManager )
507       {
508         imfContext = reinterpret_cast<Ecore_IMF_Context*>( imfManager.GetContext() );
509       }
510
511       if ( imfContext )
512       {
513         // We're consuming key down event so we have to pass to IMF so that it can parse it as well.
514         Ecore_IMF_Event_Key_Down ecoreKeyDownEvent;
515         ecoreKeyDownEvent.keyname   = keyEvent->keyname;
516         ecoreKeyDownEvent.key       = keyEvent->key;
517         ecoreKeyDownEvent.string    = keyEvent->string;
518         ecoreKeyDownEvent.compose   = keyEvent->compose;
519         ecoreKeyDownEvent.timestamp = keyEvent->timestamp;
520         ecoreKeyDownEvent.modifiers = EcoreInputModifierToEcoreIMFModifier ( keyEvent->modifiers );
521         ecoreKeyDownEvent.locks     = (Ecore_IMF_Keyboard_Locks) ECORE_IMF_KEYBOARD_LOCK_NONE;
522
523         eventHandled = ecore_imf_context_filter_event( imfContext,
524                                                        ECORE_IMF_EVENT_KEY_DOWN,
525                                                        (Ecore_IMF_Event *) &ecoreKeyDownEvent );
526
527         // If the event has not been handled by IMF then check if we should reset our IMF context
528         if( !eventHandled )
529         {
530           if ( !strcmp( keyEvent->keyname, "Escape"   ) ||
531                !strcmp( keyEvent->keyname, "Return"   ) ||
532                !strcmp( keyEvent->keyname, "KP_Enter" ) )
533           {
534             ecore_imf_context_reset( imfContext );
535           }
536         }
537       }
538     }
539
540     // If the event wasn't handled then we should send a key event.
541     if ( !eventHandled )
542     {
543       if ( keyEvent->window == handler->mImpl->mWindow )
544       {
545         std::string keyName( keyEvent->keyname );
546         std::string keyString( "" );
547         int keyCode = ecore_x_keysym_keycode_get(keyEvent->keyname);
548         int modifier( keyEvent->modifiers );
549         unsigned long time = keyEvent->timestamp;
550
551         // Ensure key event string is not NULL as keys like SHIFT have a null string.
552         if ( keyEvent->string )
553         {
554           keyString = keyEvent->string;
555         }
556
557         KeyEvent keyEvent(keyName, keyString, keyCode, modifier, time, KeyEvent::Down);
558         handler->SendEvent( keyEvent );
559       }
560     }
561
562     return ECORE_CALLBACK_PASS_ON;
563   }
564
565   /**
566    * Called when a key up is received.
567    */
568   static Eina_Bool EcoreEventKeyUp( void* data, int type, void* event )
569   {
570     DALI_LOG_INFO( gImfLogging, Debug::General, "EVENT >>EcoreEventKeyUp \n" );
571
572     EventHandler* handler( (EventHandler*)data );
573     Ecore_Event_Key *keyEvent( (Ecore_Event_Key*)event );
574     bool eventHandled( false );
575
576     // XF86Stop and XF86Send must skip ecore_imf_context_filter_event.
577     if ( strcmp( keyEvent->keyname, "XF86Send"  ) &&
578          strcmp( keyEvent->keyname, "XF86Phone" ) &&
579          strcmp( keyEvent->keyname, "XF86Stop"  ) )
580     {
581       Ecore_IMF_Context* imfContext = NULL;
582       Dali::ImfManager imfManager( ImfManager::Get() );
583       if ( imfManager )
584       {
585         imfContext = reinterpret_cast<Ecore_IMF_Context*>( imfManager.GetContext() );
586       }
587
588       if ( imfContext )
589       {
590         // We're consuming key up event so we have to pass to IMF so that it can parse it as well.
591         Ecore_IMF_Event_Key_Up ecoreKeyUpEvent;
592         ecoreKeyUpEvent.keyname   = keyEvent->keyname;
593         ecoreKeyUpEvent.key       = keyEvent->key;
594         ecoreKeyUpEvent.string    = keyEvent->string;
595         ecoreKeyUpEvent.compose   = keyEvent->compose;
596         ecoreKeyUpEvent.timestamp = keyEvent->timestamp;
597         ecoreKeyUpEvent.modifiers = EcoreInputModifierToEcoreIMFModifier ( keyEvent->modifiers );
598         ecoreKeyUpEvent.locks     = (Ecore_IMF_Keyboard_Locks) ECORE_IMF_KEYBOARD_LOCK_NONE;
599
600         eventHandled = ecore_imf_context_filter_event( imfContext,
601                                                        ECORE_IMF_EVENT_KEY_UP,
602                                                        (Ecore_IMF_Event *) &ecoreKeyUpEvent );
603       }
604     }
605
606     // If the event wasn't handled then we should send a key event.
607     if ( !eventHandled )
608     {
609       if ( keyEvent->window == handler->mImpl->mWindow )
610       {
611         std::string keyName( keyEvent->keyname );
612         std::string keyString( "" );
613         int keyCode = ecore_x_keysym_keycode_get(keyEvent->keyname);
614         int modifier( keyEvent->modifiers );
615         unsigned long time( keyEvent->timestamp );
616
617         // Ensure key event string is not NULL as keys like SHIFT have a null string.
618         if ( keyEvent->string )
619         {
620           keyString = keyEvent->string;
621         }
622
623         KeyEvent keyEvent(keyName, keyString, keyCode, modifier, time, KeyEvent::Up);
624         handler->SendEvent( keyEvent );
625
626       }
627     }
628
629     return ECORE_CALLBACK_PASS_ON;
630   }
631
632   /////////////////////////////////////////////////////////////////////////////////////////////////
633   // Window Callbacks
634   /////////////////////////////////////////////////////////////////////////////////////////////////
635
636   /**
637    * Called when the window gains focus.
638    */
639   static Eina_Bool EcoreEventWindowFocusIn( void* data, int type, void* event )
640   {
641     Ecore_X_Event_Window_Focus_In* focusInEvent( (Ecore_X_Event_Window_Focus_In*)event );
642     EventHandler* handler( (EventHandler*)data );
643
644     DALI_LOG_INFO( gImfLogging, Debug::General, "EVENT >>EcoreEventWindowFocusIn \n" );
645
646     // If the window gains focus and we hid the keyboard then show it again.
647     if ( focusInEvent->win == handler->mImpl->mWindow )
648     {
649       DALI_LOG_INFO( gImfLogging, Debug::General, "EVENT EcoreEventWindowFocusIn - >>WindowFocusGained \n" );
650
651       if ( ImfManager::IsAvailable() /* Only get the ImfManager if it's available as we do not want to create it */ )
652       {
653         Dali::ImfManager imfManager( ImfManager::Get() );
654         if ( imfManager )
655         {
656           ImfManager& imfManagerImpl( ImfManager::GetImplementation( imfManager ) );
657           if( imfManagerImpl.RestoreAfterFocusLost() )
658           {
659             imfManagerImpl.Activate();
660           }
661         }
662       }
663       // No need to connect callbacks as KeyboardStatusChanged will be called.
664     }
665
666     return ECORE_CALLBACK_PASS_ON;
667   }
668
669   /**
670    * Called when the window loses focus.
671    */
672   static Eina_Bool EcoreEventWindowFocusOut( void* data, int type, void* event )
673   {
674     Ecore_X_Event_Window_Focus_Out* focusOutEvent( (Ecore_X_Event_Window_Focus_Out*)event );
675     EventHandler* handler( (EventHandler*)data );
676
677     DALI_LOG_INFO( gImfLogging, Debug::General, "EVENT >>EcoreEventWindowFocusOut \n" );
678
679     // If the window loses focus then hide the keyboard.
680     if ( focusOutEvent->win == handler->mImpl->mWindow )
681     {
682       if ( ImfManager::IsAvailable() /* Only get the ImfManager if it's available as we do not want to create it */ )
683       {
684         Dali::ImfManager imfManager( ImfManager::Get() );
685         if ( imfManager )
686         {
687           ImfManager& imfManagerImpl( ImfManager::GetImplementation( imfManager ) );
688           if( imfManagerImpl.RestoreAfterFocusLost() )
689           {
690             imfManagerImpl.Deactivate();
691           }
692         }
693       }
694
695       // Clipboard don't support that whether clipboard is shown or not. Hide clipboard.
696       Dali::Clipboard clipboard = Clipboard::Get();
697       clipboard.HideClipboard();
698     }
699
700     return ECORE_CALLBACK_PASS_ON;
701   }
702
703   /**
704    * Called when the window is damaged.
705    */
706   static Eina_Bool EcoreEventWindowDamaged(void *data, int type, void *event)
707   {
708     Ecore_X_Event_Window_Damage* windowDamagedEvent( (Ecore_X_Event_Window_Damage*)event );
709     EventHandler* handler( (EventHandler*)data );
710
711     if( windowDamagedEvent->win == handler->mImpl->mWindow )
712     {
713       DamageArea area;
714       area.x = windowDamagedEvent->x;
715       area.y = windowDamagedEvent->y;
716       area.width = windowDamagedEvent->w;
717       area.height = windowDamagedEvent->h;
718
719       handler->SendEvent( area );
720     }
721
722     return ECORE_CALLBACK_PASS_ON;
723   }
724
725   /**
726    * Called when the window properties are changed.
727    * We are only interested in the font change.
728    */
729
730
731   /////////////////////////////////////////////////////////////////////////////////////////////////
732   // Drag & Drop Callbacks
733   /////////////////////////////////////////////////////////////////////////////////////////////////
734
735   /**
736    * Called when a dragged item enters our window's bounds.
737    * This is when items are dragged INTO our window.
738    */
739   static Eina_Bool EcoreEventDndEnter( void* data, int type, void* event )
740   {
741     DALI_LOG_INFO( gDragAndDropLogFilter, Debug::Concise, "EcoreEventDndEnter\n" );
742
743     Ecore_X_Event_Xdnd_Enter* enterEvent( (Ecore_X_Event_Xdnd_Enter*) event );
744     EventHandler* handler( (EventHandler*)data );
745     Ecore_X_Window window ( handler->mImpl->mWindow );
746
747     if ( enterEvent->win == window )
748     {
749       DragAndDropDetectorPtr dndDetector( handler->mDragAndDropDetector );
750
751       // Check whether the Drag & Drop detector has Drag & Drop behaviour enabled before we accept.
752       if ( dndDetector && dndDetector->IsEnabled() )
753       {
754         // Tell Ecore that we want to enable drop in the entire window.
755         Ecore_X_Rectangle rect;
756         rect.x = rect.y = 0;
757         ecore_x_window_geometry_get( window, NULL, NULL, (int*)&rect.width, (int*)&rect.height );
758
759         // Tell Ecore that we are able to process a drop.
760         ecore_x_dnd_send_status( EINA_TRUE, EINA_FALSE, rect, ECORE_X_ATOM_XDND_DROP );
761
762         // Register the required atoms and types.
763         ecore_x_dnd_actions_set( window, DRAG_AND_DROP_ATOMS, DRAG_AND_DROP_ATOMS_NUMBER );
764         ecore_x_dnd_types_set(   window, DRAG_AND_DROP_TYPES, DRAG_AND_DROP_TYPES_NUMBER );
765
766         // Request to get the content from Ecore.
767         ecore_x_selection_xdnd_request( window, ECORE_X_SELECTION_TARGET_UTF8_STRING );
768
769         DALI_LOG_INFO( gDragAndDropLogFilter, Debug::General, "EcoreEventDndEnter: Requesting Drag & Drop\n" );
770
771         // Clear the previous content
772         dndDetector->ClearContent();
773
774         // Emit the entered signal
775         dndDetector->EmitEnteredSignal();
776       }
777     }
778
779     return ECORE_CALLBACK_PASS_ON;
780   }
781
782   /**
783    * Called when a dragged item is moved within our window.
784    * This is when items are dragged INTO our window.
785    */
786   static Eina_Bool EcoreEventDndPosition( void* data, int type, void* event )
787   {
788     DALI_LOG_INFO(gDragAndDropLogFilter, Debug::Concise, "EcoreEventDndPosition\n" );
789
790     Ecore_X_Event_Xdnd_Position* positionEvent( (Ecore_X_Event_Xdnd_Position*) event );
791     EventHandler* handler( (EventHandler*)data );
792
793     if ( positionEvent->win == handler->mImpl->mWindow )
794     {
795       DragAndDropDetectorPtr dndDetector( handler->mDragAndDropDetector );
796
797       // If we have a detector then update its latest position.
798       if ( dndDetector )
799       {
800         DALI_LOG_INFO(gDragAndDropLogFilter, Debug::General, "EcoreEventDndPosition: position ( %d x %d )\n", positionEvent->position.x, positionEvent->position.y );
801         dndDetector->SetPosition( Vector2( positionEvent->position.x, positionEvent->position.y ));
802         dndDetector->EmitMovedSignal();
803       }
804     }
805
806     return ECORE_CALLBACK_PASS_ON;
807   }
808
809   /**
810    * Called when a dragged item leaves our window's bounds.
811    * This is when items are dragged INTO our window.
812    */
813   static Eina_Bool EcoreEventDndLeave( void* data, int type, void* event )
814   {
815     DALI_LOG_INFO(gDragAndDropLogFilter, Debug::Concise, "EcoreEventDndLeave\n" );
816
817     Ecore_X_Event_Xdnd_Leave* leaveEvent( (Ecore_X_Event_Xdnd_Leave*) event );
818     EventHandler* handler( (EventHandler*)data );
819
820     if ( leaveEvent->win == handler->mImpl->mWindow )
821     {
822       DragAndDropDetectorPtr dndDetector( handler->mDragAndDropDetector );
823
824       // If we have a detector then clear its content and emit the exited-signal. Also tell Ecore that we have finished.
825       if ( dndDetector )
826       {
827         dndDetector->ClearContent();
828         dndDetector->EmitExitedSignal();
829
830         ecore_x_dnd_send_finished();
831
832         DALI_LOG_INFO( gDragAndDropLogFilter, Debug::General, "EcoreEventDndLeave: Finished\n" );
833       }
834     }
835
836     return ECORE_CALLBACK_PASS_ON;
837   }
838
839   /**
840    * Called when the dragged item is dropped within our window's bounds.
841    * This is when items are dragged INTO our window.
842    */
843   static Eina_Bool EcoreEventDndDrop( void* data, int type, void* event )
844   {
845     DALI_LOG_INFO(gDragAndDropLogFilter, Debug::Concise, "EcoreEventDndDrop\n" );
846
847     Ecore_X_Event_Xdnd_Drop* dropEvent ( (Ecore_X_Event_Xdnd_Drop*) event);
848     EventHandler* handler( (EventHandler*)data );
849
850     if ( dropEvent->win == handler->mImpl->mWindow )
851     {
852       DragAndDropDetectorPtr dndDetector( handler->mDragAndDropDetector );
853
854       // Something has been dropped, inform the detector (if we have one) and tell Ecore that we have finished.
855       if ( dndDetector )
856       {
857         DALI_LOG_INFO(gDragAndDropLogFilter, Debug::General, "EcoreEventDndDrop: position ( %d x %d )\n", dropEvent->position.x, dropEvent->position.y );
858
859         dndDetector->SetPosition( Vector2( dropEvent->position.x, dropEvent->position.y ) );
860         dndDetector->EmitDroppedSignal();
861         ecore_x_dnd_send_finished();
862
863         DALI_LOG_INFO( gDragAndDropLogFilter, Debug::General, "EcoreEventDndDrop: Finished\n" );
864       }
865     }
866
867     return ECORE_CALLBACK_PASS_ON;
868   }
869
870   /**
871    * Called when a dragged item is moved from our window and the target window has done processing it.
872    * This is when items are dragged FROM our window.
873    */
874   static Eina_Bool EcoreEventDndFinished( void* data, int type, void* event )
875   {
876     DALI_LOG_INFO(gDragAndDropLogFilter, Debug::Concise, "EcoreEventDndFinished\n" );
877     return ECORE_CALLBACK_PASS_ON;
878   }
879
880   /**
881    * Called when a dragged item is moved from our window and the target window has sent us a status.
882    * This is when items are dragged FROM our window.
883    */
884   static Eina_Bool EcoreEventDndStatus( void* data, int type, void* event )
885   {
886     DALI_LOG_INFO(gDragAndDropLogFilter, Debug::Concise, "EcoreEventDndStatus\n" );
887     return ECORE_CALLBACK_PASS_ON;
888   }
889
890   /**
891    * Called when the client messages (i.e. the accessibility events) are received.
892    */
893   static Eina_Bool EcoreEventClientMessage( void* data, int type, void* event )
894   {
895 #ifndef DALI_PROFILE_UBUNTU
896     Ecore_X_Event_Client_Message* clientMessageEvent( (Ecore_X_Event_Client_Message*)event );
897     EventHandler* handler( (EventHandler*)data );
898
899     if (clientMessageEvent->message_type == ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL)
900     {
901       if ( ( (unsigned int)clientMessageEvent->data.l[0] == handler->mImpl->mWindow ) && handler->mAccessibilityManager )
902       {
903         AccessibilityManager* accessibilityManager( &AccessibilityManager::GetImplementation( handler->mAccessibilityManager ) );
904
905         if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_SCROLL)
906         {
907           // 2 finger touch & move, 2 finger flick
908
909           // mouse state : e->data.l[2] (0: mouse down, 1: mouse move, 2: mouse up)
910           // x : e->data.l[3]
911           // y : e->data.l[4]
912           TouchPoint::State state(TouchPoint::Down);
913
914           if ((unsigned int)clientMessageEvent->data.l[2] == 0)
915           {
916             state = TouchPoint::Down; // mouse down
917           }
918           else if ((unsigned int)clientMessageEvent->data.l[2] == 1)
919           {
920             state = TouchPoint::Motion; // mouse move
921           }
922           else if ((unsigned int)clientMessageEvent->data.l[2] == 2)
923           {
924             state = TouchPoint::Up; // mouse up
925           }
926           else
927           {
928             state = TouchPoint::Interrupted; // error
929           }
930
931           DALI_LOG_INFO(gClientMessageLogFilter, Debug::General,
932             "[%s:%d] [%d] %d, %d\n", __FUNCTION__, __LINE__,
933             (unsigned int)clientMessageEvent->data.l[2],
934             (unsigned int)clientMessageEvent->data.l[3], (unsigned int)clientMessageEvent->data.l[4]);
935
936           // Send touch event to accessibility manager.
937           TouchPoint point( 0, state, (float)clientMessageEvent->data.l[3], (float)clientMessageEvent->data.l[4] );
938
939           // In accessibility mode, scroll action should be handled when the currently focused actor is contained in scrollable control
940           accessibilityManager->HandleActionScrollEvent( point, GetCurrentMilliSeconds() );
941         }
942         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_MOUSE)
943         {
944           // 1 finger double tap and hold
945
946           // mouse state : e->data.l[2] (0: mouse down, 1: mouse move, 2: mouse up)
947           // x : e->data.l[3]
948           // y : e->data.l[4]
949           TouchPoint::State state(TouchPoint::Down);
950
951           if ((unsigned int)clientMessageEvent->data.l[2] == 0)
952           {
953             state = TouchPoint::Down; // mouse down
954           }
955           else if ((unsigned int)clientMessageEvent->data.l[2] == 1)
956           {
957             state = TouchPoint::Motion; // mouse move
958           }
959           else if ((unsigned int)clientMessageEvent->data.l[2] == 2)
960           {
961             state = TouchPoint::Up; // mouse up
962           }
963           else
964           {
965             state = TouchPoint::Interrupted; // error
966           }
967
968           DALI_LOG_INFO(gClientMessageLogFilter, Debug::General,
969             "[%s:%d] [%d] %d, %d\n", __FUNCTION__, __LINE__,
970             (unsigned int)clientMessageEvent->data.l[2],
971             (unsigned int)clientMessageEvent->data.l[3], (unsigned int)clientMessageEvent->data.l[4]);
972
973           // Send touch event to accessibility manager.
974           TouchPoint point( 0, state, (float)clientMessageEvent->data.l[3], (float)clientMessageEvent->data.l[4] );
975
976           // In accessibility mode, scroll action should be handled when the currently focused actor is contained in scrollable control
977           accessibilityManager->HandleActionTouchEvent( point, GetCurrentMilliSeconds() );
978         }
979         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_BACK)
980         {
981           // 2 finger circle draw, do back
982           accessibilityManager->HandleActionBackEvent();
983         }
984         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_NEXT)
985         {
986           // one finger flick down
987           // focus next object
988           if(accessibilityManager)
989           {
990             accessibilityManager->HandleActionNextEvent();
991           }
992         }
993         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_PREV)
994         {
995           // one finger flick up
996           // focus previous object
997           if(accessibilityManager)
998           {
999             accessibilityManager->HandleActionPreviousEvent();
1000           }
1001         }
1002         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_ACTIVATE)
1003         {
1004           // one finger double tap
1005           // same as one finger tap in normal mode (i.e. execute focused actor)
1006           if(accessibilityManager)
1007           {
1008             accessibilityManager->HandleActionActivateEvent();
1009           }
1010         }
1011         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ)
1012         {
1013           // one finger tap
1014           // focus & read an actor at ( e->data.l[2], e->data.l[3] ) position according to finger
1015           if(accessibilityManager)
1016           {
1017             accessibilityManager->HandleActionReadEvent((unsigned int)clientMessageEvent->data.l[2], (unsigned int)clientMessageEvent->data.l[3], true /* allow read again*/);
1018           }
1019         }
1020 #if defined(DALI_PROFILE_MOBILE)
1021         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_OVER)
1022         {
1023           // one finger tap & move
1024           // mouse state : e->data.l[2] (0: mouse down, 1: mouse move, 2: mouse up)
1025           // x : e->data.l[3]
1026           // y : e->data.l[4]
1027           // focus & read an actor at (x, y) position according to finger
1028           if(accessibilityManager && (unsigned int)clientMessageEvent->data.l[2] == 1 /*only work for move event*/)
1029           {
1030             accessibilityManager->HandleActionReadEvent((unsigned int)clientMessageEvent->data.l[3], (unsigned int)clientMessageEvent->data.l[4], false /* not allow read again*/);
1031           }
1032         }
1033 #endif
1034         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_NEXT)
1035         {
1036           // one finger flick right
1037           // focus next object
1038            if(accessibilityManager)
1039           {
1040             accessibilityManager->HandleActionReadNextEvent();
1041           }
1042         }
1043         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_PREV)
1044         {
1045           // one finger flick left
1046           // focus previous object
1047           if(accessibilityManager)
1048           {
1049             accessibilityManager->HandleActionReadPreviousEvent();
1050           }
1051         }
1052         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_UP)
1053         {
1054           // double down and move (right, up)
1055           // change slider value
1056           if(accessibilityManager)
1057           {
1058             accessibilityManager->HandleActionUpEvent();
1059           }
1060         }
1061         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_DOWN)
1062         {
1063           // double down and move (left, down)
1064           // change slider value
1065           if(accessibilityManager)
1066           {
1067             accessibilityManager->HandleActionDownEvent();
1068           }
1069         }
1070         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_ENABLE)
1071         {
1072            if(accessibilityManager)
1073           {
1074             accessibilityManager->HandleActionEnableEvent();
1075           }
1076         }
1077         else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_DISABLE)
1078         {
1079           if(accessibilityManager)
1080           {
1081             accessibilityManager->HandleActionDisableEvent();
1082           }
1083         }
1084         // TODO: some more actions could be added later
1085       }
1086     }
1087     else if(clientMessageEvent->message_type == ecore_x_atom_get(CLIPBOARD_ATOM))
1088     {
1089       std::string message(clientMessageEvent->data.b);
1090       if( message == CLIPBOARD_SET_OWNER_MESSAGE)
1091       {
1092         // Claim the ownership of the SECONDARY selection.
1093         ecore_x_selection_secondary_set(handler->mImpl->mWindow, "", 1);
1094
1095         // Show the clipboard window
1096         Dali::Clipboard clipboard = Dali::Clipboard::Get();
1097         clipboard.ShowClipboard();
1098       }
1099     }
1100     else if( clientMessageEvent->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE )
1101     {
1102       RotationEvent rotationEvent;
1103       rotationEvent.angle      = static_cast<int>(clientMessageEvent->data.l[1]);
1104       rotationEvent.winResize  = static_cast<int>(clientMessageEvent->data.l[2]);
1105       rotationEvent.width      = static_cast<int>(clientMessageEvent->data.l[3]);
1106       rotationEvent.height     = static_cast<int>(clientMessageEvent->data.l[4]);
1107       handler->SendRotationPrepareEvent( rotationEvent );
1108     }
1109     else if( clientMessageEvent->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST )
1110     {
1111       handler->SendRotationRequestEvent();
1112     }
1113
1114 #endif // DALI_PROFILE_UBUNTU
1115     return ECORE_CALLBACK_PASS_ON;
1116   }
1117
1118   /**
1119    * Called when the source window notifies us the content in clipboard is selected.
1120    */
1121   static Eina_Bool EcoreEventSelectionClear( void* data, int type, void* event )
1122   {
1123     DALI_LOG_INFO(gSelectionEventLogFilter, Debug::Concise, "EcoreEventSelectionClear\n" );
1124     Ecore_X_Event_Selection_Clear* selectionClearEvent( (Ecore_X_Event_Selection_Clear*) event );
1125     EventHandler* handler( (EventHandler*)data );
1126
1127     if ( selectionClearEvent->win == handler->mImpl->mWindow )
1128     {
1129       if ( selectionClearEvent->selection == ECORE_X_SELECTION_SECONDARY )
1130       {
1131         // Request to get the content from Ecore.
1132         ecore_x_selection_secondary_request(selectionClearEvent->win, ECORE_X_SELECTION_TARGET_TEXT);
1133       }
1134     }
1135     return ECORE_CALLBACK_PASS_ON;
1136   }
1137
1138   /**
1139    * Called when the source window sends us about the selected content.
1140    * For example, when dragged items are dragged INTO our window or when items are selected in the clipboard.
1141    */
1142   static Eina_Bool EcoreEventSelectionNotify( void* data, int type, void* event )
1143   {
1144     DALI_LOG_INFO(gSelectionEventLogFilter, Debug::Concise, "EcoreEventSelectionNotify\n" );
1145
1146     Ecore_X_Event_Selection_Notify* selectionNotifyEvent( (Ecore_X_Event_Selection_Notify*) event );
1147     EventHandler* handler( (EventHandler*)data );
1148
1149     if ( selectionNotifyEvent->win == handler->mImpl->mWindow )
1150     {
1151       Ecore_X_Selection_Data* selectionData( (Ecore_X_Selection_Data*) selectionNotifyEvent->data );
1152       if ( selectionData->data )
1153       {
1154         if ( selectionNotifyEvent->selection == ECORE_X_SELECTION_XDND )
1155         {
1156           DragAndDropDetectorPtr dndDetector( handler->mDragAndDropDetector );
1157
1158           // We have got the content that is to be dropped, inform the DndListener (if we have one).
1159           if ( dndDetector )
1160           {
1161             std::string content( (char*) selectionData->data, selectionData->length );
1162             dndDetector->SetContent( content );
1163
1164             DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "EcoreEventSelectionNotify: Content(%d):\n" , selectionData->length );
1165             DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "======================================\n" );
1166             DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "%s\n", selectionData->data );
1167             DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "======================================\n" );
1168           }
1169         }
1170         else if ( selectionNotifyEvent->selection == ECORE_X_SELECTION_SECONDARY )
1171         {
1172           // We have got the selected content, inform the clipboard event listener (if we have one).
1173           if ( handler->mClipboardEventNotifier )
1174           {
1175             ClipboardEventNotifier& clipboardEventNotifier( ClipboardEventNotifier::GetImplementation( handler->mClipboardEventNotifier ) );
1176             std::string content( (char*) selectionData->data, selectionData->length );
1177             clipboardEventNotifier.SetContent( content );
1178             clipboardEventNotifier.EmitContentSelectedSignal();
1179           }
1180
1181           // Claim the ownership of the SECONDARY selection.
1182           ecore_x_selection_secondary_set(handler->mImpl->mWindow, "", 1);
1183
1184           DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "EcoreEventSelectionNotify: Content(%d):\n" , selectionData->length );
1185           DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "======================================\n" );
1186           DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "%s\n", selectionData->data );
1187           DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "======================================\n" );
1188         }
1189       }
1190     }
1191     return ECORE_CALLBACK_PASS_ON;
1192   }
1193
1194
1195 #ifndef DALI_PROFILE_UBUNTU
1196   /////////////////////////////////////////////////////////////////////////////////////////////////
1197   // Font Callbacks
1198   /////////////////////////////////////////////////////////////////////////////////////////////////
1199   /**
1200    * Called when a font name is changed.
1201    */
1202   static void VconfNotifyFontNameChanged( keynode_t* node, void* data )
1203   {
1204     EventHandler* handler = static_cast<EventHandler*>( data );
1205     handler->SendEvent( StyleChange::DEFAULT_FONT_CHANGE );
1206   }
1207
1208   /**
1209    * Called when a font size is changed.
1210    */
1211   static void VconfNotifyFontSizeChanged( keynode_t* node, void* data )
1212   {
1213     EventHandler* handler = static_cast<EventHandler*>( data );
1214     handler->SendEvent( StyleChange::DEFAULT_FONT_SIZE_CHANGE );
1215   }
1216 #endif // DALI_PROFILE_UBUNTU
1217
1218   // Data
1219   EventHandler* mHandler;
1220   std::vector<Ecore_Event_Handler*> mEcoreEventHandler;
1221   Ecore_X_Window mWindow;
1222   int mXiDeviceId;
1223 };
1224
1225 EventHandler::EventHandler( RenderSurface* surface, CoreEventInterface& coreEventInterface, GestureManager& gestureManager, DamageObserver& damageObserver, DragAndDropDetectorPtr dndDetector )
1226 : mCoreEventInterface(coreEventInterface),
1227   mGestureManager( gestureManager ),
1228   mStyleMonitor( StyleMonitor::Get() ),
1229   mDamageObserver( damageObserver ),
1230   mRotationObserver( NULL ),
1231   mDragAndDropDetector( dndDetector ),
1232   mAccessibilityManager( AccessibilityManager::Get() ),
1233   mClipboardEventNotifier( ClipboardEventNotifier::Get() ),
1234   mClipboard(Clipboard::Get()),
1235   mImpl( NULL )
1236 {
1237   Ecore_X_Window window = 0;
1238
1239   // this code only works with the EcoreX11 RenderSurface so need to downcast
1240   ECore::WindowRenderSurface* ecoreSurface = dynamic_cast< ECore::WindowRenderSurface* >( surface );
1241   if( ecoreSurface )
1242   {
1243     // enable multi touch
1244     window = ecoreSurface->GetXWindow();
1245   }
1246
1247   mImpl = new Impl(this, window);
1248 }
1249
1250 EventHandler::~EventHandler()
1251 {
1252   if(mImpl)
1253   {
1254     delete mImpl;
1255   }
1256
1257   mGestureManager.Stop();
1258 }
1259
1260 void EventHandler::SendEvent(TouchPoint& point, unsigned long timeStamp)
1261 {
1262   if(timeStamp < 1)
1263   {
1264     timeStamp = GetCurrentMilliSeconds();
1265   }
1266
1267   Integration::TouchEvent touchEvent;
1268   Integration::HoverEvent hoverEvent;
1269   Integration::TouchEventCombiner::EventDispatchType type = mCombiner.GetNextTouchEvent(point, timeStamp, touchEvent, hoverEvent);
1270   if(type != Integration::TouchEventCombiner::DispatchNone )
1271   {
1272     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);
1273
1274     // First the touch and/or hover event & related gesture events are queued
1275     if(type == Integration::TouchEventCombiner::DispatchTouch || type == Integration::TouchEventCombiner::DispatchBoth)
1276     {
1277       mCoreEventInterface.QueueCoreEvent( touchEvent );
1278       mGestureManager.SendEvent(touchEvent);
1279     }
1280
1281     if(type == Integration::TouchEventCombiner::DispatchHover || type == Integration::TouchEventCombiner::DispatchBoth)
1282     {
1283       mCoreEventInterface.QueueCoreEvent( hoverEvent );
1284     }
1285
1286     // Next the events are processed with a single call into Core
1287     mCoreEventInterface.ProcessCoreEvents();
1288   }
1289 }
1290
1291 void EventHandler::SendEvent(KeyEvent& keyEvent)
1292 {
1293   Dali::PhysicalKeyboard physicalKeyboard = PhysicalKeyboard::Get();
1294   if ( physicalKeyboard )
1295   {
1296     if ( ! KeyLookup::IsDeviceButton( keyEvent.keyPressedName.c_str() ) )
1297     {
1298       GetImplementation( physicalKeyboard ).KeyReceived( keyEvent.time > 1 );
1299     }
1300   }
1301
1302   // Create KeyEvent and send to Core.
1303   Integration::KeyEvent event(keyEvent.keyPressedName, keyEvent.keyPressed, keyEvent.keyCode,
1304   keyEvent.keyModifier, keyEvent.time, static_cast<Integration::KeyEvent::State>(keyEvent.state));
1305   mCoreEventInterface.QueueCoreEvent( event );
1306   mCoreEventInterface.ProcessCoreEvents();
1307 }
1308
1309 void EventHandler::SendWheelEvent( WheelEvent& wheelEvent )
1310 {
1311   // Create WheelEvent and send to Core.
1312   Integration::WheelEvent event( static_cast< Integration::WheelEvent::Type >(wheelEvent.type), wheelEvent.direction, wheelEvent.modifiers, wheelEvent.point, wheelEvent.z, wheelEvent.timeStamp );
1313   mCoreEventInterface.QueueCoreEvent( event );
1314   mCoreEventInterface.ProcessCoreEvents();
1315 }
1316
1317 void EventHandler::SendEvent( StyleChange::Type styleChange )
1318 {
1319   DALI_ASSERT_DEBUG( mStyleMonitor && "StyleMonitor Not Available" );
1320   GetImplementation( mStyleMonitor ).StyleChanged(styleChange);
1321 }
1322
1323 void EventHandler::SendEvent( const DamageArea& area )
1324 {
1325   mDamageObserver.OnDamaged( area );
1326 }
1327
1328 void EventHandler::SendRotationPrepareEvent( const RotationEvent& event )
1329 {
1330   if( mRotationObserver != NULL )
1331   {
1332     mRotationObserver->OnRotationPrepare( event );
1333   }
1334 }
1335
1336 void EventHandler::SendRotationRequestEvent( )
1337 {
1338   if( mRotationObserver != NULL )
1339   {
1340     mRotationObserver->OnRotationRequest( );
1341   }
1342 }
1343
1344 void EventHandler::FeedTouchPoint( TouchPoint& point, int timeStamp)
1345 {
1346   SendEvent(point, timeStamp);
1347 }
1348
1349 void EventHandler::FeedWheelEvent( WheelEvent& wheelEvent )
1350 {
1351   SendWheelEvent( wheelEvent );
1352 }
1353
1354 void EventHandler::FeedKeyEvent( KeyEvent& event )
1355 {
1356   SendEvent( event );
1357 }
1358
1359 void EventHandler::FeedEvent( Integration::Event& event )
1360 {
1361   mCoreEventInterface.QueueCoreEvent( event );
1362   mCoreEventInterface.ProcessCoreEvents();
1363 }
1364
1365 void EventHandler::Reset()
1366 {
1367   mCombiner.Reset();
1368
1369   // Any touch listeners should be told of the interruption.
1370   Integration::TouchEvent event;
1371   TouchPoint point(0, TouchPoint::Interrupted, 0, 0);
1372   event.AddPoint( point );
1373
1374   // First the touch event & related gesture events are queued
1375   mCoreEventInterface.QueueCoreEvent( event );
1376   mGestureManager.SendEvent( event );
1377
1378   // Next the events are processed with a single call into Core
1379   mCoreEventInterface.ProcessCoreEvents();
1380 }
1381
1382 void EventHandler::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
1383 {
1384   mDragAndDropDetector = detector;
1385 }
1386
1387 void EventHandler::SetRotationObserver( RotationObserver* observer )
1388 {
1389   mRotationObserver = observer;
1390 }
1391
1392 } // namespace Adaptor
1393
1394 } // namespace Internal
1395
1396 } // namespace Dali