#include <dali/public-api/object/object-registry.h>
#include <dali/public-api/object/type-info.h>
#include <dali/public-api/object/type-registry-helper.h>
+#include <map>
+#include <sstream>
#include <string_view>
-#include <unordered_map>
// INTERNAL INCLUDES
#include <dali/devel-api/adaptor-framework/accessibility-bridge.h>
#include <dali/devel-api/atspi-interfaces/hypertext.h>
#include <dali/devel-api/atspi-interfaces/selection.h>
#include <dali/devel-api/atspi-interfaces/socket.h>
+#include <dali/devel-api/atspi-interfaces/table.h>
+#include <dali/devel-api/atspi-interfaces/table-cell.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>
std::string Accessible::GetRoleName() const
{
- static const std::unordered_map<Role, std::string_view> roleMap{
+ static const std::map<Role, std::string_view> roleMap{
{Role::INVALID, "invalid"},
{Role::ACCELERATOR_LABEL, "accelerator label"},
{Role::ALERT, "alert"},
return std::string{it->second};
}
+void Accessible::UpdateAttributes(Attributes& attributes) const
+{
+ using MapType = std::map<ReadingInfoType, std::string_view>;
+
+ static const std::string readingInfoTypeKey = "reading_info_type";
+ static const char separator = '|';
+ static const MapType readingInfoTypeMap{
+ {ReadingInfoType::NAME, "name"},
+ {ReadingInfoType::ROLE, "role"},
+ {ReadingInfoType::DESCRIPTION, "description"},
+ {ReadingInfoType::STATE, "state"},
+ };
+
+ bool allEnabled = mReadingInfoTypes[ReadingInfoType::NAME]
+ && mReadingInfoTypes[ReadingInfoType::ROLE]
+ && mReadingInfoTypes[ReadingInfoType::DESCRIPTION]
+ && mReadingInfoTypes[ReadingInfoType::STATE];
+
+ if(DALI_LIKELY(allEnabled))
+ {
+ attributes.erase(readingInfoTypeKey);
+ return;
+ }
+
+ std::stringstream buf;
+ for(auto& item : readingInfoTypeMap)
+ {
+ if(mReadingInfoTypes[item.first])
+ {
+ if(buf.tellp()) // non-empty
+ {
+ buf << separator;
+ }
+
+ buf << item.second;
+ }
+ }
+
+ attributes.insert_or_assign(readingInfoTypeKey, buf.str());
+}
+
+const Attributes& Accessible::GetAttributes() const
+{
+ UpdateAttributes(mAttributes);
+
+ return mAttributes;
+}
+
+bool Accessible::SetAttribute(const std::string& key, const std::string& value)
+{
+ return mAttributes.insert_or_assign(key, value).second;
+}
+
+bool Accessible::UnsetAttribute(const std::string& key)
+{
+ return (mAttributes.erase(key) > 0);
+}
+
+void Accessible::ClearAttributes()
+{
+ mAttributes.clear();
+}
+
+ReadingInfoTypes Accessible::GetReadingInfoTypes() const
+{
+ return mReadingInfoTypes;
+}
+
+void Accessible::SetReadingInfoTypes(ReadingInfoTypes types)
+{
+ mReadingInfoTypes = types;
+}
+
AtspiInterfaces Accessible::GetInterfaces() const
{
if(!mInterfaces)
interfaces[AtspiInterface::HYPERTEXT] = dynamic_cast<const Hypertext*>(this);
interfaces[AtspiInterface::SELECTION] = dynamic_cast<const Selection*>(this);
interfaces[AtspiInterface::SOCKET] = dynamic_cast<const Socket*>(this);
+ interfaces[AtspiInterface::TABLE] = dynamic_cast<const Table*>(this);
+ interfaces[AtspiInterface::TABLE_CELL] = dynamic_cast<const TableCell*>(this);
interfaces[AtspiInterface::TEXT] = dynamic_cast<const Text*>(this);
interfaces[AtspiInterface::VALUE] = dynamic_cast<const Value*>(this);
std::string Accessible::GetInterfaceName(AtspiInterface interface)
{
- static const std::unordered_map<AtspiInterface, std::string_view> interfaceMap{
+ static const std::map<AtspiInterface, std::string_view> interfaceMap{
{AtspiInterface::ACCESSIBLE, "org.a11y.atspi.Accessible"},
{AtspiInterface::ACTION, "org.a11y.atspi.Action"},
{AtspiInterface::APPLICATION, "org.a11y.atspi.Application"},
{
class AdaptorAccessible : public ActorAccessible
{
+private:
+ std::unique_ptr<TriggerEventInterface> mRenderNotification = nullptr;
+
protected:
bool mRoot = false;
state[State::VISIBLE] = true;
state[State::ACTIVE] = visible;
}
- else
+ else if (GetParent())
{
auto parentState = GetParent()->GetStates();
state[State::SHOWING] = parentState[State::SHOWING];
state[State::VISIBLE] = parentState[State::VISIBLE];
}
+ else
+ {
+ state[State::SHOWING] = false;
+ state[State::VISIBLE] = false;
+ }
return state;
}
- Attributes GetAttributes() const override
+ void UpdateAttributes(Attributes& attributes) const override
{
- Attributes attributes;
+ static const std::string resIDKey = "resID";
- if(mRoot)
+ ActorAccessible::UpdateAttributes(attributes);
+
+ if(mRoot && attributes.find(resIDKey) == attributes.end())
{
Dali::Window window = Dali::DevelWindow::Get(Self());
Dali::Internal::Adaptor::Window& windowImpl = Dali::GetImplementation(window);
- attributes["resID"] = windowImpl.GetNativeResourceId();
- }
-
- Dali::TypeInfo type;
- Self().GetTypeInfo(type);
- attributes["class"] = type.GetName();
- return attributes;
+ attributes.emplace(resIDKey, windowImpl.GetNativeResourceId());
+ }
}
bool DoGesture(const GestureInfo& gestureInfo) override
{
return {};
}
+
+ void SetListenPostRender(bool enabled) override
+ {
+ if (!mRoot)
+ {
+ return;
+ }
+
+ auto window = Dali::DevelWindow::Get(Self());
+ Dali::Internal::Adaptor::Window& windowImpl = Dali::GetImplementation(window);
+
+ if(!mRenderNotification)
+ {
+ mRenderNotification = std::unique_ptr<TriggerEventInterface>(
+ TriggerEventFactory::CreateTriggerEvent(MakeCallback(this, &AdaptorAccessible::OnPostRender),
+ TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER));
+ }
+
+ if (enabled)
+ {
+ windowImpl.SetRenderNotification(mRenderNotification.get());
+ }
+ else
+ {
+ windowImpl.SetRenderNotification(nullptr);
+ }
+ }
+
+ void OnPostRender()
+ {
+ Accessibility::Bridge::GetCurrentBridge()->Emit(Accessibility::Accessible::Get(Self()), Accessibility::WindowEvent::POST_RENDER);
+ }
+
}; // AdaptorAccessible
-using AdaptorAccessiblesType = std::unordered_map<const Dali::RefObject*, std::unique_ptr<AdaptorAccessible> >;
+using AdaptorAccessiblesType = std::map<const Dali::RefObject*, std::unique_ptr<AdaptorAccessible>>;
// Save RefObject from an Actor in Accessible::Get()
AdaptorAccessiblesType gAdaptorAccessibles;
convertingFunctor = functor;
}
-Accessible* Accessible::Get(Dali::Actor actor, bool isRoot)
+Accessible* Accessible::Get(Dali::Actor actor)
{
if(!actor)
{
auto pair = gAdaptorAccessibles.emplace(&actor.GetBaseObject(), nullptr);
if(pair.second)
{
+ bool isRoot = false;
+ Dali::Integration::Scene scene = Dali::Integration::Scene::Get(actor);
+ if(scene)
+ {
+ isRoot = (actor == scene.GetRootLayer());
+ }
pair.first->second.reset(new AdaptorAccessible(actor, isRoot));
}
accessible = pair.first->second.get();