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