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