2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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
8 // http://floralicense.org/license/
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.
18 #include "event-handler.h"
22 #include <Ecore_Input.h>
30 #include <vconf-keys.h>
32 #include <dali/public-api/events/touch-point.h>
33 #include <dali/public-api/events/key-event.h>
34 #include <dali/public-api/events/mouse-wheel-event.h>
35 #include <dali/integration-api/debug.h>
36 #include <dali/integration-api/events/key-event-integ.h>
37 #include <dali/integration-api/events/touch-event-integ.h>
38 #include <dali/integration-api/events/mouse-wheel-event-integ.h>
41 #include <internal/common/events/gesture-manager.h>
42 #include <internal/common/ecore-x/window-render-surface.h>
43 #include <internal/common/clipboard-impl.h>
44 #include <internal/common/key-impl.h>
45 #include <internal/common/physical-keyboard-impl.h>
46 #include <internal/common/style-monitor-impl.h>
47 #include <base/core-event-interface.h>
60 #if defined(DEBUG_ENABLED)
63 Integration::Log::Filter* gTouchEventLogFilter = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_TOUCH");
64 Integration::Log::Filter* gClientMessageLogFilter = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_CLIENT_MESSAGE");
65 Integration::Log::Filter* gDragAndDropLogFilter = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_DND");
66 Integration::Log::Filter* gImfLogging = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_IMF");
67 Integration::Log::Filter* gSelectionEventLogFilter = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_SELECTION");
68 } // unnamed namespace
74 // Currently this code is internal to dali/dali/internal/event/text/utf8.h but should be made Public and used from there instead.
75 size_t Utf8SequenceLength(const unsigned char leadByte)
79 if ((leadByte & 0x80) == 0 ) //ASCII character (lead bit zero)
83 else if (( leadByte & 0xe0 ) == 0xc0 ) //110x xxxx
87 else if (( leadByte & 0xf0 ) == 0xe0 ) //1110 xxxx
91 else if (( leadByte & 0xf8 ) == 0xf0 ) //1111 0xxx
97 DALI_LOG_WARNING("Unrecognized lead byte %c\n", leadByte);
103 const unsigned int PRIMARY_TOUCH_BUTTON_ID( 1 );
105 const char * CLIPBOARD_ATOM = "CBHM_MSG";
106 const char * CLIPBOARD_SET_OWNER_MESSAGE = "SET_OWNER";
108 /// The atoms required by Ecore for Drag & Drop behaviour.
109 Ecore_X_Atom DRAG_AND_DROP_ATOMS[] =
111 ECORE_X_ATOM_XDND_ACTION_COPY,
114 /// The types that we support.
115 const char * DRAG_AND_DROP_TYPES[] =
117 ECORE_X_SELECTION_TARGET_UTF8_STRING,
120 const unsigned int DRAG_AND_DROP_ATOMS_NUMBER = sizeof( DRAG_AND_DROP_ATOMS ) / sizeof( Ecore_X_Atom );
121 const unsigned int DRAG_AND_DROP_TYPES_NUMBER = sizeof( DRAG_AND_DROP_TYPES ) / sizeof( const char * );
123 const unsigned int BYTES_PER_CHARACTER_FOR_ATTRIBUTES = 3;
126 * Ecore_Event_Modifier enums in Ecore_Input.h do not match Ecore_IMF_Keyboard_Modifiers in Ecore_IMF.h.
127 * This function converts from Ecore_Event_Modifier to Ecore_IMF_Keyboard_Modifiers enums.
128 * @param[in] ecoreModifier the Ecore_Event_Modifier input.
129 * @return the Ecore_IMF_Keyboard_Modifiers output.
131 Ecore_IMF_Keyboard_Modifiers EcoreInputModifierToEcoreIMFModifier(unsigned int ecoreModifier)
133 int modifier( ECORE_IMF_KEYBOARD_MODIFIER_NONE ); // If no other matches returns NONE.
136 if ( ecoreModifier & ECORE_EVENT_MODIFIER_SHIFT ) // enums from ecore_input/Ecore_Input.h
138 modifier |= ECORE_IMF_KEYBOARD_MODIFIER_SHIFT; // enums from ecore_imf/ecore_imf.h
141 if ( ecoreModifier & ECORE_EVENT_MODIFIER_ALT )
143 modifier |= ECORE_IMF_KEYBOARD_MODIFIER_ALT;
146 if ( ecoreModifier & ECORE_EVENT_MODIFIER_CTRL )
148 modifier |= ECORE_IMF_KEYBOARD_MODIFIER_CTRL;
151 if ( ecoreModifier & ECORE_EVENT_MODIFIER_WIN )
153 modifier |= ECORE_IMF_KEYBOARD_MODIFIER_WIN;
156 if ( ecoreModifier & ECORE_EVENT_MODIFIER_ALTGR )
158 modifier |= ECORE_IMF_KEYBOARD_MODIFIER_ALTGR;
161 return static_cast<Ecore_IMF_Keyboard_Modifiers>( modifier );
165 // Copied from x server
166 static unsigned int GetCurrentMilliSeconds(void)
171 static clockid_t clockid;
175 #ifdef CLOCK_MONOTONIC_COARSE
176 if (clock_getres(CLOCK_MONOTONIC_COARSE, &tp) == 0 &&
177 (tp.tv_nsec / 1000) <= 1000 && clock_gettime(CLOCK_MONOTONIC_COARSE, &tp) == 0)
179 clockid = CLOCK_MONOTONIC_COARSE;
183 if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
185 clockid = CLOCK_MONOTONIC;
192 if (clockid != ~0L && clock_gettime(clockid, &tp) == 0)
194 return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
197 gettimeofday(&tv, NULL);
198 return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
201 const char * DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE = "db/setting/accessibility/font_name"; // It will be update at vconf-key.h and replaced.
203 } // unnamed namespace
205 // Impl to hide EFL implementation.
206 struct EventHandler::Impl
208 // Construction & Destruction
213 Impl( EventHandler* handler, Ecore_X_Window window )
214 : mHandler( handler ),
215 mEcoreEventHandler(),
218 // Only register for touch and key events if we have a window
221 // Register Touch events
222 mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_EVENT_MOUSE_BUTTON_DOWN, EcoreEventMouseButtonDown, handler ) );
223 mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_EVENT_MOUSE_BUTTON_UP, EcoreEventMouseButtonUp, handler ) );
224 mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_EVENT_MOUSE_MOVE, EcoreEventMouseButtonMove, handler ) );
225 mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_EVENT_MOUSE_OUT, EcoreEventMouseButtonUp, handler ) ); // process mouse out event like up event
227 // Register Mouse wheel events
228 mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_EVENT_MOUSE_WHEEL, EcoreEventMouseWheel, handler ) );
230 // Register Key events
231 mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_EVENT_KEY_DOWN, EcoreEventKeyDown, handler ) );
232 mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_EVENT_KEY_UP, EcoreEventKeyUp, handler ) );
234 // Register Focus events
235 mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_X_EVENT_WINDOW_FOCUS_IN, EcoreEventWindowFocusIn, handler ) );
236 mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_X_EVENT_WINDOW_FOCUS_OUT, EcoreEventWindowFocusOut, handler ) );
238 // Register Window damage events
239 mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_X_EVENT_WINDOW_DAMAGE, EcoreEventWindowDamaged, handler ) );
241 // Enable Drag & Drop and register DnD events
242 ecore_x_dnd_aware_set( window, EINA_TRUE );
243 mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_X_EVENT_XDND_ENTER, EcoreEventDndEnter, handler) );
244 mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_X_EVENT_XDND_POSITION, EcoreEventDndPosition, handler) );
245 mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_X_EVENT_XDND_LEAVE, EcoreEventDndLeave, handler) );
246 mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_X_EVENT_XDND_DROP, EcoreEventDndDrop, handler) );
247 mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_X_EVENT_XDND_FINISHED, EcoreEventDndFinished, handler) );
248 mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_X_EVENT_XDND_STATUS, EcoreEventDndStatus, handler) );
250 // Register Client message events - accessibility etc.
251 mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_X_EVENT_CLIENT_MESSAGE, EcoreEventClientMessage, handler ) );
253 // Register Selection event - clipboard selection, Drag & Drop selection etc.
254 mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_X_EVENT_SELECTION_CLEAR, EcoreEventSelectionClear, handler ) );
255 mEcoreEventHandler.push_back( ecore_event_handler_add( ECORE_X_EVENT_SELECTION_NOTIFY, EcoreEventSelectionNotify, handler ) );
257 // Register Vconf notify - font name and size
258 vconf_notify_key_changed( DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, VconfNotifyFontNameChanged, handler );
259 vconf_notify_key_changed( VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, VconfNotifyFontSizeChanged, handler );
268 vconf_ignore_key_changed( VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, VconfNotifyFontSizeChanged );
269 vconf_ignore_key_changed( DALI_VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, VconfNotifyFontNameChanged );
271 for( std::vector<Ecore_Event_Handler*>::iterator iter = mEcoreEventHandler.begin(), endIter = mEcoreEventHandler.end(); iter != endIter; ++iter )
273 ecore_event_handler_del( *iter );
279 /////////////////////////////////////////////////////////////////////////////////////////////////
281 /////////////////////////////////////////////////////////////////////////////////////////////////
284 * Called when a touch down is received.
286 static Eina_Bool EcoreEventMouseButtonDown( void* data, int type, void* event )
288 Ecore_Event_Mouse_Button *touchEvent( (Ecore_Event_Mouse_Button*)event );
289 EventHandler* handler( (EventHandler*)data );
291 if ( touchEvent->window == handler->mImpl->mWindow )
293 TouchPoint::State state ( TouchPoint::Down );
295 // Check if the buttons field is set and ensure it's the primary touch button.
296 // If this event was triggered by buttons other than the primary button (used for touch), then
297 // just send an interrupted event to Core.
298 if ( touchEvent->buttons && (touchEvent->buttons != PRIMARY_TOUCH_BUTTON_ID ) )
300 state = TouchPoint::Interrupted;
303 TouchPoint point( touchEvent->multi.device, state, touchEvent->x, touchEvent->y );
304 handler->SendEvent( point, touchEvent->timestamp );
307 return ECORE_CALLBACK_PASS_ON;
311 * Called when a touch up is received.
313 static Eina_Bool EcoreEventMouseButtonUp( void* data, int type, void* event )
315 Ecore_Event_Mouse_Button *touchEvent( (Ecore_Event_Mouse_Button*)event );
316 EventHandler* handler( (EventHandler*)data );
318 if ( touchEvent->window == handler->mImpl->mWindow )
320 TouchPoint point( touchEvent->multi.device, TouchPoint::Up, touchEvent->x, touchEvent->y );
321 handler->SendEvent( point, touchEvent->timestamp );
324 return ECORE_CALLBACK_PASS_ON;
328 * Called when a touch up is received.
330 static Eina_Bool EcoreEventMouseWheel( void* data, int type, void* event )
332 Ecore_Event_Mouse_Wheel *mouseWheelEvent( (Ecore_Event_Mouse_Wheel*)event );
334 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);
336 EventHandler* handler( (EventHandler*)data );
337 if ( mouseWheelEvent->window == handler->mImpl->mWindow )
339 MouseWheelEvent wheelEvent(mouseWheelEvent->direction, mouseWheelEvent->modifiers, Vector2(mouseWheelEvent->x, mouseWheelEvent->y), mouseWheelEvent->z, mouseWheelEvent->timestamp);
340 handler->SendMouseWheelEvent( wheelEvent );
342 return ECORE_CALLBACK_PASS_ON;
346 * Called when a touch motion is received.
348 static Eina_Bool EcoreEventMouseButtonMove( void* data, int type, void* event )
350 Ecore_Event_Mouse_Move *touchEvent( (Ecore_Event_Mouse_Move*)event );
351 EventHandler* handler( (EventHandler*)data );
353 if ( touchEvent->window == handler->mImpl->mWindow )
355 TouchPoint point( touchEvent->multi.device, TouchPoint::Motion, touchEvent->x, touchEvent->y );
356 handler->SendEvent( point, touchEvent->timestamp );
359 return ECORE_CALLBACK_PASS_ON;
362 /////////////////////////////////////////////////////////////////////////////////////////////////
364 /////////////////////////////////////////////////////////////////////////////////////////////////
367 * Called when a key down is received.
369 static Eina_Bool EcoreEventKeyDown( void* data, int type, void* event )
371 DALI_LOG_INFO( gImfLogging, Debug::General, "EVENT >>EcoreEventKeyDown \n" );
373 EventHandler* handler( (EventHandler*)data );
374 Ecore_Event_Key *keyEvent( (Ecore_Event_Key*)event );
375 bool eventHandled( false );
377 Ecore_IMF_Context* imfContext = NULL;
378 if ( Dali::Adaptor::IsAvailable() && handler->mImfManager )
380 imfContext = reinterpret_cast<Ecore_IMF_Context*>( handler->mImfManager.GetContext() );
383 // If a device key then skip ecore_imf_context_filter_event.
384 if ( imfContext && !( KeyLookup::IsDeviceButton( keyEvent->keyname ) ) )
386 // We're consuming key down event so we have to pass to IMF so that it can parse it as well.
387 Ecore_IMF_Event_Key_Down ecoreKeyDownEvent;
388 ecoreKeyDownEvent.keyname = keyEvent->keyname;
389 ecoreKeyDownEvent.key = keyEvent->key;
390 ecoreKeyDownEvent.string = keyEvent->string;
391 ecoreKeyDownEvent.compose = keyEvent->compose;
392 ecoreKeyDownEvent.timestamp = keyEvent->timestamp;
393 ecoreKeyDownEvent.modifiers = EcoreInputModifierToEcoreIMFModifier ( keyEvent->modifiers );
394 ecoreKeyDownEvent.locks = (Ecore_IMF_Keyboard_Locks) ECORE_IMF_KEYBOARD_LOCK_NONE;
396 eventHandled = ecore_imf_context_filter_event( imfContext,
397 ECORE_IMF_EVENT_KEY_DOWN,
398 (Ecore_IMF_Event *) &ecoreKeyDownEvent );
400 // If the event has not been handled by IMF then check if we should reset our IMF context
403 if ( !strcmp( keyEvent->keyname, "Escape" ) ||
404 !strcmp( keyEvent->keyname, "Return" ) ||
405 !strcmp( keyEvent->keyname, "KP_Enter" ) )
407 ecore_imf_context_reset( imfContext );
412 // If the event wasn't handled then we should send a key event.
415 if ( keyEvent->window == handler->mImpl->mWindow )
417 std::string keyName( keyEvent->keyname );
418 std::string keyString( "" );
419 int keyCode = ecore_x_keysym_keycode_get(keyEvent->keyname);
420 int modifier( keyEvent->modifiers );
421 unsigned long time = keyEvent->timestamp;
423 // Ensure key event string is not NULL as keys like SHIFT have a null string.
424 if ( keyEvent->string )
426 keyString = keyEvent->string;
429 KeyEvent keyEvent(keyName, keyString, keyCode, modifier, time, KeyEvent::Down);
430 handler->SendEvent( keyEvent );
434 return ECORE_CALLBACK_PASS_ON;
438 * Called when a key up is received.
440 static Eina_Bool EcoreEventKeyUp( void* data, int type, void* event )
442 DALI_LOG_INFO( gImfLogging, Debug::General, "EVENT >>EcoreEventKeyUp \n" );
444 EventHandler* handler( (EventHandler*)data );
445 Ecore_Event_Key *keyEvent( (Ecore_Event_Key*)event );
446 bool eventHandled( false );
448 Ecore_IMF_Context* imfContext = NULL;
449 if ( Dali::Adaptor::IsAvailable() && handler->mImfManager )
451 imfContext = reinterpret_cast<Ecore_IMF_Context*>( handler->mImfManager.GetContext() );
454 // XF86Stop and XF86Send must skip ecore_imf_context_filter_event.
455 if ( imfContext && strcmp( keyEvent->keyname, "XF86Send" ) && strcmp( keyEvent->keyname, "XF86Phone" ) && strcmp( keyEvent->keyname, "XF86Stop" ) )
458 // We're consuming key up event so we have to pass to IMF so that it can parse it as well.
459 Ecore_IMF_Event_Key_Up ecoreKeyUpEvent;
460 ecoreKeyUpEvent.keyname = keyEvent->keyname;
461 ecoreKeyUpEvent.key = keyEvent->key;
462 ecoreKeyUpEvent.string = keyEvent->string;
463 ecoreKeyUpEvent.compose = keyEvent->compose;
464 ecoreKeyUpEvent.timestamp = keyEvent->timestamp;
465 ecoreKeyUpEvent.modifiers = EcoreInputModifierToEcoreIMFModifier ( keyEvent->modifiers );
466 ecoreKeyUpEvent.locks = (Ecore_IMF_Keyboard_Locks) ECORE_IMF_KEYBOARD_LOCK_NONE;
468 eventHandled = ecore_imf_context_filter_event( imfContext,
469 ECORE_IMF_EVENT_KEY_UP,
470 (Ecore_IMF_Event *) &ecoreKeyUpEvent );
473 // If the event wasn't handled then we should send a key event.
476 if ( keyEvent->window == handler->mImpl->mWindow )
478 std::string keyName( keyEvent->keyname );
479 std::string keyString( "" );
480 int keyCode = ecore_x_keysym_keycode_get(keyEvent->keyname);
481 int modifier( keyEvent->modifiers );
482 unsigned long time( keyEvent->timestamp );
484 // Ensure key event string is not NULL as keys like SHIFT have a null string.
485 if ( keyEvent->string )
487 keyString = keyEvent->string;
490 KeyEvent keyEvent(keyName, keyString, keyCode, modifier, time, KeyEvent::Up);
491 handler->SendEvent( keyEvent );
496 return ECORE_CALLBACK_PASS_ON;
499 /////////////////////////////////////////////////////////////////////////////////////////////////
501 /////////////////////////////////////////////////////////////////////////////////////////////////
504 * Called when the window gains focus.
506 static Eina_Bool EcoreEventWindowFocusIn( void* data, int type, void* event )
508 Ecore_X_Event_Window_Focus_In* focusInEvent( (Ecore_X_Event_Window_Focus_In*)event );
509 EventHandler* handler( (EventHandler*)data );
511 DALI_LOG_INFO( gImfLogging, Debug::General, "EVENT >>EcoreEventWindowFocusIn \n" );
513 // If the window gains focus and we hid the keyboard then show it again.
514 if ( focusInEvent->win == handler->mImpl->mWindow )
516 DALI_LOG_INFO( gImfLogging, Debug::General, "EVENT EcoreEventWindowFocusIn - >>WindowFocusGained \n" );
518 if ( handler->mImfManager )
520 ImfManager& imfManager( ImfManager::GetImplementation( handler->mImfManager ) );
521 if( imfManager.RestoreAfterFocusLost() )
523 imfManager.Activate();
526 // No need to connect callbacks as KeyboardStatusChanged will be called.
529 return ECORE_CALLBACK_PASS_ON;
533 * Called when the window loses focus.
535 static Eina_Bool EcoreEventWindowFocusOut( void* data, int type, void* event )
537 Ecore_X_Event_Window_Focus_Out* focusOutEvent( (Ecore_X_Event_Window_Focus_Out*)event );
538 EventHandler* handler( (EventHandler*)data );
540 DALI_LOG_INFO( gImfLogging, Debug::General, "EVENT >>EcoreEventWindowFocusOut \n" );
542 // If the window loses focus then hide the keyboard.
543 if ( focusOutEvent->win == handler->mImpl->mWindow )
545 if ( handler->mImfManager )
547 ImfManager& imfManager( ImfManager::GetImplementation( handler->mImfManager ) );
548 if( imfManager.RestoreAfterFocusLost() )
550 imfManager.Deactivate();
554 // Clipboard don't support that whether clipboard is shown or not. Hide clipboard.
555 Dali::Clipboard clipboard = Clipboard::Get();
556 clipboard.HideClipboard();
559 return ECORE_CALLBACK_PASS_ON;
563 * Called when the window is damaged.
565 static Eina_Bool EcoreEventWindowDamaged(void *data, int type, void *event)
567 Ecore_X_Event_Window_Damage* windowDamagedEvent( (Ecore_X_Event_Window_Damage*)event );
568 EventHandler* handler( (EventHandler*)data );
570 if( windowDamagedEvent->win == handler->mImpl->mWindow )
573 area.x = windowDamagedEvent->x;
574 area.y = windowDamagedEvent->y;
575 area.width = windowDamagedEvent->w;
576 area.height = windowDamagedEvent->h;
578 handler->SendEvent( area );
581 return ECORE_CALLBACK_PASS_ON;
585 * Called when the window properties are changed.
586 * We are only interested in the font change.
590 /////////////////////////////////////////////////////////////////////////////////////////////////
591 // Drag & Drop Callbacks
592 /////////////////////////////////////////////////////////////////////////////////////////////////
595 * Called when a dragged item enters our window's bounds.
596 * This is when items are dragged INTO our window.
598 static Eina_Bool EcoreEventDndEnter( void* data, int type, void* event )
600 DALI_LOG_INFO( gDragAndDropLogFilter, Debug::Concise, "EcoreEventDndEnter\n" );
602 Ecore_X_Event_Xdnd_Enter* enterEvent( (Ecore_X_Event_Xdnd_Enter*) event );
603 EventHandler* handler( (EventHandler*)data );
604 Ecore_X_Window window ( handler->mImpl->mWindow );
606 if ( enterEvent->win == window )
608 DragAndDropDetectorPtr dndDetector( handler->mDragAndDropDetector );
610 // Check whether the Drag & Drop detector has Drag & Drop behaviour enabled before we accept.
611 if ( dndDetector && dndDetector->IsEnabled() )
613 // Tell Ecore that we want to enable drop in the entire window.
614 Ecore_X_Rectangle rect;
616 ecore_x_window_geometry_get( window, NULL, NULL, (int*)&rect.width, (int*)&rect.height );
618 // Tell Ecore that we are able to process a drop.
619 ecore_x_dnd_send_status( EINA_TRUE, EINA_FALSE, rect, ECORE_X_ATOM_XDND_DROP );
621 // Register the required atoms and types.
622 ecore_x_dnd_actions_set( window, DRAG_AND_DROP_ATOMS, DRAG_AND_DROP_ATOMS_NUMBER );
623 ecore_x_dnd_types_set( window, DRAG_AND_DROP_TYPES, DRAG_AND_DROP_TYPES_NUMBER );
625 // Request to get the content from Ecore.
626 ecore_x_selection_xdnd_request( window, ECORE_X_SELECTION_TARGET_UTF8_STRING );
628 DALI_LOG_INFO( gDragAndDropLogFilter, Debug::General, "EcoreEventDndEnter: Requesting Drag & Drop\n" );
630 // Clear the previous content
631 dndDetector->ClearContent();
633 // Emit the entered signal
634 dndDetector->EmitEnteredSignal();
638 return ECORE_CALLBACK_PASS_ON;
642 * Called when a dragged item is moved within our window.
643 * This is when items are dragged INTO our window.
645 static Eina_Bool EcoreEventDndPosition( void* data, int type, void* event )
647 DALI_LOG_INFO(gDragAndDropLogFilter, Debug::Concise, "EcoreEventDndPosition\n" );
649 Ecore_X_Event_Xdnd_Position* positionEvent( (Ecore_X_Event_Xdnd_Position*) event );
650 EventHandler* handler( (EventHandler*)data );
652 if ( positionEvent->win == handler->mImpl->mWindow )
654 DragAndDropDetectorPtr dndDetector( handler->mDragAndDropDetector );
656 // If we have a detector then update its latest position.
659 DALI_LOG_INFO(gDragAndDropLogFilter, Debug::General, "EcoreEventDndPosition: position ( %d x %d )\n", positionEvent->position.x, positionEvent->position.y );
660 dndDetector->SetPosition( Vector2( positionEvent->position.x, positionEvent->position.y ));
661 dndDetector->EmitMovedSignal();
664 return ECORE_CALLBACK_PASS_ON;
668 * Called when a dragged item leaves our window's bounds.
669 * This is when items are dragged INTO our window.
671 static Eina_Bool EcoreEventDndLeave( void* data, int type, void* event )
673 DALI_LOG_INFO(gDragAndDropLogFilter, Debug::Concise, "EcoreEventDndLeave\n" );
675 Ecore_X_Event_Xdnd_Leave* leaveEvent( (Ecore_X_Event_Xdnd_Leave*) event );
676 EventHandler* handler( (EventHandler*)data );
678 if ( leaveEvent->win == handler->mImpl->mWindow )
680 DragAndDropDetectorPtr dndDetector( handler->mDragAndDropDetector );
682 // If we have a detector then clear its content and emit the exited-signal. Also tell Ecore that we have finished.
685 dndDetector->ClearContent();
686 dndDetector->EmitExitedSignal();
688 ecore_x_dnd_send_finished();
690 DALI_LOG_INFO( gDragAndDropLogFilter, Debug::General, "EcoreEventDndLeave: Finished\n" );
693 return ECORE_CALLBACK_PASS_ON;
697 * Called when the dragged item is dropped within our window's bounds.
698 * This is when items are dragged INTO our window.
700 static Eina_Bool EcoreEventDndDrop( void* data, int type, void* event )
702 DALI_LOG_INFO(gDragAndDropLogFilter, Debug::Concise, "EcoreEventDndDrop\n" );
704 Ecore_X_Event_Xdnd_Drop* dropEvent ( (Ecore_X_Event_Xdnd_Drop*) event);
705 EventHandler* handler( (EventHandler*)data );
707 if ( dropEvent->win == handler->mImpl->mWindow )
709 DragAndDropDetectorPtr dndDetector( handler->mDragAndDropDetector );
711 // Something has been dropped, inform the detector (if we have one) and tell Ecore that we have finished.
714 DALI_LOG_INFO(gDragAndDropLogFilter, Debug::General, "EcoreEventDndDrop: position ( %d x %d )\n", dropEvent->position.x, dropEvent->position.y );
716 dndDetector->SetPosition( Vector2( dropEvent->position.x, dropEvent->position.y ) );
717 dndDetector->EmitDroppedSignal();
718 ecore_x_dnd_send_finished();
720 DALI_LOG_INFO( gDragAndDropLogFilter, Debug::General, "EcoreEventDndDrop: Finished\n" );
724 return ECORE_CALLBACK_PASS_ON;
728 * Called when a dragged item is moved from our window and the target window has done processing it.
729 * This is when items are dragged FROM our window.
731 static Eina_Bool EcoreEventDndFinished( void* data, int type, void* event )
733 DALI_LOG_INFO(gDragAndDropLogFilter, Debug::Concise, "EcoreEventDndFinished\n" );
734 return ECORE_CALLBACK_PASS_ON;
738 * Called when a dragged item is moved from our window and the target window has sent us a status.
739 * This is when items are dragged FROM our window.
741 static Eina_Bool EcoreEventDndStatus( void* data, int type, void* event )
743 DALI_LOG_INFO(gDragAndDropLogFilter, Debug::Concise, "EcoreEventDndStatus\n" );
744 return ECORE_CALLBACK_PASS_ON;
748 * Called when the client messages (i.e. the accessibility events) are received.
750 static Eina_Bool EcoreEventClientMessage( void* data, int type, void* event )
752 Ecore_X_Event_Client_Message* clientMessageEvent( (Ecore_X_Event_Client_Message*)event );
753 EventHandler* handler( (EventHandler*)data );
755 if (clientMessageEvent->message_type == ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL)
757 if ( ( (unsigned int)clientMessageEvent->data.l[0] == handler->mImpl->mWindow ) && handler->mAccessibilityManager )
759 AccessibilityManager* accessibilityManager( &AccessibilityManager::GetImplementation( handler->mAccessibilityManager ) );
761 if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_SCROLL)
763 // 2 finger touch & move, 2 finger flick
765 // mouse state : e->data.l[2] (0: mouse down, 1: mouse move, 2: mouse up)
768 TouchPoint::State state(TouchPoint::Down);
770 if ((unsigned int)clientMessageEvent->data.l[2] == 0)
772 state = TouchPoint::Down; // mouse down
774 else if ((unsigned int)clientMessageEvent->data.l[2] == 1)
776 state = TouchPoint::Motion; // mouse move
778 else if ((unsigned int)clientMessageEvent->data.l[2] == 2)
780 state = TouchPoint::Up; // mouse up
784 state = TouchPoint::Interrupted; // error
787 DALI_LOG_INFO(gClientMessageLogFilter, Debug::General,
788 "[%s:%d] [%d] %d, %d\n", __FUNCTION__, __LINE__,
789 (unsigned int)clientMessageEvent->data.l[2],
790 (unsigned int)clientMessageEvent->data.l[3], (unsigned int)clientMessageEvent->data.l[4]);
792 // Send touch event to accessibility manager.
793 TouchPoint point( 0, state, (float)clientMessageEvent->data.l[3], (float)clientMessageEvent->data.l[4] );
795 // In accessibility mode, scroll action should be handled when the currently focused actor is contained in scrollable control
796 accessibilityManager->HandleActionScrollEvent( point, GetCurrentMilliSeconds() );
798 else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_MOUSE)
800 // 1 finger double tap and hold
802 // mouse state : e->data.l[2] (0: mouse down, 1: mouse move, 2: mouse up)
805 TouchPoint::State state(TouchPoint::Down);
807 if ((unsigned int)clientMessageEvent->data.l[2] == 0)
809 state = TouchPoint::Down; // mouse down
811 else if ((unsigned int)clientMessageEvent->data.l[2] == 1)
813 state = TouchPoint::Motion; // mouse move
815 else if ((unsigned int)clientMessageEvent->data.l[2] == 2)
817 state = TouchPoint::Up; // mouse up
821 state = TouchPoint::Interrupted; // error
824 DALI_LOG_INFO(gClientMessageLogFilter, Debug::General,
825 "[%s:%d] [%d] %d, %d\n", __FUNCTION__, __LINE__,
826 (unsigned int)clientMessageEvent->data.l[2],
827 (unsigned int)clientMessageEvent->data.l[3], (unsigned int)clientMessageEvent->data.l[4]);
829 // Send touch event to core.
830 TouchPoint point( 0, state, (float)clientMessageEvent->data.l[3], (float)clientMessageEvent->data.l[4] );
831 handler->SendEvent( point, 0 );
833 else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_BACK)
835 // 2 finger circle draw, do back
836 accessibilityManager->HandleActionBackEvent();
838 else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_NEXT)
840 // one finger flick down
842 if(accessibilityManager)
844 accessibilityManager->HandleActionNextEvent();
847 else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_PREV)
849 // one finger flick up
850 // focus previous object
851 if(accessibilityManager)
853 accessibilityManager->HandleActionPreviousEvent();
856 else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_ACTIVATE)
858 // one finger double tap
859 // same as one finger tap in normal mode (i.e. execute focused actor)
860 if(accessibilityManager)
862 accessibilityManager->HandleActionActivateEvent();
865 else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ)
868 // focus & read an actor at ( e->data.l[2], e->data.l[3] ) position according to finger
869 if(accessibilityManager)
871 accessibilityManager->HandleActionReadEvent((unsigned int)clientMessageEvent->data.l[2], (unsigned int)clientMessageEvent->data.l[3], true);
874 #if defined(DALI_PROFILE_MOBILE) || defined(DALI_PROFILE_TV)
875 else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_OVER)
878 // focus & read an actor at ( e->data.l[2], e->data.l[3] ) position according to finger
879 if(accessibilityManager)
881 accessibilityManager->HandleActionReadEvent((unsigned int)clientMessageEvent->data.l[2], (unsigned int)clientMessageEvent->data.l[3], false );
885 else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_NEXT)
887 // one finger flick right
889 if(accessibilityManager)
891 accessibilityManager->HandleActionReadNextEvent();
894 else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_PREV)
896 // one finger flick left
897 // focus previous object
898 if(accessibilityManager)
900 accessibilityManager->HandleActionReadPreviousEvent();
903 else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_UP)
905 // double down and move (right, up)
906 // change slider value
907 if(accessibilityManager)
909 accessibilityManager->HandleActionUpEvent();
912 else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_DOWN)
914 // double down and move (left, down)
915 // change slider value
916 if(accessibilityManager)
918 accessibilityManager->HandleActionDownEvent();
921 else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_ENABLE)
923 if(accessibilityManager)
925 accessibilityManager->HandleActionEnableEvent();
928 else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_DISABLE)
930 if(accessibilityManager)
932 accessibilityManager->HandleActionDisableEvent();
935 // TODO: some more actions could be added later
938 else if(clientMessageEvent->message_type == ecore_x_atom_get(CLIPBOARD_ATOM))
940 std::string message(clientMessageEvent->data.b);
941 if( message == CLIPBOARD_SET_OWNER_MESSAGE)
943 // Claim the ownership of the SECONDARY selection.
944 ecore_x_selection_secondary_set(handler->mImpl->mWindow, "", 1);
946 // Show the clipboard window
947 Dali::Clipboard clipboard = Dali::Clipboard::Get();
948 clipboard.ShowClipboard();
951 else if( clientMessageEvent->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE )
953 RotationEvent rotationEvent;
954 rotationEvent.angle = static_cast<int>(clientMessageEvent->data.l[1]);
955 rotationEvent.winResize = static_cast<int>(clientMessageEvent->data.l[2]);
956 rotationEvent.width = static_cast<int>(clientMessageEvent->data.l[3]);
957 rotationEvent.height = static_cast<int>(clientMessageEvent->data.l[4]);
958 handler->SendRotationPrepareEvent( rotationEvent );
960 else if( clientMessageEvent->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST )
962 handler->SendRotationRequestEvent();
965 return ECORE_CALLBACK_PASS_ON;
969 * Called when the source window notifies us the content in clipboard is selected.
971 static Eina_Bool EcoreEventSelectionClear( void* data, int type, void* event )
973 DALI_LOG_INFO(gSelectionEventLogFilter, Debug::Concise, "EcoreEventSelectionClear\n" );
974 Ecore_X_Event_Selection_Clear* selectionClearEvent( (Ecore_X_Event_Selection_Clear*) event );
975 EventHandler* handler( (EventHandler*)data );
977 if ( selectionClearEvent->win == handler->mImpl->mWindow )
979 if ( selectionClearEvent->selection == ECORE_X_SELECTION_SECONDARY )
981 // Request to get the content from Ecore.
982 ecore_x_selection_secondary_request(selectionClearEvent->win, ECORE_X_SELECTION_TARGET_TEXT);
985 return ECORE_CALLBACK_PASS_ON;
989 * Called when the source window sends us about the selected content.
990 * For example, when dragged items are dragged INTO our window or when items are selected in the clipboard.
992 static Eina_Bool EcoreEventSelectionNotify( void* data, int type, void* event )
994 DALI_LOG_INFO(gSelectionEventLogFilter, Debug::Concise, "EcoreEventSelectionNotify\n" );
996 Ecore_X_Event_Selection_Notify* selectionNotifyEvent( (Ecore_X_Event_Selection_Notify*) event );
997 EventHandler* handler( (EventHandler*)data );
999 if ( selectionNotifyEvent->win == handler->mImpl->mWindow )
1001 Ecore_X_Selection_Data* selectionData( (Ecore_X_Selection_Data*) selectionNotifyEvent->data );
1002 if ( selectionData->data )
1004 if ( selectionNotifyEvent->selection == ECORE_X_SELECTION_XDND )
1006 DragAndDropDetectorPtr dndDetector( handler->mDragAndDropDetector );
1008 // We have got the content that is to be dropped, inform the DndListener (if we have one).
1011 std::string content( (char*) selectionData->data, selectionData->length );
1012 dndDetector->SetContent( content );
1014 DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "EcoreEventSelectionNotify: Content(%d):\n" , selectionData->length );
1015 DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "======================================\n" );
1016 DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "%s\n", selectionData->data );
1017 DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "======================================\n" );
1020 else if ( selectionNotifyEvent->selection == ECORE_X_SELECTION_SECONDARY )
1022 // We have got the selected content, inform the clipboard event listener (if we have one).
1023 if ( handler->mClipboardEventNotifier )
1025 ClipboardEventNotifier& clipboardEventNotifier( ClipboardEventNotifier::GetImplementation( handler->mClipboardEventNotifier ) );
1026 std::string content( (char*) selectionData->data, selectionData->length );
1027 clipboardEventNotifier.SetContent( content );
1028 clipboardEventNotifier.EmitContentSelectedSignal();
1031 // Claim the ownership of the SECONDARY selection.
1032 ecore_x_selection_secondary_set(handler->mImpl->mWindow, "", 1);
1034 DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "EcoreEventSelectionNotify: Content(%d):\n" , selectionData->length );
1035 DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "======================================\n" );
1036 DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "%s\n", selectionData->data );
1037 DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "======================================\n" );
1041 return ECORE_CALLBACK_PASS_ON;
1044 /////////////////////////////////////////////////////////////////////////////////////////////////
1046 /////////////////////////////////////////////////////////////////////////////////////////////////
1048 * Called when a font name is changed.
1050 static void VconfNotifyFontNameChanged( keynode_t* node, void* data )
1052 EventHandler* handler = static_cast<EventHandler*>( data );
1054 StyleChange fontChange;
1055 fontChange.defaultFontChange = true;
1057 handler->SendEvent( fontChange );
1061 * Called when a font size is changed.
1063 static void VconfNotifyFontSizeChanged( keynode_t* node, void* data )
1065 EventHandler* handler = static_cast<EventHandler*>( data );
1067 StyleChange fontChange;
1068 fontChange.defaultFontSizeChange = true;
1070 handler->SendEvent( fontChange );
1074 EventHandler* mHandler;
1075 std::vector<Ecore_Event_Handler*> mEcoreEventHandler;
1076 Ecore_X_Window mWindow;
1079 EventHandler::EventHandler( RenderSurface* surface, CoreEventInterface& coreEventInterface, GestureManager& gestureManager, DamageObserver& damageObserver, DragAndDropDetectorPtr dndDetector )
1080 : mCoreEventInterface(coreEventInterface),
1081 mGestureManager( gestureManager ),
1082 mStyleMonitor( StyleMonitor::Get() ),
1083 mDamageObserver( damageObserver ),
1084 mRotationObserver( NULL ),
1085 mDragAndDropDetector( dndDetector ),
1086 mAccessibilityManager( AccessibilityManager::Get() ),
1087 mClipboardEventNotifier( ClipboardEventNotifier::Get() ),
1088 mClipboard(Clipboard::Get()),
1089 mImfManager( ImfManager::Get() ),
1092 Ecore_X_Window window = 0;
1094 if( surface->GetType() == Dali::RenderSurface::WINDOW )
1096 // this code only works with the EcoreX11 RenderSurface so need to downcast
1097 ECoreX::WindowRenderSurface* ecoreSurface = dynamic_cast< ECoreX::WindowRenderSurface* >( surface );
1100 // enable multi touch
1101 window = ecoreSurface->GetXWindow();
1102 ecore_x_input_multi_select( window );
1106 mImpl = new Impl(this, window);
1108 mGestureManager.Start();
1111 EventHandler::~EventHandler()
1118 mGestureManager.Stop();
1121 void EventHandler::SendEvent(TouchPoint& point, unsigned long timeStamp)
1125 timeStamp = GetCurrentMilliSeconds();
1128 Integration::TouchEvent event;
1129 if (mCombiner.GetNextTouchEvent(point, timeStamp, event))
1131 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);
1133 // First the touch event & related gesture events are queued
1134 mCoreEventInterface.QueueCoreEvent( event );
1135 mGestureManager.SendEvent(event);
1137 // Next the events are processed with a single call into Core
1138 mCoreEventInterface.ProcessCoreEvents();
1142 void EventHandler::SendEvent(KeyEvent& keyEvent)
1144 Dali::PhysicalKeyboard physicalKeyboard = PhysicalKeyboard::Get();
1145 if ( physicalKeyboard )
1147 if ( ! KeyLookup::IsDeviceButton( keyEvent.keyPressedName.c_str() ) )
1149 GetImplementation( physicalKeyboard ).KeyReceived( keyEvent.time > 1 );
1153 // Create KeyEvent and send to Core.
1154 Integration::KeyEvent event(keyEvent.keyPressedName, keyEvent.keyPressed, keyEvent.keyCode,
1155 keyEvent.keyModifier, keyEvent.time, static_cast<Integration::KeyEvent::State>(keyEvent.state));
1156 mCoreEventInterface.QueueCoreEvent( event );
1157 mCoreEventInterface.ProcessCoreEvents();
1160 void EventHandler::SendMouseWheelEvent( MouseWheelEvent& wheelEvent )
1162 // Create MouseWheelEvent and send to Core.
1163 Integration::MouseWheelEvent event(wheelEvent.direction, wheelEvent.modifiers, wheelEvent.point, wheelEvent.z, wheelEvent.timeStamp);
1164 mCoreEventInterface.QueueCoreEvent( event );
1165 mCoreEventInterface.ProcessCoreEvents();
1168 void EventHandler::SendEvent(StyleChange styleChange)
1170 DALI_ASSERT_DEBUG( mStyleMonitor && "StyleMonitor Not Available" );
1171 GetImplementation( mStyleMonitor ).StyleChanged(styleChange);
1174 void EventHandler::SendEvent( const DamageArea& area )
1176 mDamageObserver.OnDamaged( area );
1179 void EventHandler::SendRotationPrepareEvent( const RotationEvent& event )
1181 if( mRotationObserver != NULL )
1183 mRotationObserver->OnRotationPrepare( event );
1187 void EventHandler::SendRotationRequestEvent( )
1189 if( mRotationObserver != NULL )
1191 mRotationObserver->OnRotationRequest( );
1195 void EventHandler::FeedTouchPoint( TouchPoint& point, int timeStamp)
1197 SendEvent(point, timeStamp);
1200 void EventHandler::FeedWheelEvent( MouseWheelEvent& wheelEvent )
1202 SendMouseWheelEvent( wheelEvent );
1205 void EventHandler::FeedKeyEvent( KeyEvent& event )
1210 void EventHandler::FeedEvent( Integration::Event& event )
1212 mCoreEventInterface.QueueCoreEvent( event );
1213 mCoreEventInterface.ProcessCoreEvents();
1216 void EventHandler::Reset()
1220 // Any touch listeners should be told of the interruption.
1221 Integration::TouchEvent event;
1222 TouchPoint point(0, TouchPoint::Interrupted, 0, 0);
1223 event.AddPoint( point );
1225 // First the touch event & related gesture events are queued
1226 mCoreEventInterface.QueueCoreEvent( event );
1227 mGestureManager.SendEvent( event );
1229 // Next the events are processed with a single call into Core
1230 mCoreEventInterface.ProcessCoreEvents();
1233 void EventHandler::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
1235 mDragAndDropDetector = detector;
1238 void EventHandler::SetRotationObserver( RotationObserver* observer )
1240 mRotationObserver = observer;
1243 } // namespace Adaptor
1245 } // namespace Internal