8bdec19194965500d8226a1519dab947d1c44822
[platform/core/uifw/dali-adaptor.git] / dali / internal / window-system / common / event-handler.cpp
1 /*
2  * Copyright (c) 2020 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/devel-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/clipboard/common/clipboard-impl.h>
36 #include <dali/internal/styling/common/style-monitor-impl.h>
37 #include <dali/internal/window-system/common/window-render-surface.h>
38
39 namespace Dali
40 {
41
42 namespace Internal
43 {
44
45 namespace Adaptor
46 {
47
48 #if defined(DEBUG_ENABLED)
49 namespace
50 {
51 Integration::Log::Filter* gSelectionEventLogFilter = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_SELECTION");
52 } // unnamed namespace
53 #endif
54
55 #ifdef DALI_ELDBUS_AVAILABLE
56 namespace
57 {
58
59 static constexpr auto QUICKPANEL_TYPE_SYSTEM_DEFAULT = 1;
60 static constexpr auto QUICKPANEL_TYPE_APPS_MENU = 3;
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 #endif
100
101 EventHandler::EventHandler( WindowBase* windowBase, DamageObserver& damageObserver )
102 : mStyleMonitor( StyleMonitor::Get() ),
103   mDamageObserver( damageObserver ),
104   mAccessibilityAdaptor( AccessibilityAdaptor::Get() ),
105   mClipboardEventNotifier( ClipboardEventNotifier::Get() ),
106   mClipboard( Clipboard::Get() ),
107   mPaused( false )
108 {
109   // Connect signals
110   if( windowBase )
111   {
112     windowBase->WindowDamagedSignal().Connect( this, &EventHandler::OnWindowDamaged );
113     windowBase->FocusChangedSignal().Connect( this, &EventHandler::OnFocusChanged );
114     windowBase->RotationSignal().Connect( this, &EventHandler::OnRotation );
115     windowBase->TouchEventSignal().Connect( this, &EventHandler::OnTouchEvent );
116     windowBase->WheelEventSignal().Connect( this, &EventHandler::OnWheelEvent );
117     windowBase->KeyEventSignal().Connect( this, &EventHandler::OnKeyEvent );
118     windowBase->SelectionDataSendSignal().Connect( this, &EventHandler::OnSelectionDataSend );
119     windowBase->SelectionDataReceivedSignal().Connect( this, &EventHandler::OnSelectionDataReceived );
120     windowBase->StyleChangedSignal().Connect( this, &EventHandler::OnStyleChanged );
121     windowBase->AccessibilitySignal().Connect( this, &EventHandler::OnAccessibilityNotification );
122     windowBase->QuickPanelSignal().Connect( this, &EventHandler::OnAccessibilityQuickpanelChanged );
123   }
124   else
125   {
126     DALI_LOG_ERROR("WindowBase is invalid!!!\n");
127   }
128 }
129
130 EventHandler::~EventHandler()
131 {
132 }
133
134 void EventHandler::SendEvent( StyleChange::Type styleChange )
135 {
136   DALI_ASSERT_DEBUG( mStyleMonitor && "StyleMonitor Not Available" );
137   GetImplementation( mStyleMonitor ).StyleChanged(styleChange);
138 }
139
140 void EventHandler::SendEvent( const DamageArea& area )
141 {
142   mDamageObserver.OnDamaged( area );
143 }
144
145 void EventHandler::Pause()
146 {
147   mPaused = true;
148 }
149
150 void EventHandler::Resume()
151 {
152   mPaused = false;
153 }
154
155 void EventHandler::OnTouchEvent( Integration::Point& point, uint32_t timeStamp )
156 {
157   for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
158   {
159     (*iter)->OnTouchPoint( point, timeStamp );
160   }
161 }
162
163 void EventHandler::OnWheelEvent( Integration::WheelEvent& wheelEvent )
164 {
165   for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
166   {
167     (*iter)->OnWheelEvent( wheelEvent );
168   }
169 }
170
171 void EventHandler::OnKeyEvent( Integration::KeyEvent& keyEvent )
172 {
173   for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
174   {
175     (*iter)->OnKeyEvent( keyEvent );
176   }
177 }
178
179 void EventHandler::OnFocusChanged( bool focusIn )
180 {
181   // If the window gains focus and we hid the keyboard then show it again.
182   if( focusIn )
183   {
184     Dali::Clipboard clipboard = Clipboard::Get();
185     if ( clipboard )
186     {
187       clipboard.HideClipboard();
188     }
189   }
190   else
191   {
192     // Hiding clipboard event will be ignored once because window focus out event is always received on showing clipboard
193     Dali::Clipboard clipboard = Clipboard::Get();
194     if ( clipboard )
195     {
196       Clipboard& clipBoardImpl( GetImplementation( clipboard ) );
197       clipBoardImpl.HideClipboard(true);
198     }
199   }
200 }
201
202 void EventHandler::OnRotation( const RotationEvent& event )
203 {
204   for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
205   {
206     (*iter)->OnRotation( event );
207   }
208 }
209
210 void EventHandler::OnWindowDamaged( const DamageArea& area )
211 {
212   SendEvent( area );
213 }
214
215 void EventHandler::OnSelectionDataSend( void* event )
216 {
217   Dali::Clipboard clipboard = Clipboard::Get();
218   if( clipboard )
219   {
220     Clipboard& clipBoardImpl( GetImplementation( clipboard ) );
221     clipBoardImpl.ExcuteBuffered( true, event );
222   }
223 }
224
225 void EventHandler::OnSelectionDataReceived( void* event )
226 {
227   // We have got the selected content, inform the clipboard event listener (if we have one).
228   Dali::Clipboard clipboard = Clipboard::Get();
229   char* selectionData = NULL;
230   if( clipboard )
231   {
232     Clipboard& clipBoardImpl( GetImplementation( clipboard ) );
233     selectionData = clipBoardImpl.ExcuteBuffered( false, event );
234   }
235
236   if( selectionData && mClipboardEventNotifier )
237   {
238     ClipboardEventNotifier& clipboardEventNotifier( ClipboardEventNotifier::GetImplementation( mClipboardEventNotifier ) );
239     std::string content( selectionData, strlen( selectionData ) );
240
241     clipboardEventNotifier.SetContent( content );
242     clipboardEventNotifier.EmitContentSelectedSignal();
243
244     DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "EcoreEventSelectionNotify: Content(%d): %s\n" , strlen(selectionData), selectionData );
245   }
246 }
247
248 void EventHandler::OnStyleChanged( StyleChange::Type styleChange )
249 {
250   SendEvent( styleChange );
251 }
252
253 void EventHandler::OnAccessibilityNotification( const WindowBase::AccessibilityInfo& info )
254 {
255 #ifdef DALI_ELDBUS_AVAILABLE
256   if( mPaused )
257   {
258     return;
259   }
260
261   if( !mAccessibilityAdaptor )
262   {
263     DALI_LOG_ERROR( "Invalid accessibility adaptor\n" );
264     return;
265   }
266
267   AccessibilityAdaptor* accessibilityAdaptor( &AccessibilityAdaptor::GetImplementation( mAccessibilityAdaptor ) );
268   if( !accessibilityAdaptor )
269   {
270     DALI_LOG_ERROR( "Cannot access accessibility adaptor\n" );
271     return;
272   }
273
274   if( !accessibilityAdaptor->IsEnabled() )
275   {
276     DALI_LOG_ERROR( "The current dali accessibility is not available. \n" );
277     return;
278   }
279
280   if( ( info.quickpanelInfo & ( 1 << QUICKPANEL_TYPE_SYSTEM_DEFAULT ) ) && ( info.quickpanelInfo & ( 1 << QUICKPANEL_TYPE_APPS_MENU ) ) )
281   {
282     DALI_LOG_ERROR("Quickpanel is top now, so all dali apps should be stopped \n");
283     return;
284   }
285
286   // Create a touch point object.
287   PointState::Type touchPointState( PointState::DOWN );
288   if( info.state == 0 )
289   {
290     touchPointState = PointState::DOWN; // Mouse down.
291   }
292   else if( info.state == 1 )
293   {
294     touchPointState = PointState::MOTION; // Mouse move.
295   }
296   else if( info.state == 2 )
297   {
298     touchPointState = PointState::UP; // Mouse up.
299   }
300   else
301   {
302     touchPointState = PointState::INTERRUPTED; // Error.
303   }
304
305   // Send touch event to accessibility adaptor.
306   TouchPoint point( 0, touchPointState, static_cast< float >( info.startX ), static_cast< float >( info.startY ) );
307
308   // Perform actions based on received gestures.
309   // Note: This is seperated from the reading so we can have other input readers without changing the below code.
310   switch( info.gestureValue )
311   {
312     case 0: // OneFingerHover
313     {
314       // Focus, read out.
315       accessibilityAdaptor->HandleActionReadEvent( static_cast< unsigned int >( info.startX ), static_cast< unsigned int >( info.startY ), true /* allow read again */ );
316       break;
317     }
318     case 1: // TwoFingersHover
319     {
320       // In accessibility mode, scroll action should be handled when the currently focused actor is contained in scrollable control
321       accessibilityAdaptor->HandleActionScrollEvent( point, GetCurrentMilliSeconds() );
322       break;
323     }
324     case 2: // ThreeFingersHover
325     {
326       // Read from top item on screen continuously.
327       accessibilityAdaptor->HandleActionReadFromTopEvent();
328       break;
329     }
330     case 3: // OneFingerFlickLeft
331     {
332       // Move to previous item.
333       accessibilityAdaptor->HandleActionReadPreviousEvent();
334       break;
335     }
336     case 4: // OneFingerFlickRight
337     {
338       // Move to next item.
339       accessibilityAdaptor->HandleActionReadNextEvent();
340       break;
341     }
342     case 5: // OneFingerFlickUp
343     {
344       // Move to previous item.
345       accessibilityAdaptor->HandleActionPreviousEvent();
346       break;
347     }
348     case 6: // OneFingerFlickDown
349     {
350       // Move to next item.
351       accessibilityAdaptor->HandleActionNextEvent();
352       break;
353     }
354     case 7: // TwoFingersFlickUp
355     {
356       // Scroll up the list.
357       accessibilityAdaptor->HandleActionScrollUpEvent();
358       break;
359     }
360     case 8: // TwoFingersFlickDown
361     {
362       // Scroll down the list.
363       accessibilityAdaptor->HandleActionScrollDownEvent();
364       break;
365     }
366     case 9: // TwoFingersFlickLeft
367     {
368       // Scroll left to the previous page
369       accessibilityAdaptor->HandleActionPageLeftEvent();
370       break;
371     }
372     case 10: // TwoFingersFlickRight
373     {
374       // Scroll right to the next page
375       accessibilityAdaptor->HandleActionPageRightEvent();
376       break;
377     }
378     case 11: // ThreeFingersFlickLeft
379     {
380       // Not exist yet
381       break;
382     }
383     case 12: // ThreeFingersFlickRight
384     {
385       // Not exist yet
386       break;
387     }
388     case 13: // ThreeFingersFlickUp
389     {
390       // Not exist yet
391       break;
392     }
393     case 14: // ThreeFingersFlickDown
394     {
395       // Not exist yet
396       break;
397     }
398     case 15: // OneFingerSingleTap
399     {
400       // Focus, read out.
401       accessibilityAdaptor->HandleActionReadEvent( static_cast< unsigned int >( info.startX ), static_cast< unsigned int >( info.startY ), true /* allow read again */ );
402       break;
403     }
404     case 16: // OneFingerDoubleTap
405     {
406       // Activate selected item / active edit mode.
407       accessibilityAdaptor->HandleActionActivateEvent();
408       break;
409     }
410     case 17: // OneFingerTripleTap
411     {
412       // Zoom
413       accessibilityAdaptor->HandleActionZoomEvent();
414       break;
415     }
416     case 18: // TwoFingersSingleTap
417     {
418       // Pause/Resume current speech
419       accessibilityAdaptor->HandleActionReadPauseResumeEvent();
420       break;
421     }
422     case 19: // TwoFingersDoubleTap
423     {
424       // Start/Stop current action
425       accessibilityAdaptor->HandleActionStartStopEvent();
426       break;
427     }
428     case 20: // TwoFingersTripleTap
429     {
430       // Read information from indicator
431       // Not supported
432       break;
433     }
434     case 21: // ThreeFingersSingleTap
435     {
436       // Read from top item on screen continuously.
437       accessibilityAdaptor->HandleActionReadFromTopEvent();
438       break;
439     }
440     case 22: // ThreeFingersDoubleTap
441     {
442       // Read from next item continuously.
443       accessibilityAdaptor->HandleActionReadFromNextEvent();
444       break;
445     }
446     case 23: // ThreeFingersTripleTap
447     {
448       // Not exist yet
449       break;
450     }
451     case 24: // OneFingerFlickLeftReturn
452     {
453       // Scroll up to the previous page
454       accessibilityAdaptor->HandleActionPageUpEvent();
455       break;
456     }
457     case 25: // OneFingerFlickRightReturn
458     {
459       // Scroll down to the next page
460       accessibilityAdaptor->HandleActionPageDownEvent();
461       break;
462     }
463     case 26: // OneFingerFlickUpReturn
464     {
465       // Move to the first item on screen
466       accessibilityAdaptor->HandleActionMoveToFirstEvent();
467       break;
468     }
469     case 27: // OneFingerFlickDownReturn
470     {
471       // Move to the last item on screen
472       accessibilityAdaptor->HandleActionMoveToLastEvent();
473       break;
474     }
475     case 28: // TwoFingersFlickLeftReturn
476     {
477       // Not exist yet
478       break;
479     }
480     case 29: // TwoFingersFlickRightReturn
481     {
482       // Not exist yet
483       break;
484     }
485     case 30: // TwoFingersFlickUpReturn
486     {
487       // Not exist yet
488       break;
489     }
490     case 31: // TwoFingersFlickDownReturn
491     {
492       // Not exist yet
493       break;
494     }
495     case 32: // ThreeFingersFlickLeftReturn
496     {
497       // Not exist yet
498       break;
499     }
500     case 33: // ThreeFingersFlickRightReturn
501     {
502       // Not exist yet
503       break;
504     }
505     case 34: // ThreeFingersFlickUpReturn
506     {
507       // Not exist yet
508       break;
509     }
510     case 35: // ThreeFingersFlickDownReturn
511     {
512       // Not exist yet
513       break;
514     }
515   }
516 #endif
517 }
518
519 void EventHandler::OnAccessibilityQuickpanelChanged( const unsigned char& info )
520 {
521 #ifdef DALI_ELDBUS_AVAILABLE
522   if( mPaused )
523   {
524     return;
525   }
526
527   if( !mAccessibilityAdaptor )
528   {
529     DALI_LOG_ERROR( "Invalid accessibility adaptor\n" );
530     return;
531   }
532
533   AccessibilityAdaptor* accessibilityAdaptor( &AccessibilityAdaptor::GetImplementation( mAccessibilityAdaptor ) );
534   if( !accessibilityAdaptor )
535   {
536     DALI_LOG_ERROR( "Cannot access accessibility adaptor\n" );
537     return;
538   }
539
540   if( ( ( info & ( 1 << QUICKPANEL_TYPE_SYSTEM_DEFAULT ) ) && ( info & ( 1 << QUICKPANEL_TYPE_APPS_MENU ) ) ) || // Both QuickPanel and Apps are shown
541       ( info & ( 1 << QUICKPANEL_TYPE_SYSTEM_DEFAULT ) ) ) // QuickPanel is shown
542   {
543     // dali apps should be disabled.
544     DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "OnAccessibilityQuickpanelChanged: Quickpanel show -> DisableAccessibility \n" );
545     accessibilityAdaptor->DisableAccessibility();
546   }
547   else if( info & ( 1 << QUICKPANEL_TYPE_APPS_MENU ) ) // Only Apps menu (dali application) is shown
548   {
549     if( !accessibilityAdaptor->IsForcedEnable() ) // It is not in case of that an application controls the accessibility status itself
550     {
551       DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "OnAccessibilityQuickpanelChanged: Only Apps show, but not forced dali -> DisableAccessibility \n" );
552       accessibilityAdaptor->DisableAccessibility();
553     }
554     else
555     {
556       DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "OnAccessibilityQuickpanelChanged: Only Apps show and it is a forced dali -> EnableAccessibility \n" );
557       accessibilityAdaptor->EnableAccessibility();
558     }
559   }
560   else
561   {
562     DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "OnAccessibilityQuickpanelChanged: Nothing shows -> EnableAccessibility \n" );
563     // dali app should be enabled.
564     accessibilityAdaptor->EnableAccessibility();
565   }
566
567 #endif
568 }
569
570 void EventHandler::AddObserver( Observer& observer )
571 {
572   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
573
574   if ( match == mObservers.end() )
575   {
576     mObservers.push_back( &observer );
577   }
578 }
579
580 void EventHandler::RemoveObserver( Observer& observer )
581 {
582   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
583
584   if ( match != mObservers.end() )
585   {
586     mObservers.erase( match );
587   }
588 }
589
590 } // namespace Adaptor
591
592 } // namespace Internal
593
594 } // namespace Dali