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