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 /* allow read again*/);
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)
877 // one finger tap & move
878 // mouse state : e->data.l[2] (0: mouse down, 1: mouse move, 2: mouse up)
881 // focus & read an actor at (x, y) position according to finger
882 if(accessibilityManager)
884 accessibilityManager->HandleActionReadEvent((unsigned int)clientMessageEvent->data.l[3], (unsigned int)clientMessageEvent->data.l[4], false /* not allow read again*/);
888 else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_NEXT)
890 // one finger flick right
892 if(accessibilityManager)
894 accessibilityManager->HandleActionReadNextEvent();
897 else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_PREV)
899 // one finger flick left
900 // focus previous object
901 if(accessibilityManager)
903 accessibilityManager->HandleActionReadPreviousEvent();
906 else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_UP)
908 // double down and move (right, up)
909 // change slider value
910 if(accessibilityManager)
912 accessibilityManager->HandleActionUpEvent();
915 else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_DOWN)
917 // double down and move (left, down)
918 // change slider value
919 if(accessibilityManager)
921 accessibilityManager->HandleActionDownEvent();
924 else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_ENABLE)
926 if(accessibilityManager)
928 accessibilityManager->HandleActionEnableEvent();
931 else if((unsigned int)clientMessageEvent->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_DISABLE)
933 if(accessibilityManager)
935 accessibilityManager->HandleActionDisableEvent();
938 // TODO: some more actions could be added later
941 else if(clientMessageEvent->message_type == ecore_x_atom_get(CLIPBOARD_ATOM))
943 std::string message(clientMessageEvent->data.b);
944 if( message == CLIPBOARD_SET_OWNER_MESSAGE)
946 // Claim the ownership of the SECONDARY selection.
947 ecore_x_selection_secondary_set(handler->mImpl->mWindow, "", 1);
949 // Show the clipboard window
950 Dali::Clipboard clipboard = Dali::Clipboard::Get();
951 clipboard.ShowClipboard();
954 else if( clientMessageEvent->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE )
956 RotationEvent rotationEvent;
957 rotationEvent.angle = static_cast<int>(clientMessageEvent->data.l[1]);
958 rotationEvent.winResize = static_cast<int>(clientMessageEvent->data.l[2]);
959 rotationEvent.width = static_cast<int>(clientMessageEvent->data.l[3]);
960 rotationEvent.height = static_cast<int>(clientMessageEvent->data.l[4]);
961 handler->SendRotationPrepareEvent( rotationEvent );
963 else if( clientMessageEvent->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST )
965 handler->SendRotationRequestEvent();
968 return ECORE_CALLBACK_PASS_ON;
972 * Called when the source window notifies us the content in clipboard is selected.
974 static Eina_Bool EcoreEventSelectionClear( void* data, int type, void* event )
976 DALI_LOG_INFO(gSelectionEventLogFilter, Debug::Concise, "EcoreEventSelectionClear\n" );
977 Ecore_X_Event_Selection_Clear* selectionClearEvent( (Ecore_X_Event_Selection_Clear*) event );
978 EventHandler* handler( (EventHandler*)data );
980 if ( selectionClearEvent->win == handler->mImpl->mWindow )
982 if ( selectionClearEvent->selection == ECORE_X_SELECTION_SECONDARY )
984 // Request to get the content from Ecore.
985 ecore_x_selection_secondary_request(selectionClearEvent->win, ECORE_X_SELECTION_TARGET_TEXT);
988 return ECORE_CALLBACK_PASS_ON;
992 * Called when the source window sends us about the selected content.
993 * For example, when dragged items are dragged INTO our window or when items are selected in the clipboard.
995 static Eina_Bool EcoreEventSelectionNotify( void* data, int type, void* event )
997 DALI_LOG_INFO(gSelectionEventLogFilter, Debug::Concise, "EcoreEventSelectionNotify\n" );
999 Ecore_X_Event_Selection_Notify* selectionNotifyEvent( (Ecore_X_Event_Selection_Notify*) event );
1000 EventHandler* handler( (EventHandler*)data );
1002 if ( selectionNotifyEvent->win == handler->mImpl->mWindow )
1004 Ecore_X_Selection_Data* selectionData( (Ecore_X_Selection_Data*) selectionNotifyEvent->data );
1005 if ( selectionData->data )
1007 if ( selectionNotifyEvent->selection == ECORE_X_SELECTION_XDND )
1009 DragAndDropDetectorPtr dndDetector( handler->mDragAndDropDetector );
1011 // We have got the content that is to be dropped, inform the DndListener (if we have one).
1014 std::string content( (char*) selectionData->data, selectionData->length );
1015 dndDetector->SetContent( content );
1017 DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "EcoreEventSelectionNotify: Content(%d):\n" , selectionData->length );
1018 DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "======================================\n" );
1019 DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "%s\n", selectionData->data );
1020 DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "======================================\n" );
1023 else if ( selectionNotifyEvent->selection == ECORE_X_SELECTION_SECONDARY )
1025 // We have got the selected content, inform the clipboard event listener (if we have one).
1026 if ( handler->mClipboardEventNotifier )
1028 ClipboardEventNotifier& clipboardEventNotifier( ClipboardEventNotifier::GetImplementation( handler->mClipboardEventNotifier ) );
1029 std::string content( (char*) selectionData->data, selectionData->length );
1030 clipboardEventNotifier.SetContent( content );
1031 clipboardEventNotifier.EmitContentSelectedSignal();
1034 // Claim the ownership of the SECONDARY selection.
1035 ecore_x_selection_secondary_set(handler->mImpl->mWindow, "", 1);
1037 DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "EcoreEventSelectionNotify: Content(%d):\n" , selectionData->length );
1038 DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "======================================\n" );
1039 DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "%s\n", selectionData->data );
1040 DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "======================================\n" );
1044 return ECORE_CALLBACK_PASS_ON;
1047 /////////////////////////////////////////////////////////////////////////////////////////////////
1049 /////////////////////////////////////////////////////////////////////////////////////////////////
1051 * Called when a font name is changed.
1053 static void VconfNotifyFontNameChanged( keynode_t* node, void* data )
1055 EventHandler* handler = static_cast<EventHandler*>( data );
1057 StyleChange fontChange;
1058 fontChange.defaultFontChange = true;
1060 handler->SendEvent( fontChange );
1064 * Called when a font size is changed.
1066 static void VconfNotifyFontSizeChanged( keynode_t* node, void* data )
1068 EventHandler* handler = static_cast<EventHandler*>( data );
1070 StyleChange fontChange;
1071 fontChange.defaultFontSizeChange = true;
1073 handler->SendEvent( fontChange );
1077 EventHandler* mHandler;
1078 std::vector<Ecore_Event_Handler*> mEcoreEventHandler;
1079 Ecore_X_Window mWindow;
1082 EventHandler::EventHandler( RenderSurface* surface, CoreEventInterface& coreEventInterface, GestureManager& gestureManager, DamageObserver& damageObserver, DragAndDropDetectorPtr dndDetector )
1083 : mCoreEventInterface(coreEventInterface),
1084 mGestureManager( gestureManager ),
1085 mStyleMonitor( StyleMonitor::Get() ),
1086 mDamageObserver( damageObserver ),
1087 mRotationObserver( NULL ),
1088 mDragAndDropDetector( dndDetector ),
1089 mAccessibilityManager( AccessibilityManager::Get() ),
1090 mClipboardEventNotifier( ClipboardEventNotifier::Get() ),
1091 mClipboard(Clipboard::Get()),
1092 mImfManager( ImfManager::Get() ),
1095 Ecore_X_Window window = 0;
1097 if( surface->GetType() == Dali::RenderSurface::WINDOW )
1099 // this code only works with the EcoreX11 RenderSurface so need to downcast
1100 ECoreX::WindowRenderSurface* ecoreSurface = dynamic_cast< ECoreX::WindowRenderSurface* >( surface );
1103 // enable multi touch
1104 window = ecoreSurface->GetXWindow();
1105 ecore_x_input_multi_select( window );
1109 mImpl = new Impl(this, window);
1111 mGestureManager.Start();
1114 EventHandler::~EventHandler()
1121 mGestureManager.Stop();
1124 void EventHandler::SendEvent(TouchPoint& point, unsigned long timeStamp)
1128 timeStamp = GetCurrentMilliSeconds();
1131 Integration::TouchEvent event;
1132 if (mCombiner.GetNextTouchEvent(point, timeStamp, event))
1134 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);
1136 // First the touch event & related gesture events are queued
1137 mCoreEventInterface.QueueCoreEvent( event );
1138 mGestureManager.SendEvent(event);
1140 // Next the events are processed with a single call into Core
1141 mCoreEventInterface.ProcessCoreEvents();
1145 void EventHandler::SendEvent(KeyEvent& keyEvent)
1147 Dali::PhysicalKeyboard physicalKeyboard = PhysicalKeyboard::Get();
1148 if ( physicalKeyboard )
1150 if ( ! KeyLookup::IsDeviceButton( keyEvent.keyPressedName.c_str() ) )
1152 GetImplementation( physicalKeyboard ).KeyReceived( keyEvent.time > 1 );
1156 // Create KeyEvent and send to Core.
1157 Integration::KeyEvent event(keyEvent.keyPressedName, keyEvent.keyPressed, keyEvent.keyCode,
1158 keyEvent.keyModifier, keyEvent.time, static_cast<Integration::KeyEvent::State>(keyEvent.state));
1159 mCoreEventInterface.QueueCoreEvent( event );
1160 mCoreEventInterface.ProcessCoreEvents();
1163 void EventHandler::SendMouseWheelEvent( MouseWheelEvent& wheelEvent )
1165 // Create MouseWheelEvent and send to Core.
1166 Integration::MouseWheelEvent event(wheelEvent.direction, wheelEvent.modifiers, wheelEvent.point, wheelEvent.z, wheelEvent.timeStamp);
1167 mCoreEventInterface.QueueCoreEvent( event );
1168 mCoreEventInterface.ProcessCoreEvents();
1171 void EventHandler::SendEvent(StyleChange styleChange)
1173 DALI_ASSERT_DEBUG( mStyleMonitor && "StyleMonitor Not Available" );
1174 GetImplementation( mStyleMonitor ).StyleChanged(styleChange);
1177 void EventHandler::SendEvent( const DamageArea& area )
1179 mDamageObserver.OnDamaged( area );
1182 void EventHandler::SendRotationPrepareEvent( const RotationEvent& event )
1184 if( mRotationObserver != NULL )
1186 mRotationObserver->OnRotationPrepare( event );
1190 void EventHandler::SendRotationRequestEvent( )
1192 if( mRotationObserver != NULL )
1194 mRotationObserver->OnRotationRequest( );
1198 void EventHandler::FeedTouchPoint( TouchPoint& point, int timeStamp)
1200 SendEvent(point, timeStamp);
1203 void EventHandler::FeedWheelEvent( MouseWheelEvent& wheelEvent )
1205 SendMouseWheelEvent( wheelEvent );
1208 void EventHandler::FeedKeyEvent( KeyEvent& event )
1213 void EventHandler::FeedEvent( Integration::Event& event )
1215 mCoreEventInterface.QueueCoreEvent( event );
1216 mCoreEventInterface.ProcessCoreEvents();
1219 void EventHandler::Reset()
1223 // Any touch listeners should be told of the interruption.
1224 Integration::TouchEvent event;
1225 TouchPoint point(0, TouchPoint::Interrupted, 0, 0);
1226 event.AddPoint( point );
1228 // First the touch event & related gesture events are queued
1229 mCoreEventInterface.QueueCoreEvent( event );
1230 mGestureManager.SendEvent( event );
1232 // Next the events are processed with a single call into Core
1233 mCoreEventInterface.ProcessCoreEvents();
1236 void EventHandler::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
1238 mDragAndDropDetector = detector;
1241 void EventHandler::SetRotationObserver( RotationObserver* observer )
1243 mRotationObserver = observer;
1246 } // namespace Adaptor
1248 } // namespace Internal