[AT-SPI] Rework Accessible::GetInterfaces() 72/270772/11
authorArtur Świgoń <a.swigon@samsung.com>
Tue, 8 Feb 2022 08:19:46 +0000 (09:19 +0100)
committerArtur Świgoń <a.swigon@samsung.com>
Thu, 24 Feb 2022 15:15:55 +0000 (16:15 +0100)
This patch:

* Introduces an AtspiInterface enumeration with all possible AT-SPI
interfaces and an AtspiInterfaces collection (using EnumBitSet), and
changes the return type of Accessible::GetInterfaces() to
AtspiInterfaces. The new, compact storage format allows the collection
of interfaces to be cached. Interfaces will be queried even more often
with the upcoming polymorphic NUIViewAccessible. Thus, it makes sense to
introduce such an optimization, and checking whether a bit is set in a
4-byte bitmask is significantly cheaper than performing a series of
dynamic_cast's every time GetInterfaces() is called. Such calculation is
only performed once by a new virtual method, DoGetInterfaces().

* Adds a new static method Accessible::GetInterfaceName() which converts
an AtspiInterface value to a string identifier used in DBus
communication, which allows to remove most of the macro definitions in
accessibility-common.h.

* Adds some missing operators to Accessibility::BitSet and EnumBitSet.

* Introduces a template type resolver AtspiInterfaceType which converts
an AtspiInterface value to a native C++ type, and adds
Accessible::DownCast() which uses this helper to check both the return
value of GetInterfaces() and the result of dynamic_cast. This double
checking is required by the upcoming NUIViewAccessible. As a possible
optimization, dynamic_cast could be changed to static_cast for release
builds in the future (which should be safe as long as DoGetInterfaces()
is implemented correctly).

* Adds a new template method FindCurrentObjectWithInterface() to
BridgeBase in order to centralize previously duplicated error return
logic in implementations of FindSelf() in various Bridge classes, which
differed only in the target type and interface name to be reported in
the error DBus reply.

* Adds a new virtual method Accessible::DoGetInterfaces() which allows
any derived classes to customize (specifically, narrow down) the set of
interfaces visible to DBus callers (and FindCurrentObjectWithInterface()
respects that). This is the first step towards allowing NUI controls to
freely implement AT-SPI interfaces (currently they have to choose from a
small predefined set of NUIViewAccessible-derived classes due to the use
of dynamic_cast).

Change-Id: I14428ec20693a9b121d40ac1b12b6e30c709d313

32 files changed:
dali/devel-api/adaptor-framework/accessibility-bitset.h
dali/devel-api/adaptor-framework/accessibility.cpp
dali/devel-api/adaptor-framework/accessibility.h
dali/devel-api/atspi-interfaces/accessible.h
dali/devel-api/atspi-interfaces/action.h
dali/devel-api/atspi-interfaces/application.h
dali/devel-api/atspi-interfaces/collection.h
dali/devel-api/atspi-interfaces/component.h
dali/devel-api/atspi-interfaces/editable-text.h
dali/devel-api/atspi-interfaces/hyperlink.h
dali/devel-api/atspi-interfaces/hypertext.h
dali/devel-api/atspi-interfaces/selection.h
dali/devel-api/atspi-interfaces/text.h
dali/devel-api/atspi-interfaces/value.h
dali/internal/accessibility/bridge/accessibility-common.h
dali/internal/accessibility/bridge/accessible.cpp
dali/internal/accessibility/bridge/bridge-accessible.cpp
dali/internal/accessibility/bridge/bridge-accessible.h
dali/internal/accessibility/bridge/bridge-action.cpp
dali/internal/accessibility/bridge/bridge-application.cpp
dali/internal/accessibility/bridge/bridge-base.cpp
dali/internal/accessibility/bridge/bridge-base.h
dali/internal/accessibility/bridge/bridge-collection.cpp
dali/internal/accessibility/bridge/bridge-component.cpp
dali/internal/accessibility/bridge/bridge-editable-text.cpp
dali/internal/accessibility/bridge/bridge-hyperlink.cpp
dali/internal/accessibility/bridge/bridge-hypertext.cpp
dali/internal/accessibility/bridge/bridge-impl.cpp
dali/internal/accessibility/bridge/bridge-object.cpp
dali/internal/accessibility/bridge/bridge-selection.cpp
dali/internal/accessibility/bridge/bridge-text.cpp
dali/internal/accessibility/bridge/bridge-value.cpp

index cdb5410..d9c0159 100644 (file)
@@ -169,6 +169,22 @@ public:
   /**
    * @brief Constructs a new BitSet with all bits initialized with bits from the specified integer.
    *
+   * This constructor is only available for BitSets with 32-bit capacity. Equivalent to the pseudocode:
+   * @code
+   * for(i = 0; i < 32; ++i) bits[i] = (data >> i) & 0x1;
+   * @endcode
+   *
+   * @param data 32-bit integer with the initial values.
+   */
+  template<std::size_t I = N, typename = std::enable_if_t<(I == N && N == 1u)>>
+  explicit BitSet(std::uint32_t data)
+  {
+    mData[0] = data;
+  }
+
+  /**
+   * @brief Constructs a new BitSet with all bits initialized with bits from the specified integer.
+   *
    * This constructor is only available for BitSets with 64-bit capacity. Equivalent to the pseudocode:
    * @code
    * for(i = 0; i < 64; ++i) bits[i] = (data >> i) & 0x1;
@@ -360,6 +376,21 @@ public:
   /**
    * @brief Obtains a copy of the internal storage serialized as a single integer.
    *
+   * This method is only available for BitSets with 32-bit capacity.
+   *
+   * @return A copy of the internal storage.
+   *
+   * @see BitSet::BitSet(std::uint32_t)
+   */
+  template<std::size_t I = N, typename = std::enable_if_t<(I == N && N == 1u)>>
+  std::uint32_t GetRawData32() const
+  {
+    return mData[0];
+  }
+
+  /**
+   * @brief Obtains a copy of the internal storage serialized as a single integer.
+   *
    * This method is only available for BitSets with 64-bit capacity.
    *
    * @return A copy of the internal storage.
@@ -424,6 +455,38 @@ public:
   // Operators
 
   /**
+   * @copydoc BitSet::operator~() const
+   */
+  EnumBitSet operator~() const
+  {
+    return BitSet<N>::operator~();
+  }
+
+  /**
+   * @copydoc BitSet::operator|(const BitSet&) const
+   */
+  EnumBitSet operator|(const EnumBitSet& other) const
+  {
+    return BitSet<N>::operator|(other);
+  }
+
+  /**
+   * @copydoc BitSet::operator&(const BitSet&) const
+   */
+  EnumBitSet operator&(const EnumBitSet& other) const
+  {
+    return BitSet<N>::operator&(other);
+  }
+
+  /**
+   * @copydoc BitSet::operator^(const BitSet&) const
+   */
+  EnumBitSet operator^(const EnumBitSet& other) const
+  {
+    return BitSet<N>::operator^(other);
+  }
+
+  /**
    * @copydoc BitSet::operator[](IndexType) const
    */
   bool operator[](Enum index) const
@@ -440,6 +503,12 @@ public:
   }
 
 private:
+  // For operators '~|&^'
+  EnumBitSet(BitSet<N>&& bitSet)
+  : BitSet<N>(bitSet)
+  {
+  }
+
   // No data members (non-virtual destructor)
 };
 
index cea55f3..196ab60 100644 (file)
 #include <dali/devel-api/adaptor-framework/proxy-accessible.h>
 #include <dali/devel-api/adaptor-framework/window-devel.h>
 #include <dali/devel-api/atspi-interfaces/accessible.h>
+#include <dali/devel-api/atspi-interfaces/action.h>
+#include <dali/devel-api/atspi-interfaces/application.h>
 #include <dali/devel-api/atspi-interfaces/collection.h>
 #include <dali/devel-api/atspi-interfaces/component.h>
