Merge branch 'devel/master' into tizen
[platform/core/uifw/dali-adaptor.git] / dali / internal / window-system / common / event-handler.cpp
1 /*
2  * Copyright (c) 2019 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 <dali/internal/window-system/common/event-handler.h>
20
21 // EXTERNAL INCLUDES
22 #include <cstring>
23 #include <sys/time.h>
24
25 #include <dali/public-api/events/touch-point.h>
26 #include <dali/public-api/events/key-event.h>
27 #include <dali/public-api/events/wheel-event.h>
28 #include <dali/integration-api/debug.h>
29 #include <dali/integration-api/events/key-event-integ.h>
30 #include <dali/integration-api/events/touch-event-integ.h>
31 #include <dali/integration-api/events/hover-event-integ.h>
32 #include <dali/integration-api/events/wheel-event-integ.h>
33 #include <dali/integration-api/scene.h>
34
35 // INTERNAL INCLUDES
36 #include <dali/internal/input/common/gesture-manager.h>
37 #include <dali/internal/clipboard/common/clipboard-impl.h>
38 #include <dali/internal/input/common/key-impl.h>
39 #include <dali/internal/input/common/physical-keyboard-impl.h>
40 #include <dali/internal/styling/common/style-monitor-impl.h>
41 #include <dali/internal/window-system/common/window-render-surface.h>
42
43 namespace Dali
44 {
45
46 namespace Internal
47 {
48
49 namespace Adaptor
50 {
51
52 #if defined(DEBUG_ENABLED)
53 namespace
54 {
55 Integration::Log::Filter* gTouchEventLogFilter  = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_TOUCH");
56 Integration::Log::Filter* gSelectionEventLogFilter = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_SELECTION");
57 } // unnamed namespace
58 #endif
59
60 namespace
61 {
62
63 // Copied from x server
64 static uint32_t GetCurrentMilliSeconds(void)
65 {
66   struct timeval tv;
67
68   struct timespec tp;
69   static clockid_t clockid;
70
71   if (!clockid)
72   {
73 #ifdef CLOCK_MONOTONIC_COARSE
74     if (clock_getres(CLOCK_MONOTONIC_COARSE, &tp) == 0 &&
75       (tp.tv_nsec / 1000) <= 1000 && clock_gettime(CLOCK_MONOTONIC_COARSE, &tp) == 0)
76     {
77       clockid = CLOCK_MONOTONIC_COARSE;
78     }
79     else
80 #endif
81     if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
82     {
83       clockid = CLOCK_MONOTONIC;
84     }
85     else
86     {
87       clockid = ~0L;
88     }
89   }
90   if (clockid != ~0L && clock_gettime(clockid, &tp) == 0)
91   {
92     return static_cast<uint32_t>( (tp.tv_sec * 1000 ) + (tp.tv_nsec / 1000000L) );
93   }
94
95   gettimeofday(&tv, NULL);
96   return static_cast<uint32_t>( (tv.tv_sec * 1000 ) + (tv.tv_usec / 1000) );
97 }
98
99 } // unnamed namespace
100
101 EventHandler::EventHandler( Dali::Integration::Scene scene, CoreEventInterface& coreEventInterface, GestureManager& gestureManager, DamageObserver& damageObserver )
102 : mScene( scene ),
103   mCoreEventInterface( coreEventInterface ),
104   mGestureManager( gestureManager ),
105   mStyleMonitor( StyleMonitor::Get() ),
106   mDamageObserver( damageObserver ),
107   mRotationObserver( NULL ),
108   mAccessibilityAdaptor( AccessibilityAdaptor::Get() ),
109   mClipboardEventNotifier( ClipboardEventNotifier::Get() ),
110   mClipboard( Clipboard::Get() ),
111   mRotationAngle( 0 ),
112   mWindowWidth( 0 ),
113   mWindowHeight( 0 ),
114   mPaused( false )
115 {
116   // this code only works with the WindowRenderSurface so need to downcast
117   WindowRenderSurface* windowRenderSurface = static_cast< WindowRenderSurface* >( scene.GetSurface() );
118   if( windowRenderSurface )
119   {
120     WindowBase* windowBase = windowRenderSurface->GetWindowBase();
121
122     // Connect signals
123     windowBase->WindowDamagedSignal().Connect( this, &EventHandler::OnWindowDamaged );
124     windowBase->FocusChangedSignal().Connect( this, &EventHandler::OnFocusChanged );
125     windowBase->RotationSignal().Connect( this, &EventHandler::SendRotationPrepareEvent );
126     windowBase->TouchEventSignal().Connect( this, &EventHandler::OnTouchEvent );
127     windowBase->WheelEventSignal().Connect( this, &EventHandler::OnWheelEvent );
128     windowBase->KeyEventSignal().Connect( this, &EventHandler::OnKeyEvent );
129     windowBase->SelectionDataSendSignal().Connect( this, &EventHandler::OnSelectionDataSend );
130     windowBase->SelectionDataReceivedSignal().Connect( this, &EventHandler::OnSelectionDataReceived );
131     windowBase->StyleChangedSignal().Connect( this, &EventHandler::OnStyleChanged );
132     windowBase->AccessibilitySignal().Connect( this, &EventHandler::OnAccessibilityNotification );
133   }
134 }
135
136 EventHandler::~EventHandler()
137 {
138   mGestureManager.Stop();
139 }
140
141 void EventHandler::SendEvent( Integration::Point& point, uint32_t timeStamp )
142 {
143   if( timeStamp < 1 )
144   {
145     timeStamp = GetCurrentMilliSeconds();
146   }
147
148   ConvertTouchPosition( point );
149
150   Integration::TouchEvent touchEvent;
151   Integration::HoverEvent hoverEvent;
152   Integration::TouchEventCombiner::EventDispatchType type = mCombiner.GetNextTouchEvent(point, timeStamp, touchEvent, hoverEvent);
153   if( type != Integration::TouchEventCombiner::DispatchNone )
154   {
155     DALI_LOG_INFO( gTouchEventLogFilter, Debug::General, "%d: Device %d: Button state %d (%.2f, %.2f)\n", timeStamp, point.GetDeviceId(), point.GetState(), point.GetScreenPosition().x, point.GetScreenPosition().y );
156     // First the touch and/or hover event & related gesture events are queued
157     if( type == Integration::TouchEventCombiner::DispatchTouch || type == Integration::TouchEventCombiner::DispatchBoth )
158     {
159       mScene.QueueEvent( touchEvent );
160       mGestureManager.SendEvent( mScene, touchEvent );
161     }
162
163     if( type == Integration::TouchEventCombiner::DispatchHover || type == Integration::TouchEventCombiner::DispatchBoth )
164     {
165       mScene.QueueEvent( hoverEvent );
166     }
167
168     // Next the events are processed with a single call into Core
169     mCoreEventInterface.ProcessCoreEvents();
170   }
171 }
172
173 void EventHandler::SendEvent(Integration::KeyEvent& keyEvent)
174 {
175   Dali::PhysicalKeyboard physicalKeyboard = PhysicalKeyboard::Get();
176   if( physicalKeyboard )
177   {
178     if( ! KeyLookup::IsDeviceButton( keyEvent.keyName.c_str() ) )
179     {
180       GetImplementation( physicalKeyboard ).KeyReceived( keyEvent.time > 1 );
181     }
182   }
183
184   // Create send KeyEvent to Core.
185   mScene.QueueEvent( keyEvent );
186   mCoreEventInterface.ProcessCoreEvents();
187 }
188
189 void EventHandler::SendWheelEvent( WheelEvent& wheelEvent )
190 {
191   // Create WheelEvent and send to Core.
192   Integration::WheelEvent event( static_cast< Integration::WheelEvent::Type >(wheelEvent.type), wheelEvent.direction, wheelEvent.modifiers, wheelEvent.point, wheelEvent.z, wheelEvent.timeStamp );
193
194   mScene.QueueEvent( event );
195   mCoreEventInterface.ProcessCoreEvents();
196 }
197
198 void EventHandler::SendEvent( StyleChange::Type styleChange )
199 {
200   DALI_ASSERT_DEBUG( mStyleMonitor && "StyleMonitor Not Available" );
201   GetImplementation( mStyleMonitor ).StyleChanged(styleChange);
202 }
203
204 void EventHandler::SendEvent( const DamageArea& area )
205 {
206   mDamageObserver.OnDamaged( area );
207 }
208
209 void EventHandler::SendRotationPrepareEvent( const RotationEvent& event )
210 {
211   if( mRotationObserver != NULL )
212   {
213     mRotationAngle = event.angle;
214     mWindowWidth = event.width;
215     mWindowHeight = event.height;
216
217     mRotationObserver->OnRotationPrepare( event );
218     mRotationObserver->OnRotationRequest();
219   }
220 }
221
222 void EventHandler::SendRotationRequestEvent( )
223 {
224   // No need to separate event into prepare and request
225 }
226
227 void EventHandler::FeedTouchPoint( TouchPoint& point, uint32_t timeStamp)
228 {
229   Integration::Point convertedPoint( point );
230   SendEvent( convertedPoint, timeStamp );
231 }
232
233 void EventHandler::FeedWheelEvent( WheelEvent& wheelEvent )
234 {
235   SendWheelEvent( wheelEvent );
236 }
237
238 void EventHandler::FeedKeyEvent( KeyEvent& event )
239 {
240   Integration::KeyEvent convertedEvent( event );
241   SendEvent( convertedEvent );
242 }
243
244 void EventHandler::FeedEvent( Integration::Event& event )
245 {
246   mScene.QueueEvent( event );
247   mCoreEventInterface.ProcessCoreEvents();
248 }
249
250 void EventHandler::Reset()
251 {
252   mCombiner.Reset();
253
254   // Any touch listeners should be told of the interruption.
255   Integration::TouchEvent event;
256   Integration::Point point;
257   point.SetState( PointState::INTERRUPTED );
258   event.AddPoint( point );
259
260   // First the touch event & related gesture events are queued
261   mScene.QueueEvent( event );
262
263   mGestureManager.SendEvent( mScene, event );
264
265   // Next the events are processed with a single call into Core
266   mCoreEventInterface.ProcessCoreEvents();
267 }
268
269 void EventHandler::Pause()
270 {
271   mPaused = true;
272   Reset();
273 }
274
275 void EventHandler::Resume()
276 {
277   mPaused = false;
278   Reset();
279 }
280
281 void EventHandler::SetRotationObserver( RotationObserver* observer )
282 {
283   mRotationObserver = observer;
284 }
285
286 void EventHandler::OnTouchEvent( Integration::Point& point, uint32_t timeStamp )
287 {
288   SendEvent( point, timeStamp );
289 }
290
291 void EventHandler::OnWheelEvent( WheelEvent& wheelEvent )
292 {
293   SendWheelEvent( wheelEvent );
294 }
295
296 void EventHandler::OnKeyEvent( Integration::KeyEvent& keyEvent )
297 {
298   SendEvent( keyEvent );
299 }
300
301 void EventHandler::OnFocusChanged( bool focusIn )
302 {
303   // If the window gains focus and we hid the keyboard then show it again.
304   if( focusIn )
305   {
306     Dali::Clipboard clipboard = Clipboard::Get();
307     if ( clipboard )
308     {
309       clipboard.HideClipboard();
310     }
311   }
312   else
313   {
314     // Hiding clipboard event will be ignored once because window focus out event is always received on showing clipboard
315     Dali::Clipboard clipboard = Clipboard::Get();
316     if ( clipboard )
317     {
318       Clipboard& clipBoardImpl( GetImplementation( clipboard ) );
319       clipBoardImpl.HideClipboard(true);
320     }
321   }
322 }
323
324 void EventHandler::OnWindowDamaged( const DamageArea& area )
325 {
326   SendEvent( area );
327 }
328
329 void EventHandler::OnSelectionDataSend( void* event )
330 {
331   Dali::Clipboard clipboard = Clipboard::Get();
332   if( clipboard )
333   {
334     Clipboard& clipBoardImpl( GetImplementation( clipboard ) );
335     clipBoardImpl.ExcuteBuffered( true, event );
336   }
337 }
338
339 void EventHandler::OnSelectionDataReceived( void* event )
340 {
341   // We have got the selected content, inform the clipboard event listener (if we have one).
342   Dali::Clipboard clipboard = Clipboard::Get();
343   char* selectionData = NULL;
344   if( clipboard )
345   {
346     Clipboard& clipBoardImpl( GetImplementation( clipboard ) );
347     selectionData = clipBoardImpl.ExcuteBuffered( false, event );
348   }
349
350   if( selectionData && mClipboardEventNotifier )
351   {
352     ClipboardEventNotifier& clipboardEventNotifier( ClipboardEventNotifier::GetImplementation( mClipboardEventNotifier ) );
353     std::string content( selectionData, strlen( selectionData ) );
354
355     clipboardEventNotifier.SetContent( content );
356     clipboardEventNotifier.EmitContentSelectedSignal();
357
358     DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "EcoreEventSelectionNotify: Content(%d): %s\n" , strlen(selectionData), selectionData );
359   }
360 }
361
362 void EventHandler::OnStyleChanged( StyleChange::Type styleChange )
363 {
364   SendEvent( styleChange );
365 }
366
367 void EventHandler::OnAccessibilityNotification( const WindowBase::AccessibilityInfo& info )
368 {
369 #ifdef DALI_ELDBUS_AVAILABLE
370   if( mPaused )
371   {
372     return;
373   }
374
375   if( !mAccessibilityAdaptor )
376   {
377     DALI_LOG_ERROR( "Invalid accessibility adaptor\n" );
378     return;
379   }
380
381   AccessibilityAdaptor* accessibilityAdaptor( &AccessibilityAdaptor::GetImplementation( mAccessibilityAdaptor ) );
382   if( !accessibilityAdaptor )
383   {
384     DALI_LOG_ERROR( "Cannot access accessibility adaptor\n" );
385     return;
386   }
387
388   // Create a touch point object.
389   TouchPoint::State touchPointState( TouchPoint::Down );
390   if( info.state == 0 )
391   {
392     touchPointState = TouchPoint::Down; // Mouse down.
393   }
394   else if( info.state == 1 )
395   {
396     touchPointState = TouchPoint::Motion; // Mouse move.
397   }
398   else if( info.state == 2 )
399   {
400     touchPointState = TouchPoint::Up; // Mouse up.
401   }
402   else
403   {
404     touchPointState = TouchPoint::Interrupted; // Error.
405   }
406
407   // Send touch event to accessibility adaptor.
408   TouchPoint point( 0, touchPointState, static_cast< float >( info.startX ), static_cast< float >( info.startY ) );
409
410   // Perform actions based on received gestures.
411   // Note: This is seperated from the reading so we can have other input readers without changing the below code.
412   switch( info.gestureValue )
413   {
414     case 0: // OneFingerHover
415     {
416       // Focus, read out.
417       accessibilityAdaptor->HandleActionReadEvent( static_cast< unsigned int >( info.startX ), static_cast< unsigned int >( info.startY ), true /* allow read again */ );
418       break;
419     }
420     case 1: // TwoFingersHover
421     {
422       // In accessibility mode, scroll action should be handled when the currently focused actor is contained in scrollable control
423       accessibilityAdaptor->HandleActionScrollEvent( point, GetCurrentMilliSeconds() );
424       break;
425     }
426     case 2: // ThreeFingersHover
427     {
428       // Read from top item on screen continuously.
429       accessibilityAdaptor->HandleActionReadFromTopEvent();
430       break;
431     }
432     case 3: // OneFingerFlickLeft
433     {
434       // Move to previous item.
435       accessibilityAdaptor->HandleActionReadPreviousEvent();
436       break;
437     }
438     case 4: // OneFingerFlickRight
439     {
440       // Move to next item.
441       accessibilityAdaptor->HandleActionReadNextEvent();
442       break;
443     }
444     case 5: // OneFingerFlickUp
445     {
446       // Move to previous item.
447       accessibilityAdaptor->HandleActionPreviousEvent();
448       break;
449     }
450     case 6: // OneFingerFlickDown
451     {
452       // Move to next item.
453       accessibilityAdaptor->HandleActionNextEvent();
454       break;
455     }
456     case 7: // TwoFingersFlickUp
457     {
458       // Scroll up the list.
459       accessibilityAdaptor->HandleActionScrollUpEvent();
460       break;
461     }
462     case 8: // TwoFingersFlickDown
463     {
464       // Scroll down the list.
465       accessibilityAdaptor->HandleActionScrollDownEvent();
466       break;
467     }
468     case 9: // TwoFingersFlickLeft
469     {
470       // Scroll left to the previous page
471       accessibilityAdaptor->HandleActionPageLeftEvent();
472       break;
473     }
474     case 10: // TwoFingersFlickRight
475     {
476       // Scroll right to the next page
477       accessibilityAdaptor->HandleActionPageRightEvent();
478       break;
479     }
480     case 11: // ThreeFingersFlickLeft
481     {
482       // Not exist yet
483       break;
484     }
485     case 12: // ThreeFingersFlickRight
486     {
487       // Not exist yet
488       break;
489     }
490     case 13: // ThreeFingersFlickUp
491     {
492       // Not exist yet
493       break;
494     }
495     case 14: // ThreeFingersFlickDown
496     {
497       // Not exist yet
498       break;
499     }
500     case 15: // OneFingerSingleTap
501     {
502       // Focus, read out.
503       accessibilityAdaptor->HandleActionReadEvent( static_cast< unsigned int >( info.startX ), static_cast< unsigned int >( info.startY ), true /* allow read again */ );
504       break;
505     }
506     case 16: // OneFingerDoubleTap
507     {
508       // Activate selected item / active edit mode.
509       accessibilityAdaptor->HandleActionActivateEvent();
510       break;
511     }
512     case 17: // OneFingerTripleTap
513     {
514       // Zoom
515       accessibilityAdaptor->HandleActionZoomEvent();
516       break;
517     }
518     case 18: // TwoFingersSingleTap
519     {
520       // Pause/Resume current speech
521       accessibilityAdaptor->HandleActionReadPauseResumeEvent();
522       break;
523     }
524     case 19: // TwoFingersDoubleTap
525     {
526       // Start/Stop current action
527       accessibilityAdaptor->HandleActionStartStopEvent();
528       break;
529     }
530     case 20: // TwoFingersTripleTap
531     {
532       // Read information from indicator
533       // Not supported
534       break;
535     }
536     case 21: // ThreeFingersSingleTap
537     {
538       // Read from top item on screen continuously.
539       accessibilityAdaptor->HandleActionReadFromTopEvent();
540       break;
541     }
542     case 22: // ThreeFingersDoubleTap
543     {
544       // Read from next item continuously.
545       accessibilityAdaptor->HandleActionReadFromNextEvent();
546       break;
547     }
548     case 23: // ThreeFingersTripleTap
549     {
550       // Not exist yet
551       break;
552     }
553     case 24: // OneFingerFlickLeftReturn
554     {
555       // Scroll up to the previous page
556       accessibilityAdaptor->HandleActionPageUpEvent();
557       break;
558     }
559     case 25: // OneFingerFlickRightReturn
560     {
561       // Scroll down to the next page
562       accessibilityAdaptor->HandleActionPageDownEvent();
563       break;
564     }
565     case 26: // OneFingerFlickUpReturn
566     {
567       // Move to the first item on screen
568       accessibilityAdaptor->HandleActionMoveToFirstEvent();
569       break;
570     }
571     case 27: // OneFingerFlickDownReturn
572     {
573       // Move to the last item on screen
574       accessibilityAdaptor->HandleActionMoveToLastEvent();
575       break;
576     }
577     case 28: // TwoFingersFlickLeftReturn
578     {
579       // Not exist yet
580       break;
581     }
582     case 29: // TwoFingersFlickRightReturn
583     {
584       // Not exist yet
585       break;
586     }
587     case 30: // TwoFingersFlickUpReturn
588     {
589       // Not exist yet
590       break;
591     }
592     case 31: // TwoFingersFlickDownReturn
593     {
594       // Not exist yet
595       break;
596     }
597     case 32: // ThreeFingersFlickLeftReturn
598     {
599       // Not exist yet
600       break;
601     }
602     case 33: // ThreeFingersFlickRightReturn
603     {
604       // Not exist yet
605       break;
606     }
607     case 34: // ThreeFingersFlickUpReturn
608     {
609       // Not exist yet
610       break;
611     }
612     case 35: // ThreeFingersFlickDownReturn
613     {
614       // Not exist yet
615       break;
616     }
617   }
618 #endif
619 }
620
621 void EventHandler::ConvertTouchPosition( Integration::Point& point )
622 {
623   Vector2 position = point.GetScreenPosition();
624   Vector2 convertedPosition;
625
626   switch( mRotationAngle )
627   {
628     case 90:
629     {
630       convertedPosition.x = static_cast<float>( mWindowWidth ) - position.y;
631       convertedPosition.y = position.x;
632       break;
633     }
634     case 180:
635     {
636       convertedPosition.x = static_cast<float>( mWindowWidth ) - position.x;
637       convertedPosition.y = static_cast<float>( mWindowHeight ) - position.y;
638       break;
639     }
640     case 270:
641     {
642       convertedPosition.x = position.y;
643       convertedPosition.y = static_cast<float>( mWindowHeight ) - position.x;
644       break;
645     }
646     default:
647     {
648       convertedPosition = position;
649       break;
650     }
651   }
652
653   point.SetScreenPosition( convertedPosition );
654 }
655
656 } // namespace Adaptor
657
658 } // namespace Internal
659
660 } // namespace Dali