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