+#include <dali/devel-api/atspi-interfaces/editable-text.h>
+#include <dali/devel-api/atspi-interfaces/hyperlink.h>
+#include <dali/devel-api/atspi-interfaces/hypertext.h>
+#include <dali/devel-api/atspi-interfaces/selection.h>
+#include <dali/devel-api/atspi-interfaces/text.h>
+#include <dali/devel-api/atspi-interfaces/value.h>
 #include <dali/internal/adaptor/common/adaptor-impl.h>
 #include <dali/public-api/dali-adaptor-common.h>
 
@@ -185,6 +193,99 @@ std::string Accessible::GetRoleName() const
   return std::string{it->second};
 }
 
+AtspiInterfaces Accessible::GetInterfaces() const
+{
+  if(!mInterfaces)
+  {
+    mInterfaces = DoGetInterfaces();
+    DALI_ASSERT_DEBUG(mInterfaces); // There has to be at least AtspiInterface::ACCESSIBLE
+  }
+
+  return mInterfaces;
+}
+
+std::vector<std::string> Accessible::GetInterfacesAsStrings() const
+{
+  std::vector<std::string> ret;
+  AtspiInterfaces          interfaces = GetInterfaces();
+
+  for(std::size_t i = 0u; i < static_cast<std::size_t>(AtspiInterface::MAX_COUNT); ++i)
+  {
+    auto interface = static_cast<AtspiInterface>(i);
+
+    if(interfaces[interface])
+    {
+      auto name = GetInterfaceName(interface);
+
+      DALI_ASSERT_DEBUG(!name.empty());
+      ret.emplace_back(std::move(name));
+    }
+  }
+
+  return ret;
+}
+
+AtspiInterfaces Accessible::DoGetInterfaces() const
+{
+  AtspiInterfaces interfaces;
+
+  interfaces[AtspiInterface::ACCESSIBLE]    = true;
+  interfaces[AtspiInterface::ACTION]        = dynamic_cast<const Action*>(this);
+  interfaces[AtspiInterface::APPLICATION]   = dynamic_cast<const Application*>(this);
+  interfaces[AtspiInterface::COLLECTION]    = dynamic_cast<const Collection*>(this);
+  interfaces[AtspiInterface::COMPONENT]     = dynamic_cast<const Component*>(this);
+  interfaces[AtspiInterface::EDITABLE_TEXT] = dynamic_cast<const EditableText*>(this);
+  interfaces[AtspiInterface::HYPERLINK]     = dynamic_cast<const Hyperlink*>(this);
+  interfaces[AtspiInterface::HYPERTEXT]     = dynamic_cast<const Hypertext*>(this);
+  interfaces[AtspiInterface::SELECTION]     = dynamic_cast<const Selection*>(this);
+  interfaces[AtspiInterface::TEXT]          = dynamic_cast<const Text*>(this);
+  interfaces[AtspiInterface::VALUE]         = dynamic_cast<const Value*>(this);
+
+  return interfaces;
+}
+
+std::string Accessible::GetInterfaceName(AtspiInterface interface)
+{
+  static const std::unordered_map<AtspiInterface, std::string_view> interfaceMap{
+    {AtspiInterface::ACCESSIBLE, "org.a11y.atspi.Accessible"},
+    {AtspiInterface::ACTION, "org.a11y.atspi.Action"},
+    {AtspiInterface::APPLICATION, "org.a11y.atspi.Application"},
+    {AtspiInterface::CACHE, "org.a11y.atspi.Cache"},
+    {AtspiInterface::COLLECTION, "org.a11y.atspi.Collection"},
+    {AtspiInterface::COMPONENT, "org.a11y.atspi.Component"},
+    {AtspiInterface::DEVICE_EVENT_CONTROLLER, "org.a11y.atspi.DeviceEventController"},
+    {AtspiInterface::DEVICE_EVENT_LISTENER, "org.a11y.atspi.DeviceEventListener"},
+    {AtspiInterface::DOCUMENT, "org.a11y.atspi.Document"},
+    {AtspiInterface::EDITABLE_TEXT, "org.a11y.atspi.EditableText"},
+    {AtspiInterface::EVENT_DOCUMENT, "org.a11y.atspi.Event.Document"},
+    {AtspiInterface::EVENT_FOCUS, "org.a11y.atspi.Event.Focus"},
+    {AtspiInterface::EVENT_KEYBOARD, "org.a11y.atspi.Event.Keyboard"},
+    {AtspiInterface::EVENT_MOUSE, "org.a11y.atspi.Event.Mouse"},
+    {AtspiInterface::EVENT_OBJECT, "org.a11y.atspi.Event.Object"},
+    {AtspiInterface::EVENT_TERMINAL, "org.a11y.atspi.Event.Terminal"},
+    {AtspiInterface::EVENT_WINDOW, "org.a11y.atspi.Event.Window"},
+    {AtspiInterface::HYPERLINK, "org.a11y.atspi.Hyperlink"},
+    {AtspiInterface::HYPERTEXT, "org.a11y.atspi.Hypertext"},
+    {AtspiInterface::IMAGE, "org.a11y.atspi.Image"},
+    {AtspiInterface::REGISTRY, "org.a11y.atspi.Registry"},
+    {AtspiInterface::SELECTION, "org.a11y.atspi.Selection"},
+    {AtspiInterface::SOCKET, "org.a11y.atspi.Socket"},
+    {AtspiInterface::TABLE, "org.a11y.atspi.Table"},
+    {AtspiInterface::TABLE_CELL, "org.a11y.atspi.TableCell"},
+    {AtspiInterface::TEXT, "org.a11y.atspi.Text"},
+    {AtspiInterface::VALUE, "org.a11y.atspi.Value"},
+  };
+
+  auto it = interfaceMap.find(interface);
+
+  if(it == interfaceMap.end())
+  {
+    return {};
+  }
+
+  return std::string{it->second};
+}
+
 Dali::Actor Accessible::GetCurrentlyHighlightedActor()
 {
   return IsUp() ? Bridge::GetCurrentBridge()->mData->mCurrentlyHighlightedActor : Dali::Actor{};
index ef54cd3..1142576 100644 (file)
@@ -428,10 +428,77 @@ enum class ReadingInfoType
   MAX_COUNT\r
 };\r
 \r
+/**\r
+ * @brief Enumeration of all AT-SPI interfaces.\r
+ *\r
+ * @see Dali::Accessibility::Accessible::GetInterfaceName()\r
+ * @see Dali::Accessibility::AtspiInterfaceType\r
+ */\r
+enum class AtspiInterface\r
+{\r
+  ACCESSIBLE,\r
+  ACTION,\r
+  APPLICATION,\r
+  CACHE,\r
+  COLLECTION,\r
+  COMPONENT,\r
+  DEVICE_EVENT_CONTROLLER,\r
+  DEVICE_EVENT_LISTENER,\r
+  DOCUMENT,\r
+  EDITABLE_TEXT,\r
+  EVENT_DOCUMENT,\r
+  EVENT_FOCUS,\r
+  EVENT_KEYBOARD,\r
+  EVENT_MOUSE,\r
+  EVENT_OBJECT,\r
+  EVENT_TERMINAL,\r
+  EVENT_WINDOW,\r
+  HYPERLINK,\r
+  HYPERTEXT,\r
+  IMAGE,\r
+  REGISTRY,\r
+  SELECTION,\r
+  SOCKET,\r
+  TABLE,\r
+  TABLE_CELL,\r
+  TEXT,\r
+  VALUE,\r
+  MAX_COUNT\r
+};\r
+\r
+using AtspiInterfaces  = EnumBitSet<AtspiInterface, AtspiInterface::MAX_COUNT>;\r
 using ReadingInfoTypes = EnumBitSet<ReadingInfoType, ReadingInfoType::MAX_COUNT>;\r
 using States           = EnumBitSet<State, State::MAX_COUNT>;\r
 using Attributes       = std::unordered_map<std::string, std::string>;\r
 \r
