+
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+ // ElDBus Accessibility Callbacks
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef DALI_ELDBUS_AVAILABLE
+ // Callback for Ecore ElDBus accessibility events.
+ static void OnEcoreElDBusAccessibilityNotification( void *context EINA_UNUSED, const Eldbus_Message *message )
+ {
+ EventHandler* handler = static_cast< EventHandler* >( context );
+ // Ignore any accessibility events when paused.
+ if( handler->mPaused )
+ {
+ return;
+ }
+
+ if ( !handler->mAccessibilityAdaptor )
+ {
+ DALI_LOG_ERROR( "Invalid accessibility adaptor\n" );
+ return;
+ }
+
+ AccessibilityAdaptor* accessibilityAdaptor( &AccessibilityAdaptor::GetImplementation( handler->mAccessibilityAdaptor ) );
+ if ( !accessibilityAdaptor )
+ {
+ DALI_LOG_ERROR( "Cannot access accessibility adaptor\n" );
+ return;
+ }
+
+ const char *gestureName;
+ int xS, yS, xE, yE;
+ unsigned int state;
+
+ // The string defines the arg-list's respective types.
+ if( !eldbus_message_arguments_get( message, "siiiiu", &gestureName, &xS, &yS, &xE, &yE, &state ) )
+ {
+ DALI_LOG_ERROR( "OnEcoreElDBusAccessibilityNotification: Error getting arguments\n" );
+ }
+
+ DALI_LOG_INFO( gImfLogging, Debug::General, "Got gesture: Name: %s Args: %d,%d,%d,%d State: %d\n", gestureName, xS, yS, xE, yE );
+
+ unsigned int fingers = 0;
+ char* stringPosition = ( char* )gestureName;
+
+ // Check how many fingers the gesture uses.
+ for( unsigned int i = 0; i < FingerCountStringsTotal; ++i )
+ {
+ unsigned int matchLength = strlen( ElDBusAccessibilityFingerCountStrings[ i ] );
+ if( strncmp( gestureName, ElDBusAccessibilityFingerCountStrings[ i ], matchLength ) == 0 )
+ {
+ fingers = i + 1;
+ stringPosition += matchLength;
+ break;
+ }
+ }
+
+ if( fingers == 0 )
+ {
+ // Error: invalid gesture.
+ return;
+ }
+
+ GestureType gestureType = GESTURE_TYPE_NONE;
+ SubGestureType subGestureType = SUB_GESTURE_TYPE_NONE;
+ GestureDirection direction = GESTURE_DIRECTION_NONE;
+
+ // Check for full gesture type names first.
+ for( unsigned int i = 0; i < FullEventTypeStringsTotal; ++i )
+ {
+ unsigned int matchLength = strlen( ElDBusAccessibilityFullEventTypeStrings[ i ].name );
+ if( strncmp( stringPosition, ElDBusAccessibilityFullEventTypeStrings[ i ].name, matchLength ) == 0 )
+ {
+ gestureType = ElDBusAccessibilityFullEventTypeStrings[ i ].type;
+ break;
+ }
+ }
+
+ // If we didn't find a full gesture, check for sub gesture type names.
+ if( gestureType == GESTURE_TYPE_NONE )
+ {
+ // No full gesture name found, look for partial types.
+ for( unsigned int i = 0; i < DirectionalEventTypeStringsTotal; ++i )
+ {
+ unsigned int matchLength = strlen( ElDBusAccessibilityDirectionalEventTypeStrings[ i ].name );
+ if( strncmp( stringPosition, ElDBusAccessibilityDirectionalEventTypeStrings[ i ].name, matchLength ) == 0 )
+ {
+ subGestureType = ElDBusAccessibilityDirectionalEventTypeStrings[ i ].type;
+ stringPosition += matchLength;
+ break;
+ }
+ }
+
+ if( subGestureType == SUB_GESTURE_TYPE_NONE )
+ {
+ // ERROR: Gesture not recognised.
+ return;
+ }
+
+ // If the gesture was a sub type, get it's respective direction.
+ for( unsigned int i = 0; i < DirectionStringsTotal; ++i )
+ {
+ unsigned int matchLength = strlen( ElDBusAccessibilityDirectionStrings[ i ].name );
+ if( strncmp( stringPosition, ElDBusAccessibilityDirectionStrings[ i ].name, matchLength ) == 0 )
+ {
+ direction = ElDBusAccessibilityDirectionStrings[ i ].direction;
+ stringPosition += matchLength;
+ break;
+ }
+ }
+
+ if( direction == GESTURE_DIRECTION_NONE )
+ {
+ // ERROR: Gesture not recognised.
+ return;
+ }
+ }
+
+ // Action the detected gesture here.
+ if( gestureType != GESTURE_TYPE_NONE )
+ {
+ DALI_LOG_INFO( gImfLogging, Debug::General, "Got gesture: Fingers: %d Gesture type: %d\n", fingers, gestureType );
+ }
+ else
+ {
+ DALI_LOG_INFO( gImfLogging, Debug::General, "Got gesture: Fingers: %d Gesture sub type: %d Gesture direction: %d\n",
+ fingers, subGestureType, direction );
+ }
+
+ // Create a touch point object.
+ TouchPoint::State touchPointState( TouchPoint::Down );
+ if ( state == 0 )
+ {
+ touchPointState = TouchPoint::Down; // Mouse down.
+ }
+ else if ( state == 1 )
+ {
+ touchPointState = TouchPoint::Motion; // Mouse move.
+ }
+ else if ( state == 2 )
+ {
+ touchPointState = TouchPoint::Up; // Mouse up.
+ }
+ else
+ {
+ touchPointState = TouchPoint::Interrupted; // Error.
+ }
+
+ // Send touch event to accessibility adaptor.
+ TouchPoint point( 0, touchPointState, (float)xS, (float)yS );
+
+ // Perform actions based on received gestures.
+ // Note: This is seperated from the reading so we can (in future)
+ // have other input readers without changing the below code.
+ switch( fingers )
+ {
+ case 1:
+ {
+ if( gestureType == GESTURE_TYPE_SINGLE_TAP || ( gestureType == GESTURE_TYPE_HOVER && touchPointState == TouchPoint::Motion ) )
+ {
+ // Focus, read out.
+ accessibilityAdaptor->HandleActionReadEvent( (unsigned int)xS, (unsigned int)yS, true /* allow read again */ );
+ }
+ else if( gestureType == GESTURE_TYPE_DOUBLE_TAP )
+ {
+ if( false ) // TODO: how to detect double tap + hold
+ {
+ // Move or drag icon / view more options for selected items.
+ // accessibilityAdaptor->HandleActionTouchEvent( point, GetCurrentMilliSeconds() );
+ }
+ else
+ {
+ // Activate selected item / active edit mode.
+ accessibilityAdaptor->HandleActionActivateEvent();
+ }
+ }
+ else if( gestureType == GESTURE_TYPE_TRIPLE_TAP )
+ {
+ // Zoom
+ accessibilityAdaptor->HandleActionZoomEvent();
+ }
+ else if( subGestureType == SUB_GESTURE_TYPE_FLICK )
+ {
+ if( direction == GESTURE_DIRECTION_LEFT )
+ {
+ // Move to previous item.
+ accessibilityAdaptor->HandleActionReadPreviousEvent();
+ }
+ else if( direction == GESTURE_DIRECTION_RIGHT )
+ {
+ // Move to next item.
+ accessibilityAdaptor->HandleActionReadNextEvent();
+ }
+ else if( direction == GESTURE_DIRECTION_UP )
+ {
+ // Move to next item.
+ accessibilityAdaptor->HandleActionPreviousEvent();
+ }
+ else if( direction == GESTURE_DIRECTION_DOWN )
+ {
+ // Move to next item.
+ accessibilityAdaptor->HandleActionNextEvent();
+ }
+ else if( direction == GESTURE_DIRECTION_LEFT_RETURN )
+ {
+ // Scroll up to the previous page
+ accessibilityAdaptor->HandleActionPageUpEvent();
+ }
+ else if( direction == GESTURE_DIRECTION_RIGHT_RETURN )
+ {
+ // Scroll down to the next page
+ accessibilityAdaptor->HandleActionPageDownEvent();
+ }
+ else if( direction == GESTURE_DIRECTION_UP_RETURN )
+ {
+ // Move to the first item on screen
+ accessibilityAdaptor->HandleActionMoveToFirstEvent();
+ }
+ else if( direction == GESTURE_DIRECTION_DOWN_RETURN )
+ {
+ // Move to the last item on screen
+ accessibilityAdaptor->HandleActionMoveToLastEvent();
+ }
+ }
+ break;
+ }
+
+ case 2:
+ {
+ if( gestureType == GESTURE_TYPE_HOVER )
+ {
+ // In accessibility mode, scroll action should be handled when the currently focused actor is contained in scrollable control
+ accessibilityAdaptor->HandleActionScrollEvent( point, GetCurrentMilliSeconds() );
+ }
+ else if( gestureType == GESTURE_TYPE_SINGLE_TAP )
+ {
+ // Pause/Resume current speech
+ accessibilityAdaptor->HandleActionReadPauseResumeEvent();
+ }
+ else if( gestureType == GESTURE_TYPE_DOUBLE_TAP )
+ {
+ // Start/Stop current action
+ accessibilityAdaptor->HandleActionStartStopEvent();
+ }
+ else if( gestureType == GESTURE_TYPE_TRIPLE_TAP )
+ {
+ // Read information from indicator
+ accessibilityAdaptor->HandleActionReadIndicatorInformationEvent();
+ }
+ else if( subGestureType == SUB_GESTURE_TYPE_FLICK )
+ {
+ if( direction == GESTURE_DIRECTION_LEFT )
+ {
+ // Scroll left to the previous page
+ accessibilityAdaptor->HandleActionPageLeftEvent();
+ }
+ else if( direction == GESTURE_DIRECTION_RIGHT )
+ {
+ // Scroll right to the next page
+ accessibilityAdaptor->HandleActionPageRightEvent();
+ }
+ else if( direction == GESTURE_DIRECTION_UP )
+ {
+ // Scroll up the list.
+ accessibilityAdaptor->HandleActionScrollUpEvent();
+ }
+ else if( direction == GESTURE_DIRECTION_DOWN )
+ {
+ // Scroll down the list.
+ accessibilityAdaptor->HandleActionScrollDownEvent();
+ }
+ }
+ break;
+ }
+
+ case 3:
+ {
+ if( gestureType == GESTURE_TYPE_SINGLE_TAP )
+ {
+ // Read from top item on screen continuously.
+ accessibilityAdaptor->HandleActionReadFromTopEvent();
+ }
+ else if( gestureType == GESTURE_TYPE_DOUBLE_TAP )
+ {
+ // Read from next item continuously.
+ accessibilityAdaptor->HandleActionReadFromNextEvent();
+ }
+ break;
+ }
+ }
+ }
+
+ // Callback for to set up Ecore ElDBus for accessibility callbacks.
+ static void EcoreElDBusInitialisation( void *handle, const Eldbus_Message *message, Eldbus_Pending *pending EINA_UNUSED )
+ {
+ Eldbus_Object *object;
+ Eldbus_Proxy *manager;
+ const char *a11yBusAddress = NULL;
+ EventHandler* handler = static_cast< EventHandler* >( handle );
+
+ // The string defines the arg-list's respective types.
+ if( !eldbus_message_arguments_get( message, "s", &a11yBusAddress ) )
+ {
+ DALI_LOG_ERROR( "EcoreElDBusInitialisation: Error getting arguments\n" );
+ }
+
+ DALI_LOG_INFO( gImfLogging, Debug::General, "Ecore ElDBus Accessibility address: %s\n", a11yBusAddress );
+
+ handler->mImpl->mA11yConnection = eldbus_address_connection_get( a11yBusAddress );
+
+ object = eldbus_object_get( handler->mImpl->mA11yConnection, BUS, PATH );
+ manager = eldbus_proxy_get( object, INTERFACE );
+
+ // Pass the callback data through to the signal handler.
+ eldbus_proxy_signal_handler_add( manager, SIGNAL, OnEcoreElDBusAccessibilityNotification, handle );
+ }
+#endif // DALI_ELDBUS_AVAILABLE
+