virtual ~Bridge() = default;
/**
+ * @brief Adds the accessible object associated with given actorId to the brige.
+ *
+ * @param[in] actorId The actorId assosiated with the accessible
+ * @param[in] accessible The accessible object
+ *
+ * @return true if given accessible is added to the bridge
+ */
+ virtual bool AddAccessible(uint32_t actorId, std::shared_ptr<Accessible> accessible) = 0;
+
+ /**
+ * @brief Removed the accessible object associated with given actorId from the brige.
+ */
+ virtual void RemoveAccessible(uint32_t actorId) = 0;
+
+ /**
+ * @brief Gets the accessible object associated with given actor from the brige.
+ */
+ virtual std::shared_ptr<Accessible> GetAccessible(Actor actor) const = 0;
+
+ /**
+ * @brief Returns true if GetChildren should include hidden objects; false otherwise.
+ */
+ virtual bool ShouldIncludeHidden() const = 0;
+
+ /**
* @brief Gets bus name which bridge is initialized on.
*
* @return The bus name
*
* @param[in] object The accessible object
*/
- virtual void RegisterDefaultLabel(Accessible* object) = 0;
+ virtual void RegisterDefaultLabel(std::shared_ptr<Accessible> object) = 0;
/**
* @brief Removes object from the stack of "default label" sourcing objects.
*
* @param[in] object The accessible object
*/
- virtual void UnregisterDefaultLabel(Accessible* object) = 0;
+ virtual void UnregisterDefaultLabel(std::shared_ptr<Accessible> object) = 0;
/**
* @brief Gets the top-most object from the stack of "default label" sourcing objects.
* Following strings are valid values for "default_label" attribute: "enabled", "disabled".
* Any other value will be interpreted as "enabled".
*/
- virtual Accessible* GetDefaultLabel(Accessible* root) const = 0;
+ virtual Accessible* GetDefaultLabel(Accessible* root) = 0;
/**
* @brief Sets name of current application which will be visible on accessibility bus.
* @param[in] newValue Whether the state value is changed to new value or not.
* @param[in] reserved Reserved. (Currently, this argument is not implemented in dali)
**/
- virtual void EmitStateChanged(Accessible* obj, State state, int newValue, int reserved = 0) = 0;
+ virtual void EmitStateChanged(std::shared_ptr<Accessible> obj, State state, int newValue, int reserved = 0) = 0;
/**
* @brief Emits window event on at-spi bus.
* @param[in] obj The accessible object
* @param[in] event Property changed event
**/
- virtual void Emit(Accessible* obj, ObjectPropertyChangeEvent event) = 0;
+ virtual void Emit(std::shared_ptr<Accessible> obj, ObjectPropertyChangeEvent event) = 0;
/**
* @brief Emits bounds-changed event on at-spi bus.
* @param[in] obj The accessible object
* @param[in] rect The rectangle for changed bounds
**/
- virtual void EmitBoundsChanged(Accessible* obj, Rect<> rect) = 0;
-
- /**
- * @brief Emits key event on at-spi bus.
- *
- * Screen-reader might receive this event and reply, that given keycode is consumed. In that case
- * further processing of the keycode should be ignored.
- *
- * @param[in] type Key event type
- * @param[in] keyCode Key code
- * @param[in] keyName Key name
- * @param[in] timeStamp Time stamp
- * @param[in] isText Whether it's text or not
- * @return Whether this event is consumed or not
- **/
- virtual Consumed Emit(KeyEventType type, unsigned int keyCode, const std::string& keyName, unsigned int timeStamp, bool isText) = 0;
+ virtual void EmitBoundsChanged(std::shared_ptr<Accessible> obj, Rect<> rect) = 0;
/**
* @brief Reads given text by screen reader
#include <dali/public-api/actors/actor.h>
#include <dali/public-api/actors/layer.h>
#include <dali/public-api/object/base-object.h>
-#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>
class AdaptorAccessible : public ActorAccessible
{
private:
- std::unique_ptr<TriggerEventInterface> mRenderNotification = nullptr;
-
-protected:
- bool mRoot = false;
+ std::unique_ptr<TriggerEventInterface> mRenderNotification{nullptr};
+ bool mRoot{false};
public:
AdaptorAccessible(Dali::Actor actor, bool isRoot)
}; // AdaptorAccessible
-using AdaptorAccessiblesType = std::map<const Dali::RefObject*, std::unique_ptr<AdaptorAccessible>>;
-
-// Save RefObject from an Actor in Accessible::Get()
-AdaptorAccessiblesType gAdaptorAccessibles;
+using ConvertingResult = std::pair<std::shared_ptr<Accessible>, bool>;
-std::function<Accessible*(Dali::Actor)> convertingFunctor = [](Dali::Actor) -> Accessible* {
- return nullptr;
+std::function<ConvertingResult(Dali::Actor)> convertingFunctor = [](Dali::Actor) -> ConvertingResult {
+ return {nullptr, true};
};
-ObjectRegistry objectRegistry;
} // namespace
-void Accessible::SetObjectRegistry(ObjectRegistry registry)
-{
- objectRegistry = registry;
- objectRegistry.ObjectDestroyedSignal().Connect([](const Dali::RefObject* obj) {
- gAdaptorAccessibles.erase(obj);
- });
-}
-
-void Accessible::RegisterExternalAccessibleGetter(std::function<Accessible*(Dali::Actor)> functor)
+void Accessible::RegisterExternalAccessibleGetter(std::function<ConvertingResult(Dali::Actor)> functor)
{
convertingFunctor = functor;
}
-Accessible* Accessible::Get(Dali::Actor actor)
+std::shared_ptr<Accessible> Accessible::GetOwningPtr(Dali::Actor actor)
{
if(!actor)
{
return nullptr;
}
- auto accessible = convertingFunctor(actor);
- if(!accessible)
+ auto bridge = Bridge::GetCurrentBridge();
+
+ // Try finding exsiting accessible object.
+ auto accessible = bridge->GetAccessible(actor);
+ if(accessible)
{
- auto pair = gAdaptorAccessibles.emplace(&actor.GetBaseObject(), nullptr);
- if(pair.second)
+ return accessible;
+ }
+
+ // No acessible object created, let's create one.
+ auto result = convertingFunctor(actor);
+ accessible = result.first;
+ const bool creationEnabled = result.second;
+ if(!accessible && creationEnabled)
+ {
+ bool isRoot = false;
+ Dali::Integration::Scene scene = Dali::Integration::Scene::Get(actor);
+ if(scene)
{
- bool isRoot = false;
- Dali::Integration::Scene scene = Dali::Integration::Scene::Get(actor);
- if(scene)
+ isRoot = (actor == scene.GetRootLayer());
+ }
+ accessible = std::make_shared<AdaptorAccessible>(actor, isRoot);
+ }
+
+ if(accessible)
+ {
+ uint32_t actorId = actor.GetProperty<int>(Dali::Actor::Property::ID);
+ if(bridge->AddAccessible(actorId, accessible))
+ {
+ if(auto actorAccesible = std::dynamic_pointer_cast<ActorAccessible>(accessible))
{
- isRoot = (actor == scene.GetRootLayer());
+ actorAccesible->StartObservingDestruction();
}
- pair.first->second.reset(new AdaptorAccessible(actor, isRoot));
}
- accessible = pair.first->second.get();
+ else
+ {
+ return nullptr;
+ }
}
return accessible;
}
+
+Accessible* Accessible::Get(Dali::Actor actor)
+{
+ auto accessible = Accessible::GetOwningPtr(actor);
+ return accessible ? accessible.get() : nullptr;
+}
\ No newline at end of file
};\r
\r
/**\r
- * @brief Enumeration describing type of key event\r
- * @see Adaptor::AccessibilityObserver::OnAccessibleKeyEvent\r
- */\r
-enum class KeyEventType\r
-{\r
- KEY_PRESSED,\r
- KEY_RELEASED,\r
-};\r
-\r
-/**\r
* @brief Enumeration with human readable values describing state of event\r
* @see Dali::Accessibility::Bridge::Emit\r
*/\r
namespace Dali::Accessibility
{
ActorAccessible::ActorAccessible(Actor actor)
-: mSelf(actor),
- mChildrenDirty{true} // to trigger the initial UpdateChildren()
+: Dali::BaseObjectObserver(actor),
+ mSelf(actor),
+ mChildrenDirty{true}, // to trigger the initial UpdateChildren()
+ mActorId{static_cast<uint32_t>(actor.GetProperty<int>(Dali::Actor::Property::ID))}
{
// Select the right overload manually because Connect(this, &OnChildrenChanged) is ambiguous.
void (ActorAccessible::*handler)(Dali::Actor) = &ActorAccessible::OnChildrenChanged;
Dali::DevelActor::ChildOrderChangedSignal(actor).Connect(this, handler);
}
+void ActorAccessible::ObjectDestroyed()
+{
+ Bridge::GetCurrentBridge()->RemoveAccessible(mActorId);
+}
+
std::string ActorAccessible::GetName() const
{
return Self().GetProperty<std::string>(Dali::Actor::Property::NAME);
mChildren.clear();
DoGetChildren(mChildren);
+ const bool shouldIncludeHidden = Bridge::GetCurrentBridge()->ShouldIncludeHidden();
+
// Erase-remove idiom
// TODO (C++20): Replace with std::erase_if
- auto it = std::remove_if(mChildren.begin(), mChildren.end(), [](const Accessible* child) {
- return !child || child->IsHidden();
+ auto it = std::remove_if(mChildren.begin(), mChildren.end(), [shouldIncludeHidden](const Accessible* child) {
+ return !child || (!shouldIncludeHidden && child->IsHidden());
});
mChildren.erase(it, mChildren.end());
mChildren.shrink_to_fit();
*/
// EXTERNAL INCLUDES
+#include <dali/devel-api/object/base-object-observer.h>
#include <dali/public-api/actors/actor.h>
#include <dali/public-api/object/weak-handle.h>
#include <dali/public-api/signals/connection-tracker.h>
class DALI_ADAPTOR_API ActorAccessible : public virtual Accessible,
public virtual Collection,
public virtual Component,
- public Dali::ConnectionTracker
+ public Dali::ConnectionTracker,
+ public Dali::BaseObjectObserver
{
public:
ActorAccessible() = delete;
ActorAccessible(Actor actor);
+ // BaseObjectObserver::ObjectDestroyed
+ void ObjectDestroyed() override;
+
/**
* @copydoc Dali::Accessibility::Accessible::GetName()
*/
Dali::WeakHandle<Dali::Actor> mSelf;
std::vector<Accessible*> mChildren;
bool mChildrenDirty;
+ const uint32_t mActorId;
};
} // namespace Dali::Accessibility
/**
* @brief Basic interface implemented by all accessibility objects.
*/
-class DALI_ADAPTOR_API Accessible
+class DALI_ADAPTOR_API Accessible : public std::enable_shared_from_this<Accessible>
{
public:
virtual ~Accessible() noexcept;
static void SetCurrentlyHighlightedActor(Dali::Actor actor);
/**
- * @brief Sets ObjectRegistry.
- *
- * @param[in] registry ObjectRegistry instance
- */
- static void SetObjectRegistry(ObjectRegistry registry);
-
- /**
* @brief The method registers functor resposible for converting Actor into Accessible.
* @param functor The returning Accessible handle from Actor object
*/
- static void RegisterExternalAccessibleGetter(std::function<Accessible*(Dali::Actor)> functor);
+ static void RegisterExternalAccessibleGetter(std::function<std::pair<std::shared_ptr<Accessible>, bool>(Dali::Actor)> functor);
/**
* @brief Acquires Accessible object from Actor object.
*
* @param[in] actor Actor object
*
- * @return The handle to Accessible object
+ * @return The raw pointer to Accessible object
*/
static Accessible* Get(Dali::Actor actor);
/**
+ * @brief Acquires Accessible object from Actor object.
+ *
+ * @param[in] actor Actor object
+ *
+ * @return The owning pointer to Accessible object
+ */
+ static std::shared_ptr<Accessible> GetOwningPtr(Dali::Actor actor);
+
+ /**
* @brief Obtains the DBus interface name for the specified AT-SPI interface.
*
* @param interface AT-SPI interface identifier (e.g. AtspiInterface::ACCESSIBLE)
#define DALI_ADAPTOR_ATSPI_APPLICATION_H
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
virtual std::string GetVersion() const = 0;
/**
+ * @brief Gets include_hidden flag currently set on the application.
+ *
+ * @return true is include_hidden is set; false otherwise.
+ */
+ virtual bool GetIncludeHidden() const = 0;
+
+ /**
+ * @brief Sets include_hidden flag to the application.
+ *
+ * @return true is include_hidden flag is updated; false otherwise.
+ */
+ virtual bool SetIncludeHidden(bool includeHidden) = 0;
+
+ /**
* @brief Downcasts an Accessible to an Application.
*
* @param obj The Accessible
if(shouldEmit)
{
- bridgeData->mBridge->EmitStateChanged(this, state, newValue, reserved);
+ bridgeData->mBridge->EmitStateChanged(shared_from_this(), state, newValue, reserved);
}
}
}
{
if(auto bridgeData = GetBridgeData())
{
- bridgeData->mBridge->Emit(this, event);
+ bridgeData->mBridge->Emit(shared_from_this(), event);
}
}
{
if(auto bridgeData = GetBridgeData())
{
- bridgeData->mBridge->EmitBoundsChanged(this, rect);
+ bridgeData->mBridge->EmitBoundsChanged(shared_from_this(), rect);
}
}
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::APPLICATION)};
AddGetPropertyToInterface(desc, "ToolkitName", &BridgeApplication::GetToolkitName);
AddGetPropertyToInterface(desc, "Version", &BridgeApplication::GetVersion);
+ AddFunctionToInterface(desc, "GetIncludeHidden", &BridgeApplication::GetIncludeHidden);
+ AddFunctionToInterface(desc, "SetIncludeHidden", &BridgeApplication::SetIncludeHidden);
mDbusServer.addInterface("/", desc, true);
}
{
return FindSelf()->GetVersion();
}
+
+DBus::ValueOrError<bool> BridgeApplication::GetIncludeHidden()
+{
+ return FindSelf()->GetIncludeHidden();
+}
+
+DBus::ValueOrError<void> BridgeApplication::SetIncludeHidden(bool includeHidden)
+{
+ if(FindSelf()->SetIncludeHidden(includeHidden))
+ {
+ NotifyIncludeHiddenChanged();
+ }
+ return {};
+}
#define DALI_INTERNAL_ACCESSIBILITY_BRIDGE_APPLICATION_H
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
Dali::Accessibility::Application* FindSelf() const;
+private:
+ virtual void NotifyIncludeHiddenChanged(){};
+
public:
/**
* @brief Gets name of graphic user interface framework used by an application.
* @return String with version
*/
std::string GetVersion();
+
+ /**
+ * @brief Gets include_hidden flag currently set on the application.
+ *
+ * @return true is include_hidden is set; false otherwise.
+ */
+ DBus::ValueOrError<bool> GetIncludeHidden();
+
+ /**
+ * @brief Sets include_hidden flag to the application.
+ */
+ DBus::ValueOrError<void> SetIncludeHidden(bool includeHidden);
};
#endif // DALI_INTERNAL_ACCESSIBILITY_BRIDGE_APPLICATION_H
{
// Remove entries for objects which no longer exist
mDefaultLabels.remove_if([](const DefaultLabelType& label) {
- return !label.first.GetBaseHandle(); // Check window's weak handle
- // TODO: Once Accessible becomes a handle type, check its weak handle here as well
+ // Check 1) window's weak handle; 2) accessible's ref object
+ return !label.first.GetBaseHandle() || label.second.expired();
});
}
-void BridgeBase::RegisterDefaultLabel(Accessible* object)
+void BridgeBase::RegisterDefaultLabel(std::shared_ptr<Accessible> object)
{
CompressDefaultLabels();
- Dali::WeakHandle<Dali::Window> window = GetWindow(object);
+ Dali::WeakHandle<Dali::Window> window = GetWindow(object.get());
if(!window.GetBaseHandle()) // true also if `object` is null
{
DALI_LOG_ERROR("Cannot register default label: object does not belong to any window");
return;
}
- auto it = std::find_if(mDefaultLabels.begin(), mDefaultLabels.end(), [object](const DefaultLabelType& label) {
- return object == label.second;
+ auto it = std::find_if(mDefaultLabels.begin(), mDefaultLabels.end(), [&object](const DefaultLabelType& label) {
+ auto labelPtr = label.second.lock();
+ return labelPtr && object == labelPtr;
});
if(it == mDefaultLabels.end())
}
}
-void BridgeBase::UnregisterDefaultLabel(Accessible* object)
+void BridgeBase::UnregisterDefaultLabel(std::shared_ptr<Accessible> object)
{
CompressDefaultLabels();
- mDefaultLabels.remove_if([object](const DefaultLabelType& label) {
- return object == label.second;
+ mDefaultLabels.remove_if([&object](const DefaultLabelType& label) {
+ auto labelPtr = label.second.lock();
+ return labelPtr && object == labelPtr;
});
}
-Accessible* BridgeBase::GetDefaultLabel(Accessible* root) const
+Accessible* BridgeBase::GetDefaultLabel(Accessible* root)
{
+ CompressDefaultLabels();
+
Dali::WeakHandle<Dali::Window> window = GetWindow(root);
if(!window.GetBaseHandle())
{
return window == label.first;
});
- return (it == mDefaultLabels.rend()) ? root : it->second;
+ Accessible* rawPtr = root;
+ if(it != mDefaultLabels.rend())
+ {
+ if(auto labelPtr = it->second.lock())
+ {
+ rawPtr = labelPtr.get();
+ }
+ }
+
+ return rawPtr;
}
std::string BridgeBase::StripPrefix(const std::string& path)
}
auto it = mData->mKnownObjects.find(static_cast<Accessible*>(accessible));
- if(it == mData->mKnownObjects.end() || (*it)->IsHidden())
+ if(it == mData->mKnownObjects.end() || (!mApplication.mShouldIncludeHidden && (*it)->IsHidden()))
{
throw std::domain_error{"unknown object '" + path + "'"};
}
std::string mName;
std::string mToolkitName{"dali"};
bool mIsEmbedded{false};
+ bool mShouldIncludeHidden{false};
std::string GetName() const override
{
return std::to_string(Dali::ADAPTOR_MAJOR_VERSION) + "." + std::to_string(Dali::ADAPTOR_MINOR_VERSION);
}
+ bool GetIncludeHidden() const override
+ {
+ return mShouldIncludeHidden;
+ }
+
+ bool SetIncludeHidden(bool includeHidden) override
+ {
+ if(mShouldIncludeHidden != includeHidden)
+ {
+ mShouldIncludeHidden = includeHidden;
+ return true;
+ }
+ return false;
+ }
+
// Socket
Dali::Accessibility::Address Embed(Dali::Accessibility::Address plug) override
/**
* @copydoc Dali::Accessibility::Bridge::RegisterDefaultLabel()
*/
- void RegisterDefaultLabel(Dali::Accessibility::Accessible* object) override;
+ void RegisterDefaultLabel(std::shared_ptr<Dali::Accessibility::Accessible> object) override;
/**
* @copydoc Dali::Accessibility::Bridge::UnregisterDefaultLabel()
*/
- void UnregisterDefaultLabel(Dali::Accessibility::Accessible* object) override;
+ void UnregisterDefaultLabel(std::shared_ptr<Dali::Accessibility::Accessible> object) override;
/**
* @copydoc Dali::Accessibility::Bridge::GetDefaultLabel()
*/
- Dali::Accessibility::Accessible* GetDefaultLabel(Dali::Accessibility::Accessible* root) const override;
+ Dali::Accessibility::Accessible* GetDefaultLabel(Dali::Accessibility::Accessible* root) override;
/**
* @copydoc Dali::Accessibility::Bridge::GetApplication()
protected:
// We use a weak handle in order not to keep a window alive forever if someone forgets to UnregisterDefaultLabel()
- using DefaultLabelType = std::pair<Dali::WeakHandle<Dali::Window>, Dali::Accessibility::Accessible*>;
+ using DefaultLabelType = std::pair<Dali::WeakHandle<Dali::Window>, std::weak_ptr<Dali::Accessibility::Accessible>>;
using DefaultLabelsType = std::list<DefaultLabelType>;
mutable ApplicationAccessible mApplication;
#include <map>
// INTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/actor-accessible.h>
#include <dali/devel-api/adaptor-framework/environment-variable.h>
#include <dali/devel-api/adaptor-framework/window-devel.h>
#include <dali/internal/accessibility/bridge/accessibility-common.h>
public BridgeTable,
public BridgeTableCell
{
- DBus::DBusClient mAccessibilityStatusClient;
- DBus::DBusClient mRegistryClient;
- DBus::DBusClient mDirectReadingClient;
- bool mIsScreenReaderEnabled = false;
- bool mIsEnabled = false;
- bool mIsApplicationRunning = false;
- std::map<int32_t, std::function<void(std::string)>> mDirectReadingCallbacks;
- Dali::Actor mHighlightedActor;
- std::function<void(Dali::Actor)> mHighlightClearAction;
- Dali::CallbackBase* mIdleCallback = NULL;
- Dali::Timer mInitializeTimer;
- Dali::Timer mReadIsEnabledTimer;
- Dali::Timer mReadScreenReaderEnabledTimer;
- Dali::Timer mForceUpTimer;
- std::string mPreferredBusName;
+ DBus::DBusClient mAccessibilityStatusClient{};
+ DBus::DBusClient mRegistryClient{};
+ DBus::DBusClient mDirectReadingClient{};
+ bool mIsScreenReaderEnabled{false};
+ bool mIsEnabled{false};
+ bool mIsApplicationRunning{false};
+ std::unordered_map<int32_t, std::function<void(std::string)>> mDirectReadingCallbacks{};
+ Dali::Actor mHighlightedActor;
+ std::function<void(Dali::Actor)> mHighlightClearAction{nullptr};
+ Dali::CallbackBase* mIdleCallback{};
+ Dali::Timer mInitializeTimer;
+ Dali::Timer mReadIsEnabledTimer;
+ Dali::Timer mReadScreenReaderEnabledTimer;
+ Dali::Timer mForceUpTimer;
+ std::string mPreferredBusName;
+ std::map<uint32_t, std::shared_ptr<Accessible>> mAccessibles; // Actor.ID to Accessible map
public:
BridgeImpl()
}
/**
- * @copydoc Dali::Accessibility::Bridge::Emit()
+ * @copydoc Dali::Accessibility::Bridge::AddAccessible()
*/
- Consumed Emit(KeyEventType type, unsigned int keyCode, const std::string& keyName, unsigned int timeStamp, bool isText) override
+ bool AddAccessible(uint32_t actorId, std::shared_ptr<Accessible> accessible) override
{
- if(!IsUp())
- {
- return Consumed::NO;
- }
+ mAccessibles[actorId] = std::move(accessible);
+ return true;
+ }
+
+ /**
+ * @copydoc Dali::Accessibility::Bridge::RemoveAccessible()
+ */
+ void RemoveAccessible(uint32_t actorId) override
+ {
+ mAccessibles.erase(actorId);
+ }
- unsigned int keyType = 0;
+ /**
+ * @copydoc Dali::Accessibility::Bridge::GetAccessible()
+ */
+ std::shared_ptr<Accessible> GetAccessible(Dali::Actor actor) const override
+ {
+ uint32_t actorId = actor.GetProperty<int>(Dali::Actor::Property::ID);
+ auto iter = mAccessibles.find(actorId);
+ return iter != mAccessibles.end() ? iter->second : nullptr;
+ }
- switch(type)
+ /**
+ * @copydoc Dali::Accessibility::Bridge::ShouldIncludeHidden()
+ */
+ bool ShouldIncludeHidden() const override
+ {
+ return mApplication.mShouldIncludeHidden;
+ }
+
+ void NotifyIncludeHiddenChanged() override
+ {
+ for(const auto& iter : mAccessibles)
{
- case KeyEventType::KEY_PRESSED:
+ const auto& accessible = iter.second;
+ if(accessible->IsHidden())
{
- keyType = 0;
- break;
- }
- case KeyEventType::KEY_RELEASED:
- {
- keyType = 1;
- break;
- }
- default:
- {
- return Consumed::NO;
+ auto* parent = dynamic_cast<ActorAccessible*>(accessible->GetParent());
+ if(parent)
+ {
+ parent->OnChildrenChanged();
+ }
}
}
-
- return Consumed::NO;
}
/**
{"", "root"});
}
-void BridgeObject::Emit(Accessible* obj, ObjectPropertyChangeEvent event)
+void BridgeObject::Emit(std::shared_ptr<Accessible> obj, ObjectPropertyChangeEvent event)
{
static const std::map<ObjectPropertyChangeEvent, std::string_view> eventMap{
{ObjectPropertyChangeEvent::NAME, "accessible-name"},
if(eventName != eventMap.end())
{
mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
- GetAccessiblePath(obj),
+ GetAccessiblePath(obj.get()),
Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
"PropertyChange",
std::string{eventName->second},
}
}
-void BridgeObject::EmitStateChanged(Accessible* obj, State state, int newValue, int reserved)
+void BridgeObject::EmitStateChanged(std::shared_ptr<Accessible> obj, State state, int newValue, int reserved)
{
static const std::map<State, std::string_view> stateMap{
{State::INVALID, "invalid"},
if(stateName != stateMap.end())
{
mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<int>, Address>(
- GetAccessiblePath(obj),
+ GetAccessiblePath(obj.get()),
Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
"StateChanged",
std::string{stateName->second},
}
}
-void BridgeObject::EmitBoundsChanged(Accessible* obj, Dali::Rect<> rect)
+void BridgeObject::EmitBoundsChanged(std::shared_ptr<Accessible> obj, Dali::Rect<> rect)
{
if(!IsUp() || !IsBoundsChangedEventAllowed || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::BOUNDS_CHANGED])
{
return;
}
- DBus::EldbusVariant<std::tuple<int32_t, int32_t, int32_t, int32_t> > tmp{
- std::tuple<int32_t, int32_t, int32_t, int32_t>{rect.x, rect.y, rect.width, rect.height}};
-
- AddCoalescableMessage(CoalescableMessages::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),
- Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
- "BoundsChanged",
- "",
- 0,
- 0,
- tmp,
- {"", "root"});
+ AddCoalescableMessage(CoalescableMessages::BOUNDS_CHANGED, obj.get(), 1.0f, [=, weakObj = std::weak_ptr<Accessible>(obj), rect = std::move(rect)]() {
+ if(auto accessible = weakObj.lock())
+ {
+ DBus::EldbusVariant<std::tuple<int32_t, int32_t, int32_t, int32_t> > tmp{
+ std::tuple<int32_t, int32_t, int32_t, int32_t>{rect.x, rect.y, rect.width, rect.height}};
+
+ mDbusServer.emit2<std::string, int, int, DBus::EldbusVariant<std::tuple<int32_t, int32_t, int32_t, int32_t> >, Address>(
+ GetAccessiblePath(accessible.get()),
+ Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
+ "BoundsChanged",
+ "",
+ 0,
+ 0,
+ tmp,
+ {"", "root"});
+ }
});
}
/**
* @copydoc Dali::Accessibility::Bridge::EmitStateChanged()
*/
- void EmitStateChanged(Dali::Accessibility::Accessible* obj, Dali::Accessibility::State state, int newValue, int reserved) override;
+ void EmitStateChanged(std::shared_ptr<Dali::Accessibility::Accessible> obj, Dali::Accessibility::State state, int newValue, int reserved) override;
/**
* @copydoc Dali::Accessibility::Bridge::Emit()
/**
* @copydoc Dali::Accessibility::Bridge::Emit()
*/
- void Emit(Dali::Accessibility::Accessible* obj, Dali::Accessibility::ObjectPropertyChangeEvent event) override;
+ void Emit(std::shared_ptr<Dali::Accessibility::Accessible> obj, Dali::Accessibility::ObjectPropertyChangeEvent event) override;
/**
* @copydoc Dali::Accessibility::Bridge::EmitBoundsChanged()
*/
- void EmitBoundsChanged(Dali::Accessibility::Accessible* obj, Dali::Rect<> rect) override;
+ void EmitBoundsChanged(std::shared_ptr<Dali::Accessibility::Accessible> obj, Dali::Rect<> rect) override;
/**
* @copydoc Dali::Accessibility::Bridge::EmitMovedOutOfScreen()
{
}
- void RegisterDefaultLabel(Accessibility::Accessible* object) override
+ void RegisterDefaultLabel(std::shared_ptr<Accessibility::Accessible> object) override
{
}
- void UnregisterDefaultLabel(Accessibility::Accessible* object) override
+ void UnregisterDefaultLabel(std::shared_ptr<Accessibility::Accessible> object) override
{
}
- Dali::Accessibility::Accessible* GetDefaultLabel(Dali::Accessibility::Accessible* root) const override
+ Dali::Accessibility::Accessible* GetDefaultLabel(Dali::Accessibility::Accessible* root) override
{
return nullptr;
}
{
}
- void EmitStateChanged(Accessibility::Accessible* obj, Accessibility::State state, int newValue, int reserved) override
+ void EmitStateChanged(std::shared_ptr<Accessibility::Accessible> obj, Accessibility::State state, int newValue, int reserved) override
{
}
{
}
- void Emit(Accessibility::Accessible* obj, Accessibility::ObjectPropertyChangeEvent event) override
+ void Emit(std::shared_ptr<Accessibility::Accessible> obj, Accessibility::ObjectPropertyChangeEvent event) override
{
}
- void EmitBoundsChanged(Accessibility::Accessible* obj, Rect<> rect) override
+ void EmitBoundsChanged(std::shared_ptr<Accessibility::Accessible> obj, Rect<> rect) override
{
}
- Accessibility::Consumed Emit(Accessibility::KeyEventType type, unsigned int keyCode, const std::string& keyName, unsigned int timeStamp, bool isText) override
- {
- return Accessibility::Consumed::YES;
- }
-
void Say(const std::string& text, bool discardable, std::function<void(std::string)> callback) override
{
}
void SetPreferredBusName(std::string_view preferredBusName) override
{
}
+
+ bool AddAccessible(uint32_t actorId, std::shared_ptr<Accessible> accessible) override
+ {
+ return false;
+ }
+
+ void RemoveAccessible(uint32_t actorId) override
+ {
+ }
+
+ std::shared_ptr<Accessible> GetAccessible(Actor actor) const override
+ {
+ return nullptr;
+ };
+
+ bool ShouldIncludeHidden() const override
+ {
+ return false;
+ }
};
} // namespace Dali::Accessibility
mConfigurationManager = Utils::MakeUnique<ConfigurationManager>(systemCachePath, mGraphics.get(), mThreadController);
}
-void Adaptor::AccessibilityObserver::OnAccessibleKeyEvent(const Dali::KeyEvent& event)
-{
- Accessibility::KeyEventType type;
- if(event.GetState() == Dali::KeyEvent::DOWN)
- {
- type = Accessibility::KeyEventType::KEY_PRESSED;
- }
- else if(event.GetState() == Dali::KeyEvent::UP)
- {
- type = Accessibility::KeyEventType::KEY_RELEASED;
- }
- else
- {
- return;
- }
- Dali::Accessibility::Bridge::GetCurrentBridge()->Emit(type, event.GetKeyCode(), event.GetKeyName(), event.GetTime(), !event.GetKeyString().empty());
-}
-
Adaptor::~Adaptor()
{
Accessibility::Bridge::GetCurrentBridge()->Terminate();
auto bridge = Accessibility::Bridge::GetCurrentBridge();
bridge->SetApplicationName(appName);
bridge->Initialize();
- Dali::Stage::GetCurrent().KeyEventSignal().Connect(&mAccessibilityObserver, &AccessibilityObserver::OnAccessibleKeyEvent);
Dali::Internal::Adaptor::SceneHolder* defaultWindow = mWindows.front();
std::unique_ptr<Integration::AddOnManager> mAddOnManager; ///< Pointer to the addon manager
- class AccessibilityObserver : public ConnectionTracker
- {
- public:
- void OnAccessibleKeyEvent(const Dali::KeyEvent& event);
- };
- AccessibilityObserver mAccessibilityObserver;
-
public:
inline static Adaptor& GetImplementation(Dali::Adaptor& adaptor)
{
DALI_TRACE_BEGIN(gTraceFilter, "DALI_APP_ADAPTOR_START");
mAdaptor->Start();
DALI_TRACE_END(gTraceFilter, "DALI_APP_ADAPTOR_START");
- Accessibility::Accessible::SetObjectRegistry(mAdaptor->GetObjectRegistry());
if(!mStylesheet.empty())
{
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <dali/internal/system/tizen-wayland/widget-controller-tizen.h>
// EXTERNAL INCLUDES
-#include <dali/public-api/actors/layer.h>
#include <bundle.h>
+#include <dali/public-api/actors/layer.h>
#include <unistd.h>
#include <widget_base.h>
void WidgetImplTizen::SetInformation(Dali::Window window, const std::string& widgetId)
{
- mWindow = window;
+ mWindow = window;
mWidgetId = widgetId;
auto bridge = Accessibility::Bridge::GetCurrentBridge();
bridge->SetPreferredBusName(preferredBusName);
// Widget should not send window events (which could narrow down the navigation context)
- auto& suppressedEvents = Accessibility::Accessible::Get(window.GetRootLayer())->GetSuppressedEvents();
- suppressedEvents[Accessibility::AtspiEvent::STATE_CHANGED] = true;
- suppressedEvents[Accessibility::AtspiEvent::WINDOW_CHANGED] = true;
+ if(auto accessible = Accessibility::Accessible::Get(window.GetRootLayer()))
+ {
+ auto& suppressedEvents = accessible->GetSuppressedEvents();
+ suppressedEvents[Accessibility::AtspiEvent::STATE_CHANGED] = true;
+ suppressedEvents[Accessibility::AtspiEvent::WINDOW_CHANGED] = true;
+ }
}
Dali::Window WidgetImplTizen::GetWindow() const
/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
{
if(mScene)
{
- auto bridge = Accessibility::Bridge::GetCurrentBridge();
- auto rootLayer = mScene.GetRootLayer();
- auto accessible = Accessibility::Accessible::Get(rootLayer);
- bridge->RemoveTopLevelWindow(accessible);
- // Related to multi-window case. This is called for default window and non-default window, but it is effective for non-default window.
- bridge->Emit(accessible, Accessibility::WindowEvent::DESTROY);
+ auto bridge = Accessibility::Bridge::GetCurrentBridge();
+ auto rootLayer = mScene.GetRootLayer();
+ if(auto accessible = Accessibility::Accessible::Get(rootLayer))
+ {
+ bridge->RemoveTopLevelWindow(accessible);
+ // Related to multi-window case. This is called for default window and non-default window, but it is effective for non-default window.
+ bridge->Emit(accessible, Accessibility::WindowEvent::DESTROY);
+ }
}
if(DALI_LIKELY(mAdaptor))
mSurface->SetFullSwapNextFrame();
- Dali::Accessibility::Accessible::Get(mScene.GetRootLayer())->EmitBoundsChanged(Dali::Rect<>(oldRect.x, oldRect.y, size.GetWidth(), size.GetHeight()));
+ if(auto accessible = Accessibility::Accessible::Get(mScene.GetRootLayer()))
+ {
+ accessible->EmitBoundsChanged(Dali::Rect<>(oldRect.x, oldRect.y, size.GetWidth(), size.GetHeight()));
+ }
}
Dali::Window::WindowSize Window::GetSize() const
mSurface->SetFullSwapNextFrame();
- Dali::Accessibility::Accessible::Get(mScene.GetRootLayer())->EmitBoundsChanged(Dali::Rect<>(position.GetX(), position.GetY(), oldRect.width, oldRect.height));
+ if(auto accessible = Accessibility::Accessible::Get(mScene.GetRootLayer()))
+ {
+ accessible->EmitBoundsChanged(Dali::Rect<>(position.GetX(), position.GetY(), oldRect.width, oldRect.height));
+ }
}
Dali::Window::WindowPosition Window::GetPosition() const
mSurface->SetFullSwapNextFrame();
- Dali::Accessibility::Accessible::Get(mScene.GetRootLayer())->EmitBoundsChanged(Dali::Rect<>(positionSize.x, positionSize.y, positionSize.width, positionSize.height));
+ if(auto accessible = Accessibility::Accessible::Get(mScene.GetRootLayer()))
+ {
+ accessible->EmitBoundsChanged(Dali::Rect<>(positionSize.x, positionSize.y, positionSize.width, positionSize.height));
+ }
}
void Window::SetLayout(unsigned int numCols, unsigned int numRows, unsigned int column, unsigned int row, unsigned int colSpan, unsigned int rowSpan)
if(DALI_LIKELY(mScene))
{
- Dali::Accessibility::Accessible::Get(mScene.GetRootLayer())->EmitBoundsChanged(Dali::Rect<>(positionSize.x, positionSize.y, positionSize.width, positionSize.height));
+ if(auto accessible = Accessibility::Accessible::Get(mScene.GetRootLayer()))
+ {
+ accessible->EmitBoundsChanged(Dali::Rect<>(positionSize.x, positionSize.y, positionSize.width, positionSize.height));
+ }
}
}
void Window::OnAccessibilityEnabled()
{
- auto bridge = Accessibility::Bridge::GetCurrentBridge();
- auto rootLayer = mScene.GetRootLayer();
- auto accessible = Accessibility::Accessible::Get(rootLayer);
- bridge->AddTopLevelWindow(accessible);
-
+ auto bridge = Accessibility::Bridge::GetCurrentBridge();
+ auto rootLayer = mScene.GetRootLayer();
+ if(auto accessible = Accessibility::Accessible::Get(rootLayer))
+ {
+ bridge->AddTopLevelWindow(accessible);
+ }
DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), Accessibility is enabled\n", this, mNativeWindowId);
Dali::Window handle(this);
void Window::OnAccessibilityDisabled()
{
- auto bridge = Accessibility::Bridge::GetCurrentBridge();
- auto rootLayer = mScene.GetRootLayer();
- auto accessible = Accessibility::Accessible::Get(rootLayer);
- bridge->RemoveTopLevelWindow(accessible);
+ auto bridge = Accessibility::Bridge::GetCurrentBridge();
+ auto rootLayer = mScene.GetRootLayer();
+ if(auto accessible = Accessibility::Accessible::Get(rootLayer))
+ {
+ bridge->RemoveTopLevelWindow(accessible);
+ }
DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), Accessibility is disabled\n", this, mNativeWindowId);
}