+namespace Internal\r
+{\r
+/*\r
+ * AT-SPI interfaces exposed as native C++ types should specialize this like so:\r
+ *\r
+ * template<>\r
+ * struct AtspiInterfaceTypeHelper<AtspiInterface::ACCESSIBLE>\r
+ * {\r
+ *   using Type = Dali::Accessibility::Accessible;\r
+ * };\r
+ */\r
+template<AtspiInterface I>\r
+struct AtspiInterfaceTypeHelper; // no default definition\r
+\r
+} // namespace Internal\r
+\r
+/**\r
+ * @brief Resolves to the native C++ type that represents the given AT-SPI interface.\r
+ *\r
+ * For example, @code AtspiInterfaceType<AtspiInterface::ACCESSIBLE> @endcode is the same as\r
+ * @code Dali::Accessibility::Accessible @endcode. Not all AT-SPI interfaces have native C++\r
+ * representations (in which case, such an expression will not compile).\r
+ *\r
+ * @tparam I Enumeration value indicating the requested AT-SPI interface.\r
+ */\r
+template<AtspiInterface I>\r
+using AtspiInterfaceType = typename Internal::AtspiInterfaceTypeHelper<I>::Type;\r
+\r
 /**\r
  * @brief Class representing unique object address on accessibility bus\r
  * @see Dali::Accessibility::Accessible::GetAddress\r
index 0eb7794..b0b3ba1 100644 (file)
@@ -336,9 +336,26 @@ public:
   /**
    * @brief Gets all implemented interfaces.
    *
-   * @return The collection of strings with implemented interfaces
+   * Override DoGetInterfaces() to customize the return value of this method.
+   *
+   * @return The collection of implemented interfaces
+   *
+   * @see DoGetInterfaces()
+   */
+  AtspiInterfaces GetInterfaces() const;
+
+  /**
+   * @brief Gets all implemented interfaces.
+   *
+   * Converts all interfaces returned by GetInterfaces() to their DBus names
+   * using GetInterfaceName().
+   *
+   * @return The collection of names of implemented interfaces
+   *
+   * @see GetInterfaces()
+   * @see GetInterfaceName()
    */
-  std::vector<std::string> GetInterfaces() const;
+  std::vector<std::string> GetInterfacesAsStrings() const;
 
   /**
    * @brief Checks if object is on root level.
@@ -358,6 +375,20 @@ protected:
   Accessible&                   operator=(Accessible&&) = delete;
   std::shared_ptr<Bridge::Data> GetBridgeData() const;
 
+  /**
+   * @brief Returns the collection of AT-SPI interfaces implemented by this Accessible.
+   *
+   * This method is called only once and its return value is cached. The default implementation
+   * uses dynamic_cast to determine which interfaces are implemented. Override this if you
+   * conceptually provide fewer interfaces than dynamic_cast can see.
+   *
+   * @return The collection of implemented interfaces
+   *
+   * @see GetInterfaces()
+   * @see GetInterfaceName()
+   */
+  virtual AtspiInterfaces DoGetInterfaces() const;
+
 public:
   /**
    * @brief Gets the highlight actor.
@@ -412,14 +443,52 @@ public:
    */
   static Accessible* Get(Dali::Actor actor, bool isRoot = false);
 
+  /**
+   * @brief Obtains the DBus interface name for the specified AT-SPI interface.
+   *
+   * @param interface AT-SPI interface identifier (e.g. AtspiInterface::ACCESSIBLE)
+   * @return AT-SPI interface name (e.g. "org.a11y.atspi.Accessible")
+   */
+  static std::string GetInterfaceName(AtspiInterface interface);
+
+  /**
+   * @brief Downcasts an Accessible pointer to an AT-SPI interface pointer.
+   *
+   * @tparam I Desired AT-SPI interface
+   *
+   * @param obj Object to cast.
+   *
+   * @return Pointer to an AT-SPI interface or null if the interface is not implemented.
+   */
+  template<AtspiInterface I>
+  static AtspiInterfaceType<I>* DownCast(Accessible* obj)
+  {
+    if(!obj || !obj->GetInterfaces()[I])
+    {
+      return nullptr;
+    }
+
+    return dynamic_cast<AtspiInterfaceType<I>*>(obj);
+  }
+
 private:
   friend class Bridge;
 
   mutable std::weak_ptr<Bridge::Data> mBridgeData;
+  mutable AtspiInterfaces             mInterfaces;
   bool                                mIsOnRootLevel = false;
 
 }; // Accessible class
 
+namespace Internal
+{
+template<>
+struct AtspiInterfaceTypeHelper<AtspiInterface::ACCESSIBLE>
+{
+  using Type = Accessible;
+};
+} // namespace Internal
+
 } // namespace Dali::Accessibility
 
 #endif // DALI_ADAPTOR_ATSPI_ACCESSIBLE_H
index b3d9717..b168f63 100644 (file)
@@ -93,8 +93,32 @@ public:
    * @return true on success, false otherwise
    */
   virtual bool DoAction(const std::string& name) = 0;
+
+  /**
+   * @brief Downcasts an Accessible to an Action.
+   *
+   * @param obj The Accessible
+   * @return An Action or null
+   *
+   * @see Dali::Accessibility::Accessible::DownCast()
+   */
+  static inline Action* DownCast(Accessible* obj);
 };
 
+namespace Internal
+{
+template<>
+struct AtspiInterfaceTypeHelper<AtspiInterface::ACTION>
+{
+  using Type = Action;
+};
+} // namespace Internal
+
+inline Action* Action::DownCast(Accessible* obj)
+{
+  return Accessible::DownCast<AtspiInterface::ACTION>(obj);
+}
+
 } // namespace Dali::Accessibility
 
 #endif // DALI_ADAPTOR_ATSPI_ACTION_H
index 5e37f6b..44b26ba 100644 (file)
@@ -48,8 +48,32 @@ public:
    * @return String with version
    */
   virtual std::string GetVersion() const = 0;
+
+  /**
+   * @brief Downcasts an Accessible to an Application.
+   *
+   * @param obj The Accessible
+   * @return An Application or null
+   *
+   * @see Dali::Accessibility::Accessible::DownCast()
+   */
+  static inline Application* DownCast(Accessible* obj);
 };
 
+namespace Internal
+{
+template<>
+struct AtspiInterfaceTypeHelper<AtspiInterface::APPLICATION>
+{
+  using Type = Application;
+};
+} // namespace Internal
+
+inline Application* Application::DownCast(Accessible* obj)
+{
+  return Accessible::DownCast<AtspiInterface::APPLICATION>(obj);
+}
+
 } // namespace Dali::Accessibility
 
 #endif // DALI_ADAPTOR_ATSPI_APPLICATION_H
index 6452854..7a84079 100644 (file)
@@ -25,13 +25,36 @@ namespace Dali::Accessibility
 /**
  * @brief Interface enabling advanced quering of accessibility objects.
  *
- * @note since all mathods can be implemented inside bridge,
- * none methods have to be overrided
+ * @note Since all methods can be implemented inside bridge,
+ * no methods have to be overriden.
  */
 class DALI_ADAPTOR_API Collection : public virtual Accessible
 {
+  /**
+   * @brief Downcasts an Accessible to a Collection.
+   *
+   * @param obj The Accessible
+   * @return A Collection or null
+   *
+   * @see Dali::Accessibility::Accessible::DownCast()
+   */
+  static inline Collection* DownCast(Accessible* obj);
 };
 
+namespace Internal
+{
+template<>
+struct AtspiInterfaceTypeHelper<AtspiInterface::COLLECTION>
+{
+  using Type = Collection;
+};
+} // namespace Internal
+
+inline Collection* Collection::DownCast(Accessible* obj)
+{
+  return Accessible::DownCast<AtspiInterface::COLLECTION>(obj);
+}
+
 } // namespace Dali::Accessibility
 
 #endif // DALI_ADAPTOR_ATSPI_COLLECTION_H
index 1853313..682b97c 100644 (file)
@@ -131,8 +131,32 @@ public:
    * @see Dali::Accessibility::Point
    */
   virtual bool IsAccessibleContainingPoint(Point point, CoordinateType type) const;
+
+  /**
+   * @brief Downcasts an Accessible to a Component.
+   *
+   * @param obj The Accessible
+   * @return A Component or null
+   *
+   * @see Dali::Accessibility::Accessible::DownCast()
+   */
+  static inline Component* DownCast(Accessible* obj);
 };
 
