[AT-SPI] Introduce WidgetViewAccessible 17/261417/14
authorArtur Świgoń <a.swigon@samsung.com>
Fri, 18 Mar 2022 09:06:27 +0000 (10:06 +0100)
committerArtur Świgoń <a.swigon@samsung.com>
Thu, 7 Jul 2022 15:37:46 +0000 (17:37 +0200)
WidgetView needs a special Accessible implementation that will report an
extra non-Actor child (the ProxyAccessible representing the remote
object) and handle extra D-Bus communication with it (including
informing it about its position on the screen for navigation purposes).

Change-Id: Ia631f50293a1b4d996adc7cb90ecfbc51adeb971

widget_viewer_dali/internal/widget_view/widget_view_impl.cpp
widget_viewer_dali/internal/widget_view/widget_view_impl.h

index 1fae55ff06b1b42a277c5d46012b5ca245db11d3..dabaa70e2c00ac17a41a353da19697038405af92 100644 (file)
@@ -1048,8 +1048,13 @@ void WidgetView::OnInitialize()
   self.WheelEventSignal().Connect( this, &WidgetView::OnWheelEvent );
 
   // Accessibility
-  self.SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::EMBEDDED);
-  self.SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true);
+  self.SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::FILLER);
+  self.SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, false);
+}
+
+Dali::Toolkit::DevelControl::ControlAccessible* WidgetView::CreateAccessibleObject()
+{
+  return new WidgetViewAccessible(Self());
 }
 
 void WidgetView::OnSceneConnection( int depth )
@@ -1139,6 +1144,13 @@ void WidgetView::OnUpdateArea( Dali::PropertyNotification& source )
     }
     mPaused = needPaused;
   }
+
+  if(!mPaused)
+  {
+    auto* accessible = dynamic_cast<WidgetView::WidgetViewAccessible*>(GetAccessibleObject());
+    DALI_ASSERT_DEBUG(accessible);
+    accessible->SynchronizeChildPosition();
+  }
 }
 
 void WidgetView::OnSizeSet( const Vector3& targetSize )
@@ -1871,6 +1883,53 @@ void WidgetView::OnSizeAnimation( Animation& animation, const Vector3& targetSiz
   widget_instance_resize(mInstanceId.c_str(), targetSize.x, targetSize.y);
 }
 
+WidgetView::WidgetViewAccessible::WidgetViewAccessible(Dali::Actor self)
+: ControlAccessible(self)
+{
+  mRemoteChild.SetParent(this);
+
+  Dali::Accessibility::Bridge::EnabledSignal().Connect(this, &WidgetViewAccessible::OnChildrenChanged);
+  Dali::Accessibility::Bridge::DisabledSignal().Connect(this, &WidgetViewAccessible::OnChildrenChanged);
+}
+
+void WidgetView::WidgetViewAccessible::SynchronizeChildPosition()
+{
+  if(!Dali::Accessibility::IsUp() || !mRemoteChild.GetAddress())
+  {
+    return;
+  }
+
+  auto extents = GetExtents(Dali::Accessibility::CoordinateType::SCREEN);
+  Dali::Accessibility::Bridge::GetCurrentBridge()->SetSocketOffset(&mRemoteChild, extents.x, extents.y);
+}
+
+void WidgetView::WidgetViewAccessible::DoGetChildren(std::vector<Dali::Accessibility::Accessible*>& children)
+{
+  using Dali::Accessibility::Bridge;
+
+  static const char rootPath[]  = "root";
+
+  if(!Dali::Accessibility::IsUp())
+  {
+    return;
+  }
+
+  auto  self       = Dali::WidgetView::WidgetView::DownCast(Self());
+  auto& selfImpl   = Dali::WidgetView::GetImplementation(self);
+  auto  instanceId = selfImpl.GetInstanceId();
+  auto  busName    = Bridge::MakeBusNameForWidget(instanceId);
+
+  auto address = Bridge::GetCurrentBridge()->EmbedSocket(GetAddress(), {busName, rootPath});
+
+  mRemoteChild.SetAddress(address);
+
+  if(address)
+  {
+    children.push_back(&mRemoteChild);
+    SynchronizeChildPosition();
+  }
+}
+
 } // namespace Internal
 
 } // namespace WidgetView
index 9c5ac79e121a40d12a6914628d06cdc5eddbe3e6..82c54649867a524d9087eff381ab4f88cd9851c3 100644 (file)
@@ -23,6 +23,7 @@
 
 // EXTERNAL INCLUDES
 #include <dali/public-api/rendering/renderer.h>
+#include <dali-toolkit/devel-api/controls/control-accessible.h>
 #include <dali-toolkit/public-api/controls/control-impl.h>
 #include <dali-toolkit/public-api/controls/text-controls/text-label.h>
 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
@@ -31,6 +32,7 @@
 #include <tbm_surface.h>
 #include <screen_connector_toolkit.h>
 #include <dali/devel-api/adaptor-framework/native-image-source-devel.h>
+#include <dali/devel-api/adaptor-framework/proxy-accessible.h>
 #include <dali/devel-api/adaptor-framework/window-devel.h>
 #include <dali/public-api/object/property-notification.h>
 
@@ -400,6 +402,11 @@ private: // From Control
    */
   virtual void OnInitialize();
 
+  /**
+   * @copydoc Toolkit::Internal::Control::CreateAccessibleObject()
+   */
+  Dali::Toolkit::DevelControl::ControlAccessible* CreateAccessibleObject() override;
+
   /**
    * @copydoc Toolkit::Control::OnSceneConnection()
    */
@@ -472,8 +479,32 @@ private:
   // Undefined
   WidgetView& operator= ( const WidgetView& );
 
-private:
+protected:
+  class WidgetViewAccessible : public Dali::Toolkit::DevelControl::ControlAccessible
+  {
+  public:
+    WidgetViewAccessible() = delete;
+
+    WidgetViewAccessible(Dali::Actor self);
+
+    /**
+     * @brief Notifies the remote child about its position on the screen.
+     *
+     * @note The number of D-Bus messages sent may be smaller than the number of calls to this method.
+     */
+    void SynchronizeChildPosition();
+
+  protected:
+    /**
+     * @copydoc Dali::Accessibility::ActorAccessible::DoGetChildren()
+     */
+    void DoGetChildren(std::vector<Dali::Accessibility::Accessible*>& children) override;
+
+  private:
+    Dali::Accessibility::ProxyAccessible mRemoteChild;
+  };
 
+private:
   Dali::Renderer mRenderer;
 
   std::string mWidgetId;