[dali_2.0.49] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / control / control-data-impl.cpp
index db346bd..f9f4376 100644 (file)
@@ -410,6 +410,40 @@ void SetVisualsOffScene(const RegisteredVisualContainer& container, Actor parent
   }
 }
 
+Dali::Rect<> GetShowingGeometry(Dali::Rect<> rect, Dali::Toolkit::DevelControl::AccessibleImpl* accessibleImpl)
+{
+  Rect<>  parentRect;
+  Vector2 currentPosition;
+  auto    parent = dynamic_cast<Toolkit::DevelControl::AccessibleImpl*>(accessibleImpl->GetParent());
+
+  while(parent)
+  {
+    parentRect = parent->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
+
+    currentPosition.x = rect.x;
+    currentPosition.y = rect.y;
+
+    rect.x      = rect.x > parentRect.x ? rect.x : parentRect.x;
+    rect.y      = rect.y > parentRect.y ? rect.y : parentRect.y;
+    rect.width  = currentPosition.x + rect.width < parentRect.x + parentRect.width ? currentPosition.x + rect.width - rect.x : parentRect.x + parentRect.width - rect.x;
+    rect.height = currentPosition.y + rect.height < parentRect.y + parentRect.height ? currentPosition.y + rect.height - rect.y : parentRect.y + parentRect.height - rect.y;
+
+    if(rect.width < 0 || rect.height < 0)
+    {
+      return rect;
+    }
+
+    parent = dynamic_cast<Toolkit::DevelControl::AccessibleImpl*>(parent->GetParent());
+  }
+
+  return rect;
+}
+
+static bool IsShowingGeometryOnScreen(Dali::Rect<> rect)
+{
+  return rect.width > 0 && rect.height > 0;
+}
+
 } // unnamed namespace
 
 // clang-format off
@@ -433,6 +467,8 @@ const PropertyRegistration Control::Impl::PROPERTY_18(typeRegistration, "accessi
 const PropertyRegistration Control::Impl::PROPERTY_19(typeRegistration, "accessibilityRole",              Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE,               Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
 const PropertyRegistration Control::Impl::PROPERTY_20(typeRegistration, "accessibilityHighlightable",     Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE,      Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
 const PropertyRegistration Control::Impl::PROPERTY_21(typeRegistration, "accessibilityAttributes",        Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES,         Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty);
+const PropertyRegistration Control::Impl::PROPERTY_22(typeRegistration, "dispatchKeyEvents",              Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS,               Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
+
 // clang-format on
 
 Control::Impl::Impl(Control& controlImpl)
@@ -467,7 +503,8 @@ Control::Impl::Impl(Control& controlImpl)
   mIsKeyboardNavigationSupported(false),
   mIsKeyboardFocusGroup(false),
   mIsEmittingResourceReadySignal(false),
-  mNeedToEmitResourceReady(false)
+  mNeedToEmitResourceReady(false),
+  mDispatchKeyEvents(true)
 {
   Dali::Accessibility::Accessible::RegisterControlAccessibilityGetter(
     [](Dali::Actor actor) -> Dali::Accessibility::Accessible* {
@@ -518,6 +555,90 @@ const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl
   return *internalControl.mImpl;
 }
 
+void Control::Impl::CheckHighlightedObjectGeometry()
+{
+  auto accessibleImpl = dynamic_cast<Dali::Toolkit::DevelControl::AccessibleImpl*>(mAccessibilityObject.get());
+  if(!accessibleImpl)
+  {
+    DALI_LOG_ERROR("accessibleImpl is not a pointer to a DevelControl::AccessibleImpl type");
+    return;
+  }
+
+  auto lastPosition   = accessibleImpl->GetLastPosition();
+  auto accessibleRect = accessibleImpl->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
+  auto rect = GetShowingGeometry(accessibleRect, accessibleImpl);
+
+  switch(mAccessibilityLastScreenRelativeMoveType)
+  {
+    case Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE:
+    {
+      if(IsShowingGeometryOnScreen(rect))
+      {
+        mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
+      }
+      break;
+    }
+    case Dali::Accessibility::ScreenRelativeMoveType::INSIDE:
+    {
+      if(rect.width < 0 && accessibleRect.x != lastPosition.x)
+      {
+        mAccessibilityLastScreenRelativeMoveType = (accessibleRect.x < lastPosition.x) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
+      }
+      if(rect.height < 0 && accessibleRect.y != lastPosition.y)
+      {
+        mAccessibilityLastScreenRelativeMoveType = (accessibleRect.y < lastPosition.y) ? Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT : Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT;
+      }
+      // notify AT-clients on outgoing moves only
+      if(mAccessibilityLastScreenRelativeMoveType != Dali::Accessibility::ScreenRelativeMoveType::INSIDE)
+      {
+        mAccessibilityObject.get()->EmitMovedOutOfScreen(mAccessibilityLastScreenRelativeMoveType);
+      }
+      break;
+    }
+    case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_TOP_LEFT:
+    case Dali::Accessibility::ScreenRelativeMoveType::OUTGOING_BOTTOM_RIGHT:
+    {
+      if(IsShowingGeometryOnScreen(rect))
+      {
+        mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::INSIDE;
+      }
+      else
+      {
+        mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
+      }
+      break;
+    }
+    default:
+    {
+      break;
+    }
+  }
+
+  accessibleImpl->SetLastPosition(Vector2(accessibleRect.x, accessibleRect.y));
+}
+
+void Control::Impl::RegisterAccessibilityPositionPropertyNotification()
+{
+  if(mIsAccessibilityPositionPropertyNotificationSet)
+  {
+    return;
+  }
+  // set default value until first move of object is detected
+  mAccessibilityLastScreenRelativeMoveType = Dali::Accessibility::ScreenRelativeMoveType::OUTSIDE;
+  // recalculate mAccessibilityLastScreenRelativeMoveType accordingly to the initial position
+  CheckHighlightedObjectGeometry();
+  mAccessibilityPositionNotification       = mControlImpl.Self().AddPropertyNotification(Actor::Property::WORLD_POSITION, StepCondition(1.0f, 1.0f));
+  mAccessibilityPositionNotification.SetNotifyMode(PropertyNotification::NOTIFY_ON_CHANGED);
+  mAccessibilityPositionNotification.NotifySignal().Connect(this, [this](PropertyNotification&){ CheckHighlightedObjectGeometry(); });
+  mIsAccessibilityPositionPropertyNotificationSet = true;
+}
+
+void Control::Impl::UnregisterAccessibilityPositionPropertyNotification()
+{
+  mControlImpl.Self().RemovePropertyNotification(mAccessibilityPositionNotification);
+  mIsAccessibilityPositionPropertyNotificationSet = false;
+}
+
 // Gesture Detection Methods
 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
 {
@@ -1244,6 +1365,16 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const
         }
         break;
       }
+
+      case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
+      {
+        bool dispatch;
+        if(value.Get(dispatch))
+        {
+          controlImpl.mImpl->mDispatchKeyEvents = dispatch;
+        }
+        break;
+      }
     }
   }
 }
@@ -1404,6 +1535,11 @@ Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index i
         value = controlImpl.mImpl->mAccessibilityAttributes;
         break;
       }
+      case Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS:
+      {
+        value = controlImpl.mImpl->mDispatchKeyEvents;
+        break;
+      }
     }
   }