+namespace Internal
+{
+template<>
+struct AtspiInterfaceTypeHelper<AtspiInterface::COMPONENT>
+{
+  using Type = Component;
+};
+} // namespace Internal
+
+inline Component* Component::DownCast(Accessible* obj)
+{
+  return Accessible::DownCast<AtspiInterface::COMPONENT>(obj);
+}
+
 } // namespace Dali::Accessibility
 
 #endif // DALI_ADAPTOR_ATSPI_COMPONENT_H
index 66c822e..1aa141f 100644 (file)
@@ -84,8 +84,32 @@ public:
    * @return true on success, false otherwise
    */
   virtual bool SetTextContents(std::string newContents) = 0;
+
+  /**
+   * @brief Downcasts an Accessible to an EditableText.
+   *
+   * @param obj The Accessible
+   * @return An EditableText or null
+   *
+   * @see Dali::Accessibility::Accessible::DownCast()
+   */
+  static inline EditableText* DownCast(Accessible* obj);
 };
 
+namespace Internal
+{
+template<>
+struct AtspiInterfaceTypeHelper<AtspiInterface::EDITABLE_TEXT>
+{
+  using Type = EditableText;
+};
+} // namespace Internal
+
+inline EditableText* EditableText::DownCast(Accessible* obj)
+{
+  return Accessible::DownCast<AtspiInterface::EDITABLE_TEXT>(obj);
+}
+
 } // namespace Dali::Accessibility
 
 #endif // DALI_ADAPTOR_ATSPI_EDITABLE_TEXT_H
index 5f7c8f5..aef9f4e 100644 (file)
@@ -77,8 +77,32 @@ public:
    * @return True if hyperlink object is valid, false otherwise
    */
   virtual bool IsValid() const = 0;
+
+  /**
+   * @brief Downcasts an Accessible to a Hyperlink.
+   *
+   * @param obj The Accessible
+   * @return A Hyperlink or null
+   *
+   * @see Dali::Accessibility::Accessible::DownCast()
+   */
+  static inline Hyperlink* DownCast(Accessible* obj);
 };
 
+namespace Internal
+{
+template<>
+struct AtspiInterfaceTypeHelper<AtspiInterface::HYPERLINK>
+{
+  using Type = Hyperlink;
+};
+} // namespace Internal
+
+inline Hyperlink* Hyperlink::DownCast(Accessible* obj)
+{
+  return Accessible::DownCast<AtspiInterface::HYPERLINK>(obj);
+}
+
 } // namespace Dali::Accessibility
 
 #endif // DALI_ADAPTOR_ATSPI_HYPERLINK_H
index e9b4deb..903aebc 100644 (file)
@@ -56,8 +56,32 @@ public:
    * @return The number of hyperlinks (zero if none or -1 if the number cannot be determined)
    */
   virtual std::int32_t GetLinkCount() const = 0;
+
+  /**
+   * @brief Downcasts an Accessible to a Hypertext.
+   *
+   * @param obj The Accessible
+   * @return A Hypertext or null
+   *
+   * @see Dali::Accessibility::Accessible::DownCast()
+   */
+  static inline Hypertext* DownCast(Accessible* obj);
 };
 
+namespace Internal
+{
+template<>
+struct AtspiInterfaceTypeHelper<AtspiInterface::HYPERTEXT>
+{
+  using Type = Hypertext;
+};
+} // namespace Internal
+
+inline Hypertext* Hypertext::DownCast(Accessible* obj)
+{
+  return Accessible::DownCast<AtspiInterface::HYPERTEXT>(obj);
+}
+
 } // namespace Dali::Accessibility
 
 #endif // DALI_ADAPTOR_ATSPI_HYPERTEXT_H
index 2aadd67..0ce68c4 100644 (file)
@@ -103,8 +103,32 @@ public:
    * @see Dali::Accessibility::Selection::DeselectSelectedChild
    */
   virtual bool DeselectChild(int childIndex) = 0;
+
+  /**
+   * @brief Downcasts an Accessible to a Selection.
+   *
+   * @param obj The Accessible
+   * @return A Selection or null
+   *
+   * @see Dali::Accessibility::Accessible::DownCast()
+   */
+  static inline Selection* DownCast(Accessible* obj);
 };
 
+namespace Internal
+{
+template<>
+struct AtspiInterfaceTypeHelper<AtspiInterface::SELECTION>
+{
+  using Type = Selection;
+};
+} // namespace Internal
+
+inline Selection* Selection::DownCast(Accessible* obj)
+{
+  return Accessible::DownCast<AtspiInterface::SELECTION>(obj);
+}
+
 } // namespace Dali::Accessibility
 
 #endif // DALI_ADAPTOR_ATSPI_SELECTION_H
index bd2981c..f632807 100644 (file)
@@ -118,8 +118,32 @@ public:
    * @remarks This method is `SetSelection` in DBus method.
    */
   virtual bool SetRangeOfSelection(std::size_t selectionIndex, std::size_t startOffset, std::size_t endOffset) = 0;
+
+  /**
+   * @brief Downcasts an Accessible to a Text.
+   *
+   * @param obj The Accessible
+   * @return A Text or null
+   *
+   * @see Dali::Accessibility::Accessible::DownCast()
+   */
+  static inline Text* DownCast(Accessible* obj);
 };
 
+namespace Internal
+{
+template<>
+struct AtspiInterfaceTypeHelper<AtspiInterface::TEXT>
+{
+  using Type = Text;
+};
+} // namespace Internal
+
+inline Text* Text::DownCast(Accessible* obj)
+{
+  return Accessible::DownCast<AtspiInterface::TEXT>(obj);
+}
+
 } // namespace Dali::Accessibility
 
 #endif // DALI_ADAPTOR_ATSPI_TEXT_H
index 350e2be..6c9a963 100644 (file)
@@ -64,7 +64,31 @@ public:
    * @return The lowest increment
   */
   virtual double GetMinimumIncrement() const = 0;
+
+  /**
+   * @brief Downcasts an Accessible to a Value.
+   *
+   * @param obj The Accessible
+   * @return A Value or null
+   *
+   * @see Dali::Accessibility::Accessible::DownCast()
+   */
+  static inline Value* DownCast(Accessible* obj);
+};
+
+namespace Internal
+{
+template<>
+struct AtspiInterfaceTypeHelper<AtspiInterface::VALUE>
+{
+  using Type = Value;
 };
+} // namespace Internal
+
+inline Value* Value::DownCast(Accessible* obj)
+{
+  return Accessible::DownCast<AtspiInterface::VALUE>(obj);
+}
 
 } // namespace Dali::Accessibility
 
index 4da5e3c..4f61522 100644 (file)
 #include <dali/internal/accessibility/bridge/dbus.h>
 #include <dali/public-api/dali-adaptor-common.h>
 
-/* DBus Interfaces */
+// DBus names
 
 #define A11yDbusName "org.a11y.Bus"
-#define A11yDbusPath "/org/a11y/bus"
 #define A11yDbusStatusInterface "org.a11y.Status"
 #define AtspiDbusNameRegistry "org.a11y.atspi.Registry"
+#define DirectReadingDBusName "org.tizen.ScreenReader"
+#define DirectReadingDBusInterface "org.tizen.DirectReading"
+
+// DBus paths
+
+#define A11yDbusPath "/org/a11y/bus"
+#define AtspiDbusPathCache "/org/a11y/atspi/cache"
+#define AtspiDbusPathDec "/org/a11y/atspi/registry/deviceeventcontroller"
 #define AtspiDbusPathRegistry "/org/a11y/atspi/registry"
-#define AtspiDbusInterfaceRegistry "org.a11y.atspi.Registry"
 #define AtspiDbusPathRoot "/org/a11y/atspi/accessible/root"
-#define AtspiDbusInterfaceSocket "org.a11y.atspi.Socket"
 #define AtspiPath "/org/a11y/atspi/accessible"
