448684d35cd6883139cf81f17dee47412d6bc4d9
[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
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 // Copied from x server
60 static uint32_t GetCurrentMilliSeconds(void)
61 {
62   struct timeval tv;
63
64   struct timespec tp;
65   static clockid_t clockid;
66
67   if (!clockid)
68   {
69 #ifdef CLOCK_MONOTONIC_COARSE
70     if (clock_getres(CLOCK_MONOTONIC_COARSE, &tp) == 0 &&
71       (tp.tv_nsec / 1000) <= 1000 && clock_gettime(CLOCK_MONOTONIC_COARSE, &tp) == 0)
72     {
73       clockid = CLOCK_MONOTONIC_COARSE;
74     }
75     else
76 #endif
77     if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
78     {
79       clockid = CLOCK_MONOTONIC;
80     }
81     else
82     {
83       clockid = ~0L;
84     }
85   }
86   if (clockid != ~0L && clock_gettime(clockid, &tp) == 0)
87   {
88     return static_cast<uint32_t>( (tp.tv_sec * 1000 ) + (tp.tv_nsec / 1000000L) );
89   }
90
91   gettimeofday(&tv, NULL);
92   return static_cast<uint32_t>( (tv.tv_sec * 1000 ) + (tv.tv_usec / 1000) );
93 }
94
95 } // unnamed namespace
96 #endif
97
98 EventHandler::EventHandler( WindowBase* windowBase, DamageObserver& damageObserver )
99 : mStyleMonitor( StyleMonitor::Get() ),
100   mDamageObserver( damageObserver ),
101   mAccessibilityAdaptor( AccessibilityAdaptor::Get() ),
102   mClipboardEventNotifier( ClipboardEventNotifier::Get() ),
103   mClipboard( Clipboard::Get() ),
104   mPaused( false )
105 {
106   // Connect signals
107   windowBase->WindowDamagedSignal().Connect( this, &EventHandler::OnWindowDamaged );
108   windowBase->FocusChangedSignal().Connect( this, &EventHandler::OnFocusChanged );
109   windowBase->RotationSignal().Connect( this, &EventHandler::OnRotation );
110   windowBase->TouchEventSignal().Connect( this, &EventHandler::OnTouchEvent );
111   windowBase->WheelEventSignal().Connect( this, &EventHandler::OnWheelEvent );
112   windowBase->KeyEventSignal().Connect( this, &EventHandler::OnKeyEvent );
113   windowBase->SelectionDataSendSignal().Connect( this, &EventHandler::OnSelectionDataSend );
114   windowBase->SelectionDataReceivedSignal().Connect( this, &EventHandler::OnSelectionDataReceived );
115   windowBase->StyleChangedSignal().Connect( this, &EventHandler::OnStyleChanged );
116   windowBase->AccessibilitySignal().Connect( this, &EventHandler::OnAccessibilityNotification );
117 }
118
119 EventHandler::~EventHandler()
120 {
121 }
122
123 void EventHandler::SendEvent( StyleChange::Type styleChange )
124 {
125   DALI_ASSERT_DEBUG( mStyleMonitor && "StyleMonitor Not Available" );
126   GetImplementation( mStyleMonitor ).StyleChanged(styleChange);
127 }
128
129 void EventHandler::SendEvent( const DamageArea& area )
130 {
131   mDamageObserver.OnDamaged( area );
132 }
133
134 void EventHandler::Pause()
135 {
136   mPaused = true;
137 }
138
139 void EventHandler::Resume()
140 {
141   mPaused = false;
142 }
143
144 void EventHandler::OnTouchEvent( Integration::Point& point, uint32_t timeStamp )
145 {
146   for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
147   {
148     (*iter)->OnTouchPoint( point, timeStamp );
149   }
150 }
151
152 void EventHandler::OnWheelEvent( WheelEvent& wheelEvent )
153 {
154   Integration::WheelEvent event( static_cast< Integration::WheelEvent::Type >(wheelEvent.type), wheelEvent.direction, wheelEvent.modifiers, wheelEvent.point, wheelEvent.z, wheelEvent.timeStamp );
155
156   for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
157   {
158     (*iter)->OnWheelEvent( event );
159   }
160 }
161
162 void EventHandler::OnKeyEvent( Integration::KeyEvent& keyEvent )
163 {
164   for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
165   {
166     (*iter)->OnKeyEvent( keyEvent );
167   }
168 }
169
170 void EventHandler::OnFocusChanged( bool focusIn )
171 {
172   // If the window gains focus and we hid the keyboard then show it again.
173   if( focusIn )
174   {
175     Dali::Clipboard clipboard = Clipboard::Get();
176     if ( clipboard )
177     {
178       clipboard.HideClipboard();
179     }
180   }
181   else
182   {
183     // Hiding clipboard event will be ignored once because window focus out event is always received on showing clipboard
184     Dali::Clipboard clipboard = Clipboard::Get();
185     if ( clipboard )
186     {
187       Clipboard& clipBoardImpl( GetImplementation( clipboard ) );
188       clipBoardImpl.HideClipboard(true);
189     }
190   }
191 }
192
193 void EventHandler::OnRotation( const RotationEvent& event )
194 {
195   for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
196   {
197     (*iter)->OnRotation( event );
198   }
199 }
200
201 void EventHandler::OnWindowDamaged( const DamageArea& area )
202 {
203   SendEvent( area );
204 }
205
206 void EventHandler::OnSelectionDataSend( void* event )
207 {
208   Dali::Clipboard clipboard = Clipboard::Get();
209   if( clipboard )
210   {
211     Clipboard& clipBoardImpl( GetImplementation( clipboard ) );
212     clipBoardImpl.ExcuteBuffered( true, event );
213   }
214 }
215
216 void EventHandler::OnSelectionDataReceived( void* event )
217 {
218   // We have got the selected content, inform the clipboard event listener (if we have one).
219   Dali::Clipboard clipboard = Clipboard::Get();
220   char* selectionData = NULL;
221   if( clipboard )
222   {
223     Clipboard& clipBoardImpl( GetImplementation( clipboard ) );
224     selectionData = clipBoardImpl.ExcuteBuffered( false, event );
225   }
226
227   if( selectionData && mClipboardEventNotifier )
228   {
229     ClipboardEventNotifier& clipboardEventNotifier( ClipboardEventNotifier::GetImplementation( mClipboardEventNotifier ) );
230     std::string content( selectionData, strlen( selectionData ) );
231
232     clipboardEventNotifier.SetContent( content );
233     clipboardEventNotifier.EmitContentSelectedSignal();
234
235     DALI_LOG_INFO( gSelectionEventLogFilter, Debug::General, "EcoreEventSelectionNotify: Content(%d): %s\n" , strlen(selectionData), selectionData );
236   }
237 }
238
239 void EventHandler::OnStyleChanged( StyleChange::Type styleChange )
240 {
241   SendEvent( styleChange );
242 }
243
244 void EventHandler::OnAccessibilityNotification( const WindowBase::AccessibilityInfo& info )
245 {
246 #ifdef DALI_ELDBUS_AVAILABLE
247   if( mPaused )
248   {
249     return;
250   }
251
252   if( !mAccessibilityAdaptor )
253   {
254     DALI_LOG_ERROR( "Invalid accessibility adaptor\n" );
255     return;
256   }
257
258   AccessibilityAdaptor* accessibilityAdaptor( &AccessibilityAdaptor::GetImplementation( mAccessibilityAdaptor ) );
259   if( !accessibilityAdaptor )
260   {
261     DALI_LOG_ERROR( "Cannot access accessibility adaptor\n" );
262     return;
263   }
264
265   // Create a touch point object.
266   TouchPoint::State touchPointState( TouchPoint::Down );
267   if( info.state == 0 )
268   {
269     touchPointState = TouchPoint::Down; // Mouse down.
270   }
271   else if( info.state == 1 )
272   {
273     touchPointState = TouchPoint::Motion; // Mouse move.
274   }
275   else if( info.state == 2 )
276   {
277     touchPointState = TouchPoint::Up; // Mouse up.
278   }
279   else
280   {
281     touchPointState = TouchPoint::Interrupted; // Error.
282   }
283
284   // Send touch event to accessibility adaptor.
285   TouchPoint point( 0, touchPointState, static_cast< float >( info.startX ), static_cast< float >( info.startY ) );
286
287   // Perform actions based on received gestures.
288   // Note: This is seperated from the reading so we can have other input readers without changing the below code.
289   switch( info.gestureValue )
290   {
291     case 0: // OneFingerHover
292     {
293       // Focus, read out.
294       accessibilityAdaptor->HandleActionReadEvent( static_cast< unsigned int >( info.startX ), static_cast< unsigned int >( info.startY ), true /* allow read again */ );
295       break;
296     }
297     case 1: // TwoFingersHover
298     {
299       // In accessibility mode, scroll action should be handled when the currently focused actor is contained in scrollable control
300       accessibilityAdaptor->HandleActionScrollEvent( point, GetCurrentMilliSeconds() );
301       break;
302     }
303     case 2: // ThreeFingersHover
304     {
305       // Read from top item on screen continuously.
306       accessibilityAdaptor->HandleActionReadFromTopEvent();
307       break;
308     }
309     case 3: // OneFingerFlickLeft
310     {
311       // Move to previous item.
312       accessibilityAdaptor->HandleActionReadPreviousEvent();
313       break;
314     }
315     case 4: // OneFingerFlickRight
316     {
317       // Move to next item.
318       accessibilityAdaptor->HandleActionReadNextEvent();
319       break;
320     }
321     case 5: // OneFingerFlickUp
322     {
323       // Move to previous item.
324       accessibilityAdaptor->HandleActionPreviousEvent();
325       break;
326     }
327     case 6: // OneFingerFlickDown
328     {
329       // Move to next item.
330       accessibilityAdaptor->HandleActionNextEvent();
331       break;
332     }
333     case 7: // TwoFingersFlickUp
334     {
335       // Scroll up the list.
336       accessibilityAdaptor->HandleActionScrollUpEvent();
337       break;
338     }
339     case 8: // TwoFingersFlickDown
340     {
341       // Scroll down the list.
342       accessibilityAdaptor->HandleActionScrollDownEvent();
343       break;
344     }
345     case 9: // TwoFingersFlickLeft
346     {
347       // Scroll left to the previous page
348       accessibilityAdaptor->HandleActionPageLeftEvent();
349       break;
350     }
351     case 10: // TwoFingersFlickRight
352     {
353       // Scroll right to the next page
354       accessibilityAdaptor->HandleActionPageRightEvent();
355       break;
356     }
357     case 11: // ThreeFingersFlickLeft
358     {
359       // Not exist yet
360       break;
361     }
362     case 12: // ThreeFingersFlickRight
363     {
364       // Not exist yet
365       break;
366     }
367     case 13: // ThreeFingersFlickUp
368     {
369       // Not exist yet
370       break;
371     }
372     case 14: // ThreeFingersFlickDown
373     {
374       // Not exist yet
375       break;
376     }
377     case 15: // OneFingerSingleTap
378     {
379       // Focus, read out.
380       accessibilityAdaptor->HandleActionReadEvent( static_cast< unsigned int >( info.startX ), static_cast< unsigned int >( info.startY ), true /* allow read again */ );
381       break;
382     }
383     case 16: // OneFingerDoubleTap
384     {
385       // Activate selected item / active edit mode.
386       accessibilityAdaptor->HandleActionActivateEvent();
387       break;
388     }
389     case 17: // OneFingerTripleTap
390     {
391       // Zoom
392       accessibilityAdaptor->HandleActionZoomEvent();
393       break;
394     }
395     case 18: // TwoFingersSingleTap
396     {
397       // Pause/Resume current speech
398       accessibilityAdaptor->HandleActionReadPauseResumeEvent();
399       break;
400     }
401     case 19: // TwoFingersDoubleTap
402     {
403       // Start/Stop current action
404       accessibilityAdaptor->HandleActionStartStopEvent();
405       break;
406     }
407     case 20: // TwoFingersTripleTap
408     {
409       // Read information from indicator
410       // Not supported
411       break;
412     }
413     case 21: // ThreeFingersSingleTap
414     {
415       // Read from top item on screen continuously.
416       accessibilityAdaptor->HandleActionReadFromTopEvent();
417       break;
418     }
419     case 22: // ThreeFingersDoubleTap
420     {
421       // Read from next item continuously.
422       accessibilityAdaptor->HandleActionReadFromNextEvent();
423       break;
424     }
425     case 23: // ThreeFingersTripleTap
426     {
427       // Not exist yet
428       break;
429     }
430     case 24: // OneFingerFlickLeftReturn
431     {
432       // Scroll up to the previous page
433       accessibilityAdaptor->HandleActionPageUpEvent();
434       break;
435     }
436     case 25: // OneFingerFlickRightReturn
437     {
438       // Scroll down to the next page
439       accessibilityAdaptor->HandleActionPageDownEvent();
440       break;
441     }
442     case 26: // OneFingerFlickUpReturn
443     {
444       // Move to the first item on screen
445       accessibilityAdaptor->HandleActionMoveToFirstEvent();
446       break;
447     }
448     case 27: // OneFingerFlickDownReturn
449     {
450       // Move to the last item on screen
451       accessibilityAdaptor->HandleActionMoveToLastEvent();
452       break;
453     }
454     case 28: // TwoFingersFlickLeftReturn
455     {
456       // Not exist yet
457       break;
458     }
459     case 29: // TwoFingersFlickRightReturn
460     {
461       // Not exist yet
462       break;
463     }
464     case 30: // TwoFingersFlickUpReturn
465     {
466       // Not exist yet
467       break;
468     }
469     case 31: // TwoFingersFlickDownReturn
470     {
471       // Not exist yet
472       break;
473     }
474     case 32: // ThreeFingersFlickLeftReturn
475     {
476       // Not exist yet
477       break;
478     }
479     case 33: // ThreeFingersFlickRightReturn
480     {
481       // Not exist yet
482       break;
483     }
484     case 34: // ThreeFingersFlickUpReturn
485     {
486       // Not exist yet
487       break;
488     }
489     case 35: // ThreeFingersFlickDownReturn
490     {
491       // Not exist yet
492       break;
493     }
494   }
495 #endif
496 }
497
498 void EventHandler::AddObserver( Observer& observer )
499 {
500   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
501
502   if ( match == mObservers.end() )
503   {
504     mObservers.push_back( &observer );
505   }
506 }
507
508 void EventHandler::RemoveObserver( Observer& observer )
509 {
510   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
511
512   if ( match != mObservers.end() )
513   {
514     mObservers.erase( match );
515   }
516 }
517
518 } // namespace Adaptor
519
520 } // namespace Internal
521
522 } // namespace Dali