[Tizen] Add QuickPanel changed signal in WindowBase
[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( ( info.quickpanelInfo & ( 1 << QUICKPANEL_TYPE_SYSTEM_DEFAULT ) ) && ( info.quickpanelInfo & ( 1 << QUICKPANEL_TYPE_APPS_MENU ) ) )
275   {
276     DALI_LOG_ERROR("Quickpanel is top now, so all dali apps should be stopped \n");
277     return;
278   }
279
280   // Create a touch point object.
281   PointState::Type touchPointState( PointState::DOWN );
282   if( info.state == 0 )
283   {
284     touchPointState = PointState::DOWN; // Mouse down.
285   }
286   else if( info.state == 1 )
287   {
288     touchPointState = PointState::MOTION; // Mouse move.
289   }
290   else if( info.state == 2 )
291   {
292     touchPointState = PointState::UP; // Mouse up.
293   }
294   else
295   {
296     touchPointState = PointState::INTERRUPTED; // Error.
297   }
298
299   // Send touch event to accessibility adaptor.
300   TouchPoint point( 0, touchPointState, static_cast< float >( info.startX ), static_cast< float >( info.startY ) );
301
302   // Perform actions based on received gestures.
303   // Note: This is seperated from the reading so we can have other input readers without changing the below code.
304   switch( info.gestureValue )
305   {
306     case 0: // OneFingerHover
307     {
308       // Focus, read out.
309       accessibilityAdaptor->HandleActionReadEvent( static_cast< unsigned int >( info.startX ), static_cast< unsigned int >( info.startY ), true /* allow read again */ );
310       break;
311     }
312     case 1: // TwoFingersHover
313     {
314       // In accessibility mode, scroll action should be handled when the currently focused actor is contained in scrollable control
315       accessibilityAdaptor->HandleActionScrollEvent( point, GetCurrentMilliSeconds() );
316       break;
317     }
318     case 2: // ThreeFingersHover
319     {
320       // Read from top item on screen continuously.
321       accessibilityAdaptor->HandleActionReadFromTopEvent();
322       break;
323     }
324     case 3: // OneFingerFlickLeft
325     {
326       // Move to previous item.
327       accessibilityAdaptor->HandleActionReadPreviousEvent();
328       break;
329     }
330     case 4: // OneFingerFlickRight
331     {
332       // Move to next item.
333       accessibilityAdaptor->HandleActionReadNextEvent();
334       break;
335     }
336     case 5: // OneFingerFlickUp
337     {
338       // Move to previous item.
339       accessibilityAdaptor->HandleActionPreviousEvent();
340       break;
341     }
342     case 6: // OneFingerFlickDown
343     {
344       // Move to next item.
345       accessibilityAdaptor->HandleActionNextEvent();
346       break;
347     }
348     case 7: // TwoFingersFlickUp
349     {
350       // Scroll up the list.
351       accessibilityAdaptor->HandleActionScrollUpEvent();
352       break;
353     }
354     case 8: // TwoFingersFlickDown
355     {
356       // Scroll down the list.
357       accessibilityAdaptor->HandleActionScrollDownEvent();
358       break;
359     }
360     case 9: // TwoFingersFlickLeft
361     {
362       // Scroll left to the previous page
363       accessibilityAdaptor->HandleActionPageLeftEvent();
364       break;
365     }
366     case 10: // TwoFingersFlickRight
367     {
368       // Scroll right to the next page
369       accessibilityAdaptor->HandleActionPageRightEvent();
370       break;
371     }
372     case 11: // ThreeFingersFlickLeft
373     {
374       // Not exist yet
375       break;
376     }
377     case 12: // ThreeFingersFlickRight
378     {
379       // Not exist yet
380       break;
381     }
382     case 13: // ThreeFingersFlickUp
383     {
384       // Not exist yet
385       break;
386     }
387     case 14: // ThreeFingersFlickDown
388     {
389       // Not exist yet
390       break;
391     }
392     case 15: // OneFingerSingleTap
393     {
394       // Focus, read out.
395       accessibilityAdaptor->HandleActionReadEvent( static_cast< unsigned int >( info.startX ), static_cast< unsigned int >( info.startY ), true /* allow read again */ );
396       break;
397     }
398     case 16: // OneFingerDoubleTap
399     {
400       // Activate selected item / active edit mode.
401       accessibilityAdaptor->HandleActionActivateEvent();
402       break;
403     }
404     case 17: // OneFingerTripleTap
405     {
406       // Zoom
407       accessibilityAdaptor->HandleActionZoomEvent();
408       break;
409     }
410     case 18: // TwoFingersSingleTap
411     {
412       // Pause/Resume current speech
413       accessibilityAdaptor->HandleActionReadPauseResumeEvent();
414       break;
415     }
416     case 19: // TwoFingersDoubleTap
417     {
418       // Start/Stop current action
419       accessibilityAdaptor->HandleActionStartStopEvent();
420       break;
421     }
422     case 20: // TwoFingersTripleTap
423     {
424       // Read information from indicator
425       // Not supported
426       break;
427     }
428     case 21: // ThreeFingersSingleTap
429     {
430       // Read from top item on screen continuously.
431       accessibilityAdaptor->HandleActionReadFromTopEvent();
432       break;
433     }
434     case 22: // ThreeFingersDoubleTap
435     {
436       // Read from next item continuously.
437       accessibilityAdaptor->HandleActionReadFromNextEvent();
438       break;
439     }
440     case 23: // ThreeFingersTripleTap
441     {
442       // Not exist yet
443       break;
444     }
445     case 24: // OneFingerFlickLeftReturn
446     {
447       // Scroll up to the previous page
448       accessibilityAdaptor->HandleActionPageUpEvent();
449       break;
450     }
451     case 25: // OneFingerFlickRightReturn
452     {
453       // Scroll down to the next page
454       accessibilityAdaptor->HandleActionPageDownEvent();
455       break;
456     }
457     case 26: // OneFingerFlickUpReturn
458     {
459       // Move to the first item on screen
460       accessibilityAdaptor->HandleActionMoveToFirstEvent();
461       break;
462     }
463     case 27: // OneFingerFlickDownReturn
464     {
465       // Move to the last item on screen
466       accessibilityAdaptor->HandleActionMoveToLastEvent();
467       break;
468     }
469     case 28: // TwoFingersFlickLeftReturn
470     {
471       // Not exist yet
472       break;
473     }
474     case 29: // TwoFingersFlickRightReturn
475     {
476       // Not exist yet
477       break;
478     }
479     case 30: // TwoFingersFlickUpReturn
480     {
481       // Not exist yet
482       break;
483     }
484     case 31: // TwoFingersFlickDownReturn
485     {
486       // Not exist yet
487       break;
488     }
489     case 32: // ThreeFingersFlickLeftReturn
490     {
491       // Not exist yet
492       break;
493     }
494     case 33: // ThreeFingersFlickRightReturn
495     {
496       // Not exist yet
497       break;
498     }
499     case 34: // ThreeFingersFlickUpReturn
500     {
501       // Not exist yet
502       break;
503     }
504     case 35: // ThreeFingersFlickDownReturn
505     {
506       // Not exist yet
507       break;
508     }
509   }
510 #endif
511 }
512
513 void EventHandler::OnAccessibilityQuickpanelChanged( const unsigned char& info )
514 {
515 #ifdef DALI_ELDBUS_AVAILABLE
516   if( mPaused )
517   {
518     return;
519   }
520
521   if( !mAccessibilityAdaptor )
522   {
523     DALI_LOG_ERROR( "Invalid accessibility adaptor\n" );
524     return;
525   }
526
527   AccessibilityAdaptor* accessibilityAdaptor( &AccessibilityAdaptor::GetImplementation( mAccessibilityAdaptor ) );
528   if( !accessibilityAdaptor )
529   {
530     DALI_LOG_ERROR( "Cannot access accessibility adaptor\n" );
531     return;
532   }
533
534   // Both QuickPanel and Apps are shown
535   if( ( info & ( 1 << QUICKPANEL_TYPE_SYSTEM_DEFAULT ) ) && ( info & ( 1 << QUICKPANEL_TYPE_APPS_MENU ) ) )
536   {
537     // dali apps should be disabled.
538     accessibilityAdaptor->DisableAccessibility();
539   }
540   // Only Apps menu (dali application) is shown
541   else if( info & ( 1 << QUICKPANEL_TYPE_APPS_MENU ) )
542   {
543     // dali app should be enabled.
544     accessibilityAdaptor->EnableAccessibility();
545   }
546   // QuickPanel is shown
547   else if( info & ( 1 << QUICKPANEL_TYPE_SYSTEM_DEFAULT ) )
548   {
549     // dali app should be disabled.
550     accessibilityAdaptor->DisableAccessibility();
551   }
552   else
553   {
554     // dali app should be enabled.
555     accessibilityAdaptor->EnableAccessibility();
556   }
557
558
559 #endif
560 }
561
562 void EventHandler::AddObserver( Observer& observer )
563 {
564   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
565
566   if ( match == mObservers.end() )
567   {
568     mObservers.push_back( &observer );
569   }
570 }
571
572 void EventHandler::RemoveObserver( Observer& observer )
573 {
574   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
575
576   if ( match != mObservers.end() )
577   {
578     mObservers.erase( match );
579   }
580 }
581
582 } // namespace Adaptor
583
584 } // namespace Internal
585
586 } // namespace Dali