-#define AtspiDbusInterfaceAccessible "org.a11y.atspi.Accessible"
-#define AtspiDbusInterfaceAction "org.a11y.atspi.Action"
-#define AtspiDbusInterfaceApplication "org.a11y.atspi.Application"
-#define AtspiDbusInterfaceCache "org.a11y.atspi.Cache"
-#define AtspiDbusPathCache "/org/a11y/atspi/cache"
-#define AtspiDbusInterfaceCollection "org.a11y.atspi.Collection"
-#define AtspiDbusInterfaceComponent "org.a11y.atspi.Component"
-#define AtspiDbusInterfaceDocument "org.a11y.atspi.Document"
-#define AtspiDbusInterfaceEditableText "org.a11y.atspi.EditableText"
-#define AtspiDbusInterfaceEventKeyboard "org.a11y.atspi.Event.Keyboard"
-#define AtspiDbusInterfaceEventMouse "org.a11y.atspi.Event.Mouse"
-#define AtspiDbusInterfaceEventObject "org.a11y.atspi.Event.Object"
-#define AtspiDbusInterfaceHyperlink "org.a11y.atspi.Hyperlink"
-#define AtspiDbusInterfaceHypertext "org.a11y.atspi.Hypertext"
-#define AtspiDbusInterfaceImage "org.a11y.atspi.Image"
-#define AtspiDbusInterfaceSelection "org.a11y.atspi.Selection"
-#define AtspiDbusInterfaceTable "org.a11y.atspi.Table"
-#define AtspiDbusInterfaceTableCell "org.a11y.atspi.TableCell"
-#define AtspiDbusInterfaceText "org.a11y.atspi.Text"
-#define AtspiDbusInterfaceValue "org.a11y.atspi.Value"
-#define AtspiDbusInterfaceSocket "org.a11y.atspi.Socket"
-#define AtspiDbusInterfaceEventWindow "org.a11y.atspi.Event.Window"
-
-#define AtspiDbusPathDec "/org/a11y/atspi/registry/deviceeventcontroller"
-#define AtspiDbusInterfaceDec "org.a11y.atspi.DeviceEventController"
-#define AtspiDbusInterfaceDeviceEventListener "org.a11y.atspi.DeviceEventListener"
-
-#define DirectReadingDBusName "org.tizen.ScreenReader"
 #define DirectReadingDBusPath "/org/tizen/DirectReading"
-#define DirectReadingDBusInterface "org.tizen.DirectReading"
 
 struct ObjectPath;
 
index 26ec0aa..aaf2584 100644 (file)
 
 //INTERNAL INCLUDES
 #include <dali/devel-api/atspi-interfaces/accessible.h>
-#include <dali/devel-api/atspi-interfaces/action.h>
-#include <dali/devel-api/atspi-interfaces/application.h>
-#include <dali/devel-api/atspi-interfaces/collection.h>
-#include <dali/devel-api/atspi-interfaces/component.h>
-#include <dali/devel-api/atspi-interfaces/editable-text.h>
-#include <dali/devel-api/atspi-interfaces/hyperlink.h>
-#include <dali/devel-api/atspi-interfaces/hypertext.h>
-#include <dali/devel-api/atspi-interfaces/selection.h>
-#include <dali/devel-api/atspi-interfaces/text.h>
-#include <dali/devel-api/atspi-interfaces/value.h>
 #include <dali/devel-api/adaptor-framework/accessibility-bridge.h>
 #include <dali/internal/accessibility/bridge/accessibility-common.h>
 #include <third-party/libunibreak/linebreak.h>
 
 using namespace Dali::Accessibility;
 
-std::vector<std::string> Accessible::GetInterfaces() const
-{
-  std::vector<std::string> tmp;
-  tmp.push_back(AtspiDbusInterfaceAccessible);
-  if(dynamic_cast<const Collection*>(this))
-  {
-    tmp.push_back(AtspiDbusInterfaceCollection);
-  }
-  if(dynamic_cast<const Text*>(this))
-  {
-    tmp.push_back(AtspiDbusInterfaceText);
-  }
-  if(dynamic_cast<const EditableText*>(this))
-  {
-    tmp.push_back(AtspiDbusInterfaceEditableText);
-  }
-  if(dynamic_cast<const Value*>(this))
-  {
-    tmp.push_back(AtspiDbusInterfaceValue);
-  }
-  if(dynamic_cast<const Component*>(this))
-  {
-    tmp.push_back(AtspiDbusInterfaceComponent);
-  }
-  if(auto action = dynamic_cast<const Action*>(this))
-  {
-    if(action->GetActionCount() > 0)
-    {
-      tmp.push_back(AtspiDbusInterfaceAction);
-    }
-  }
-  if(dynamic_cast<const Selection*>(this))
-  {
-    tmp.push_back(AtspiDbusInterfaceSelection);
-  }
-  if(dynamic_cast<const Hypertext*>(this))
-  {
-    tmp.push_back(AtspiDbusInterfaceHypertext);
-  }
-  if(dynamic_cast<const Hyperlink*>(this))
-  {
-    tmp.push_back(AtspiDbusInterfaceHyperlink);
-  }
-  return tmp;
-}
-
 Accessible::Accessible()
 {
 }
index 59481d3..5f71a60 100644 (file)
@@ -400,7 +400,7 @@ BridgeAccessible::BridgeAccessible()
 
 void BridgeAccessible::RegisterInterfaces()
 {
-  DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceAccessible};
+  DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::ACCESSIBLE)};
   AddGetPropertyToInterface(desc, "ChildCount", &BridgeAccessible::GetChildCount);
   AddGetPropertyToInterface(desc, "Name", &BridgeAccessible::GetName);
   AddGetPropertyToInterface(desc, "Description", &BridgeAccessible::GetDescription);
@@ -410,7 +410,7 @@ void BridgeAccessible::RegisterInterfaces()
   AddFunctionToInterface(desc, "GetLocalizedRoleName", &BridgeAccessible::GetLocalizedRoleName);
   AddFunctionToInterface(desc, "GetState", &BridgeAccessible::GetStates);
   AddFunctionToInterface(desc, "GetAttributes", &BridgeAccessible::GetAttributes);
-  AddFunctionToInterface(desc, "GetInterfaces", &BridgeAccessible::GetInterfaces);
+  AddFunctionToInterface(desc, "GetInterfaces", &BridgeAccessible::GetInterfacesAsStrings);
   AddFunctionToInterface(desc, "GetChildAtIndex", &BridgeAccessible::GetChildAtIndex);
   AddFunctionToInterface(desc, "GetChildren", &BridgeAccessible::GetChildren);
   AddFunctionToInterface(desc, "GetIndexInParent", &BridgeAccessible::GetIndexInParent);
@@ -423,6 +423,11 @@ void BridgeAccessible::RegisterInterfaces()
   mDbusServer.addInterface("/", desc, true);
 }
 
+Accessible* BridgeAccessible::FindSelf() const
+{
+  return FindCurrentObject();
+}
+
 Component* BridgeAccessible::GetObjectInRelation(Accessible* obj, RelationType relationType)
 {
   if(!obj)
@@ -513,7 +518,7 @@ BridgeAccessible::ReadingMaterialType BridgeAccessible::GetReadingMaterial()
   double minimumIncrement = 0.0;
   double maximumValue     = 0.0;
   double minimumValue     = 0.0;
-  auto*  valueInterface   = dynamic_cast<Dali::Accessibility::Value*>(self);
+  auto*  valueInterface   = Value::DownCast(self);
   if(valueInterface)
   {
     currentValue     = valueInterface->GetCurrent();
@@ -524,7 +529,7 @@ BridgeAccessible::ReadingMaterialType BridgeAccessible::GetReadingMaterial()
 
   int32_t firstSelectedChildIndex = -1;
   int32_t selectedChildCount      = 0;
-  auto*   selfSelectionInterface  = dynamic_cast<Dali::Accessibility::Selection*>(self);
+  auto*   selfSelectionInterface  = Selection::DownCast(self);
   if(selfSelectionInterface)
   {
     selectedChildCount      = selfSelectionInterface->GetSelectedChildrenCount();
@@ -558,7 +563,7 @@ BridgeAccessible::ReadingMaterialType BridgeAccessible::GetReadingMaterial()
     listChildrenCount = GetItemCountOfFirstDescendantContainer(self, Role::POPUP_MENU, Role::MENU_ITEM, false);
   }
 
-  auto*       textInterface         = dynamic_cast<Dali::Accessibility::Text*>(self);
+  auto*       textInterface         = Text::DownCast(self);
   std::string nameFromTextInterface = "";
   if(textInterface)
   {
@@ -578,7 +583,7 @@ BridgeAccessible::ReadingMaterialType BridgeAccessible::GetReadingMaterial()
   auto  parentChildCount         = parent ? static_cast<int32_t>(parent->GetChildCount()) : 0;
   auto  parentStateSet           = parent ? parent->GetStates() : States{};
   bool  isSelectedInParent       = false;
-  auto* parentSelectionInterface = dynamic_cast<Dali::Accessibility::Selection*>(parent);
+  auto* parentSelectionInterface = Selection::DownCast(parent);
   if(parentSelectionInterface)
   {
     isSelectedInParent = parentSelectionInterface->IsChildSelected(indexInParent);
@@ -1014,9 +1019,9 @@ DBus::ValueOrError<std::unordered_map<std::string, std::string>> BridgeAccessibl
   return attributes;
 }
 
-DBus::ValueOrError<std::vector<std::string>> BridgeAccessible::GetInterfaces()
+DBus::ValueOrError<std::vector<std::string>> BridgeAccessible::GetInterfacesAsStrings()
 {
-  return FindSelf()->GetInterfaces();
+  return FindSelf()->GetInterfacesAsStrings();
 }
 
 int BridgeAccessible::GetChildCount()
index 3ca2223..219c530 100644 (file)
@@ -45,6 +45,13 @@ protected:
    */
   void RegisterInterfaces();
 
+  /**
+   * @brief Returns the Accessible object of the currently executed DBus method call.
+   *
+   * @return The Accessible object
+   */
+  Dali::Accessibility::Accessible* FindSelf() const;
+
 public:
   /**
    * @brief Enumeration for NeighborSearchMode.
@@ -147,9 +154,9 @@ public:
   DBus::ValueOrError<std::unordered_map<std::string, std::string>> GetAttributes();
 
   /**
-   * @copydoc Dali::Accessibility::Accessible::GetInterfaces()
+   * @copydoc Dali::Accessibility::Accessible::GetInterfacesAsStrings()
    */
-  DBus::ValueOrError<std::vector<std::string>> GetInterfaces();
+  DBus::ValueOrError<std::vector<std::string>> GetInterfacesAsStrings();
 
   /**
    * @brief Gets Accessible object on which surface lies the point with given coordinates.
index 9db679f..90d1674 100644 (file)
 // CLASS HEADER
 #include <dali/internal/accessibility/bridge/bridge-action.h>
 
-// EXTERNAL INCLUDES
-#include <iostream>
-
 using namespace Dali::Accessibility;
 
 void BridgeAction::RegisterInterfaces()
 {
-  DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceAction};
+  DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::ACTION)};
 
   AddGetPropertyToInterface(desc, "NActions", &BridgeAction::GetActionCount);
 
@@ -40,14 +37,7 @@ void BridgeAction::RegisterInterfaces()
 
 Action* BridgeAction::FindSelf() const
 {
-  auto self = BridgeBase::FindSelf();
-  assert(self);
-  auto actionInterface = dynamic_cast<Action*>(self);
-  if(!actionInterface)
-  {
-    throw std::domain_error{"object " + self->GetAddress().ToString() + " doesn't have Action interface"};
-  }
-  return actionInterface;
+  return FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::ACTION>();
 }
 
 DBus::ValueOrError<std::string> BridgeAction::GetActionName(int32_t index)
index 00e5c19..9806bad 100644 (file)
@@ -25,7 +25,7 @@ using namespace Dali::Accessibility;
 
 void BridgeApplication::RegisterInterfaces()
 {
-  DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceApplication};
+  DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::APPLICATION)};
   AddGetPropertyToInterface(desc, "ToolkitName", &BridgeApplication::GetToolkitName);
   AddGetPropertyToInterface(desc, "Version", &BridgeApplication::GetVersion);
   mDbusServer.addInterface("/", desc, true);
@@ -33,14 +33,7 @@ void BridgeApplication::RegisterInterfaces()
 
 Application* BridgeApplication::FindSelf() const
 {
-  auto self = BridgeBase::FindSelf();
-  assert(self);
-  auto appInterface = dynamic_cast<Application*>(self);
-  if(!appInterface)
-  {
-    throw std::domain_error{"object " + self->GetAddress().ToString() + " doesn't have Application interface"};
-  }
-  return appInterface;
+  return FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::APPLICATION>();
 }
 
 std::string BridgeApplication::GetToolkitName()
index 8e4f805..983bbe3 100644 (file)
@@ -135,17 +135,17 @@ BridgeBase::ForceUpResult BridgeBase::ForceUp()
   mDbusServer     = {mConnectionPtr};
 
   {
-    DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceCache};
+    DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::CACHE)};
     AddFunctionToInterface(desc, "GetItems", &BridgeBase::GetItems);
     mDbusServer.addInterface(AtspiDbusPathCache, desc);
   }
   {
-    DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceApplication};
+    DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::APPLICATION)};
     AddGetSetPropertyToInterface(desc, "Id", &BridgeBase::GetId, &BridgeBase::SetId);
     mDbusServer.addInterface(AtspiPath, desc);
   }
 
-  mRegistry = {AtspiDbusNameRegistry, AtspiDbusPathRegistry, AtspiDbusInterfaceRegistry, mConnectionPtr};
+  mRegistry = {AtspiDbusNameRegistry, AtspiDbusPathRegistry, Accessible::GetInterfaceName(AtspiInterface::REGISTRY), mConnectionPtr};
 
   UpdateRegisteredEvents();
 
@@ -317,7 +317,7 @@ Accessible* BridgeBase::Find(const Address& ptr) const
   return Find(ptr.GetPath());
 }
 
-Accessible* BridgeBase::FindSelf() const
+Accessible* BridgeBase::FindCurrentObject() const
 {
   auto path = DBus::DBusServer::getCurrentObjectPath();
   auto size = strlen(AtspiPath);
@@ -385,7 +385,7 @@ auto BridgeBase::CreateCacheElement(Accessible* item) -> CacheElementType
     root->GetAddress(),
     parent ? parent->GetAddress() : Address{},
     children,
-    item->GetInterfaces(),
+    item->GetInterfacesAsStrings(),
     item->GetName(),
     item->GetRole(),
     item->GetDescription(),
index cdffa9e..5e1ffca 100644 (file)
@@ -425,14 +425,52 @@ public:
   /**
    * @brief Returns the target object of the currently executed DBus method call.
    *
-   * And any subclasses redefine `FindSelf` with a different return type as a convenient wrapper around dynamic_cast.
    * @return The Accessible object
    * @note When a DBus method is called on some object, this target object (`currentObject`) is temporarily saved by the bridge,
    * because DBus handles the invocation target separately from the method arguments.
    * We then use the saved object inside the 'glue' method (e.g. BridgeValue::GetMinimum)
    * to call the equivalent method on the respective C++ object (this could be ScrollBar::AccessibleImpl::GetMinimum in the example given).
    */
-  Dali::Accessibility::Accessible* FindSelf() const;
+  Dali::Accessibility::Accessible* FindCurrentObject() const;
+
+  /**
+   * @brief Returns the target object of the currently executed DBus method call.
+   *
+   * This method tries to downcast the return value of FindCurrentObject() to the requested type,
+   * issuing an error reply to the DBus caller if the requested type is not implemented. Whether
+   * a given type is implemented is decided based on the return value of Accessible::GetInterfaces()
+   * for the current object.
+   *
+   * @tparam I The requested AT-SPI interface
+   * @return The Accessible object (cast to a more derived type)
+   *
+   * @see FindCurrentObject()
+   * @see Dali::Accessibility::AtspiInterface
+   * @see Dali::Accessibility::AtspiInterfaceType
+   * @see Dali::Accessibility::Accessible::GetInterfaces()
+   */
+  template<Dali::Accessibility::AtspiInterface I>
+  auto* FindCurrentObjectWithInterface() const
+  {
+    using Type = Dali::Accessibility::AtspiInterfaceType<I>;
+
+    Type* result;
+    auto* currentObject = FindCurrentObject();
+    DALI_ASSERT_DEBUG(currentObject); // FindCurrentObject() throws domain_error
+
+    if(!(result = Dali::Accessibility::Accessible::DownCast<I>(currentObject)))
+    {
+      std::stringstream s;
+
+      s << "Object " << currentObject->GetAddress().ToString();
+      s << " does not implement ";
+      s << Dali::Accessibility::Accessible::GetInterfaceName(I);
+
+      throw std::domain_error{s.str()};
+    }
+
+    return result;
+  }
 
   /**
    * @copydoc Dali::Accessibility::Bridge::FindByPath()
index 413e23c..497863b 100644 (file)
@@ -20,7 +20,6 @@
 
 // EXTERNAL INCLUDES
 #include <algorithm>
-#include <iostream>
 #include <unordered_set>
 #include <vector>
 
@@ -46,21 +45,14 @@ enum class AtspiCollection
 
 void BridgeCollection::RegisterInterfaces()
 {
-  DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceCollection};
+  DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::COLLECTION)};
   AddFunctionToInterface(desc, "GetMatches", &BridgeCollection::GetMatches);
   mDbusServer.addInterface("/", desc, true);
 }
 
 Collection* BridgeCollection::FindSelf() const
 {
-  auto self = BridgeBase::FindSelf();
-  assert(self);
-  auto collectionInterface = dynamic_cast<Collection*>(self);
-  if(!collectionInterface)
-  {
-    throw std::domain_error{"object " + self->GetAddress().ToString() + " doesn't have Collection interface"};
-  }
-  return collectionInterface;
+  return FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::COLLECTION>();
 }
 
 /**
@@ -128,7 +120,7 @@ struct BridgeCollection::Comparer
     void Update(Accessible* obj)
     {
       mObject.clear();
-      for(auto& interface : obj->GetInterfaces())
+      for(auto& interface : obj->GetInterfacesAsStrings())
       {
         mObject.insert(std::move(interface));
       }
@@ -485,7 +477,7 @@ void BridgeCollection::VisitNodes(Accessible* obj, std::vector<Accessible*>& res
 DBus::ValueOrError<std::vector<Accessible*> > BridgeCollection::GetMatches(MatchRule rule, uint32_t sortBy, int32_t count, bool traverse)
 {
   std::vector<Accessible*> res;
-  auto                     self    = BridgeBase::FindSelf();
+  auto                     self    = BridgeBase::FindCurrentObject();
   auto                     matcher = Comparer{&rule};
   VisitNodes(self, res, matcher, count);
 
index 64694ca..2a297f5 100644 (file)
@@ -18,9 +18,6 @@
 // CLASS HEADER
 #include <dali/internal/accessibility/bridge/bridge-component.h>
 
-// EXTERNAL INCLUDES
-#include <iostream>
-
 #define DBUS_INTERFACE_PROPERTIES "org.freedesktop.DBus.Properties"
 
 using namespace Dali::Accessibility;
@@ -35,7 +32,7 @@ void BridgeComponent::RegisterInterfaces()
   // Screen Reader will call the methods with the exact names as specified in the AT-SPI Component interface:
   // https://gitlab.gnome.org/GNOME/at-spi2-core/-/blob/master/xml/Component.xml
 
-  DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceComponent};
+  DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::COMPONENT)};
   AddFunctionToInterface(desc, "Contains", &BridgeComponent::IsAccessibleContainingPoint);
   AddFunctionToInterface(desc, "GetAccessibleAtPoint", &BridgeComponent::GetAccessibleAtPoint);
   AddFunctionToInterface(desc, "GetExtents", &BridgeComponent::GetExtents);
@@ -52,14 +49,7 @@ void BridgeComponent::RegisterInterfaces()
 
 Component* BridgeComponent::FindSelf() const
 {
-  auto self = BridgeBase::FindSelf();
-  assert(self);
-  auto componentInterface = dynamic_cast<Component*>(self);
-  if(!componentInterface)
-  {
-    throw std::domain_error{"object " + self->GetAddress().ToString() + " doesn't have Component interface"};
-  }
-  return componentInterface;
+  return FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::COMPONENT>();
 }
 
 DBus::ValueOrError<bool> BridgeComponent::IsAccessibleContainingPoint(int32_t x, int32_t y, uint32_t coordType)
index 3de8dc5..034885a 100644 (file)
@@ -25,7 +25,7 @@ using namespace Dali::Accessibility;
 
 void BridgeEditableText::RegisterInterfaces()
 {
-  DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceEditableText};
+  DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::EDITABLE_TEXT)};
   AddFunctionToInterface(desc, "CopyText", &BridgeEditableText::CopyText);
   AddFunctionToInterface(desc, "CutText", &BridgeEditableText::CutText);
   AddFunctionToInterface(desc, "DeleteText", &BridgeEditableText::DeleteText);
@@ -37,14 +37,7 @@ void BridgeEditableText::RegisterInterfaces()
 
 EditableText* BridgeEditableText::FindSelf() const
 {
-  auto self = BridgeBase::FindSelf();
-  assert(self);
-  auto editableTextInterface = dynamic_cast<EditableText*>(self);
-  if(!editableTextInterface)
-  {
-    throw std::domain_error{"object " + self->GetAddress().ToString() + " doesn't have Text interface"};
-  }
-  return editableTextInterface;
+  return FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::EDITABLE_TEXT>();
 }
 
 DBus::ValueOrError<bool> BridgeEditableText::CopyText(int32_t startPosition, int32_t endPosition)
index 4395ff0..992d2cf 100644 (file)
@@ -25,7 +25,7 @@ using namespace Dali::Accessibility;
 
 void BridgeHyperlink::RegisterInterfaces()
 {
-  DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceHyperlink};
+  DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::HYPERLINK)};
   AddGetPropertyToInterface(desc, "NAnchors", &BridgeHyperlink::GetAnchorCount);
   AddGetPropertyToInterface(desc, "StartIndex", &BridgeHyperlink::GetStartIndex);
   AddGetPropertyToInterface(desc, "EndIndex", &BridgeHyperlink::GetEndIndex);
@@ -37,14 +37,7 @@ void BridgeHyperlink::RegisterInterfaces()
 
 Hyperlink* BridgeHyperlink::FindSelf() const
 {
-  auto self = BridgeBase::FindSelf();
-  assert(self);
-  auto hyperlinkInterface = dynamic_cast<Hyperlink*>(self);
-  if(!hyperlinkInterface)
-  {
-    throw std::domain_error{"object " + self->GetAddress().ToString() + " doesn't have Hyperlink interface"};
-  }
-  return hyperlinkInterface;
+  return FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::HYPERLINK>();
 }
 
 DBus::ValueOrError<int32_t> BridgeHyperlink::GetEndIndex()
index 3a42d8d..b5f3b3b 100644 (file)
@@ -25,7 +25,7 @@ using namespace Dali::Accessibility;
 
 void BridgeHypertext::RegisterInterfaces()
 {
-  DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceHypertext};
+  DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::HYPERTEXT)};
   AddFunctionToInterface(desc, "GetNLinks", &BridgeHypertext::GetLinkCount);
   AddFunctionToInterface(desc, "GetLink", &BridgeHypertext::GetLink);
   AddFunctionToInterface(desc, "GetLinkIndex", &BridgeHypertext::GetLinkIndex);
@@ -34,14 +34,7 @@ void BridgeHypertext::RegisterInterfaces()
 
 Hypertext* BridgeHypertext::FindSelf() const
 {
-  auto self = BridgeBase::FindSelf();
-  assert(self);
-  auto hypertextInterface = dynamic_cast<Hypertext*>(self);
-  if(!hypertextInterface)
-  {
-    throw std::domain_error{"object " + self->GetAddress().ToString() + " doesn't have Hypertext interface"};
-  }
-  return hypertextInterface;
+  return FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::HYPERTEXT>();
 }
 
 DBus::ValueOrError<int32_t> BridgeHypertext::GetLinkCount()
index 0d48895..e5bc0ca 100644 (file)
@@ -329,7 +329,7 @@ public:
 
     RegisterOnBridge(&mApplication);
 
-    mRegistryClient      = {AtspiDbusNameRegistry, AtspiDbusPathDec, AtspiDbusInterfaceDec, mConnectionPtr};
+    mRegistryClient      = {AtspiDbusNameRegistry, AtspiDbusPathDec, Accessible::GetInterfaceName(AtspiInterface::DEVICE_EVENT_CONTROLLER), mConnectionPtr};
     mDirectReadingClient = DBus::DBusClient{DirectReadingDBusName, DirectReadingDBusPath, DirectReadingDBusInterface, mConnectionPtr};
 
     mDirectReadingClient.addSignal<void(int32_t, std::string)>("ReadingStateChanged", [=](int32_t id, std::string readingState) {
@@ -344,7 +344,7 @@ public:
       }
     });
 
-    auto    proxy = DBus::DBusClient{AtspiDbusNameRegistry, AtspiDbusPathRoot, AtspiDbusInterfaceSocket, mConnectionPtr};
+    auto    proxy = DBus::DBusClient{AtspiDbusNameRegistry, AtspiDbusPathRoot, Accessible::GetInterfaceName(AtspiInterface::SOCKET), mConnectionPtr};
     Address root{"", "root"};
     auto    res = proxy.method<Address(Address)>("Embed").call(root);
     if(!res)
index 5a3847c..fc1834b 100644 (file)
@@ -41,7 +41,7 @@ BridgeObject::BridgeObject()
 
 void BridgeObject::RegisterInterfaces()
 {
-  // DBus::DBusInterfaceDescription desc{ AtspiDbusInterfaceEventObject };
+  // DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT)};
   // mStateChanged = addSignal<std::string, int, int, DBus::EldbusVariant<int>, Accessible*>(desc, "StateChanged");
   // mDbusServer.addInterface("/", desc, true);
 }
@@ -57,7 +57,7 @@ void BridgeObject::EmitActiveDescendantChanged(Accessible* obj, Accessible* chil
 
   mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<Address>, Address>(
     GetAccessiblePath(obj),
-    AtspiDbusInterfaceEventObject,
+    Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
     "ActiveDescendantChanged",
     "",
     index,
@@ -87,7 +87,7 @@ void BridgeObject::Emit(Accessible* obj, ObjectPropertyChangeEvent event)
   {
     mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
       GetAccessiblePath(obj),
-      AtspiDbusInterfaceEventObject,
+      Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
       "PropertyChange",
       std::string{eventName->second},
       0,
@@ -132,7 +132,7 @@ void BridgeObject::Emit(Accessible* obj, WindowEvent event, unsigned int detail)
   {
     mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
       GetAccessiblePath(obj),
-      AtspiDbusInterfaceEventWindow,
+      Accessible::GetInterfaceName(AtspiInterface::EVENT_WINDOW),
       std::string{eventName->second},
       "",
       detail,
@@ -204,7 +204,7 @@ void BridgeObject::EmitStateChanged(Accessible* obj, State state, int newValue,
   {
     mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
       GetAccessiblePath(obj),
-      AtspiDbusInterfaceEventObject,
+      Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
       "StateChanged",
       std::string{stateName->second},
       newValue,
@@ -227,7 +227,7 @@ void BridgeObject::EmitBoundsChanged(Accessible* obj, Dali::Rect<> rect)
   AddFilteredEvent(FilteredEvents::BOUNDS_CHANGED, obj, 1.0f, [=]() {
     mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<std::tuple<int32_t, int32_t, int32_t, int32_t> >, Address>(
       GetAccessiblePath(obj),
-      AtspiDbusInterfaceEventObject,
+      Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
       "BoundsChanged",
       "",
       0,
@@ -246,7 +246,7 @@ void BridgeObject::EmitCursorMoved(Accessible* obj, unsigned int cursorPosition)
 
   mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
     GetAccessiblePath(obj),
-    AtspiDbusInterfaceEventObject,
+    Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
     "TextCaretMoved",
     "",
     cursorPosition,
@@ -273,7 +273,7 @@ void BridgeObject::EmitTextChanged(Accessible* obj, TextChangedState state, unsi
   {
     mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<std::string>, Address>(
       GetAccessiblePath(obj),
-      AtspiDbusInterfaceEventObject,
+      Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
       "TextChanged",
       std::string{stateName->second},
       position,
@@ -292,7 +292,7 @@ void BridgeObject::EmitMovedOutOfScreen(Accessible* obj, ScreenRelativeMoveType
 
   mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
     GetAccessiblePath(obj),
-    AtspiDbusInterfaceEventObject,
+    Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
     "MoveOuted",
     "",
     static_cast<int>(type),
index 942bd97..0713670 100644 (file)
@@ -22,7 +22,7 @@ using namespace Dali::Accessibility;
 
 void BridgeSelection::RegisterInterfaces()
 {
-  DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceSelection};
+  DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::SELECTION)};
   AddGetPropertyToInterface(desc, "NSelectedChildren", &BridgeSelection::GetSelectedChildrenCount);
   AddFunctionToInterface(desc, "GetSelectedChild", &BridgeSelection::GetSelectedChild);
   AddFunctionToInterface(desc, "SelectChild", &BridgeSelection::SelectChild);
@@ -36,14 +36,7 @@ void BridgeSelection::RegisterInterfaces()
 
 Selection* BridgeSelection::FindSelf() const
 {
-  auto self = BridgeBase::FindSelf();
-  assert(self);
-  auto selectionInterface = dynamic_cast<Selection*>(self);
-  if(!selectionInterface)
-  {
-    throw std::domain_error{"object " + self->GetAddress().ToString() + " doesn't have Selection interface"};
-  }
-  return selectionInterface;
+  return FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::SELECTION>();
 }
 
 DBus::ValueOrError<int32_t> BridgeSelection::GetSelectedChildrenCount()
index 1ba0073..aec0ada 100644 (file)
@@ -29,7 +29,7 @@ void BridgeText::RegisterInterfaces()
   // Screen Reader will call the methods with the exact names as specified in the AT-SPI Text interface:
   // https://gitlab.gnome.org/GNOME/at-spi2-core/-/blob/master/xml/Text.xml
 
-  DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceText};
+  DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::TEXT)};
   AddFunctionToInterface(desc, "GetText", &BridgeText::GetText);
   AddGetPropertyToInterface(desc, "CharacterCount", &BridgeText::GetCharacterCount);
   AddGetPropertyToInterface(desc, "CaretOffset", &BridgeText::GetCursorOffset);
@@ -43,14 +43,7 @@ void BridgeText::RegisterInterfaces()
 
 Text* BridgeText::FindSelf() const
 {
-  auto self = BridgeBase::FindSelf();
-  assert(self);
-  auto textInterface = dynamic_cast<Text*>(self);
-  if(!textInterface)
-  {
-    throw std::domain_error{"Object " + self->GetAddress().ToString() + " doesn't have Text interface"};
-  }
-  return textInterface;
+  return FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::TEXT>();
 }
 
 DBus::ValueOrError<std::string> BridgeText::GetText(int startOffset, int endOffset)
index 7f81a32..8ac9007 100644 (file)
@@ -18,9 +18,6 @@
 // CLASS HEADER
 #include <dali/internal/accessibility/bridge/bridge-value.h>
 
-// EXTERNAL INCLUDES
-#include <iostream>
-
 using namespace Dali::Accessibility;
 
 BridgeValue::BridgeValue()
@@ -29,7 +26,7 @@ BridgeValue::BridgeValue()
 
 void BridgeValue::RegisterInterfaces()
 {
-  DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceValue};
+  DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::VALUE)};
   AddGetSetPropertyToInterface(desc, "CurrentValue", &BridgeValue::GetCurrentValue, &BridgeValue::SetCurrentValue);
   AddGetPropertyToInterface(desc, "MaximumValue", &BridgeValue::GetMaximumValue);
   AddGetPropertyToInterface(desc, "MinimumIncrement", &BridgeValue::GetMinimumIncrement);
@@ -39,14 +36,7 @@ void BridgeValue::RegisterInterfaces()
 
 Value* BridgeValue::FindSelf() const
 {
-  auto self = BridgeBase::FindSelf();
-  assert(self);
-  auto valueInterface = dynamic_cast<Value*>(self);
-  if(!valueInterface)
-  {
-    throw std::domain_error{"object " + self->GetAddress().ToString() + " doesn't have Value interface"};
-  }
-  return valueInterface;
+  return FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::VALUE>();
 }
 
 double BridgeValue::GetCurrentValue()