summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dali/devel-api/adaptor-framework/accessibility-bridge.h110
-rw-r--r--dali/devel-api/adaptor-framework/accessibility.cpp19
-rw-r--r--dali/devel-api/atspi-interfaces/accessible.h11
-rw-r--r--dali/internal/accessibility/bridge/accessible.cpp15
-rw-r--r--dali/internal/accessibility/bridge/bridge-accessible.cpp102
-rw-r--r--dali/internal/accessibility/bridge/bridge-accessible.h47
-rw-r--r--dali/internal/accessibility/bridge/bridge-action.cpp11
-rw-r--r--dali/internal/accessibility/bridge/bridge-application.cpp10
-rw-r--r--dali/internal/accessibility/bridge/bridge-base.cpp417
-rw-r--r--dali/internal/accessibility/bridge/bridge-base.h518
-rw-r--r--dali/internal/accessibility/bridge/bridge-collection.cpp13
-rw-r--r--dali/internal/accessibility/bridge/bridge-collection.h15
-rw-r--r--dali/internal/accessibility/bridge/bridge-component.cpp21
-rw-r--r--dali/internal/accessibility/bridge/bridge-component.h18
-rw-r--r--dali/internal/accessibility/bridge/bridge-data.cpp93
-rw-r--r--dali/internal/accessibility/bridge/bridge-data.h122
-rw-r--r--dali/internal/accessibility/bridge/bridge-editable-text.cpp10
-rw-r--r--dali/internal/accessibility/bridge/bridge-hyperlink.cpp10
-rw-r--r--dali/internal/accessibility/bridge/bridge-hypertext.cpp10
-rw-r--r--dali/internal/accessibility/bridge/bridge-impl.cpp738
-rw-r--r--dali/internal/accessibility/bridge/bridge-selection.cpp10
-rw-r--r--dali/internal/accessibility/bridge/bridge-socket.cpp9
-rw-r--r--dali/internal/accessibility/bridge/bridge-table-cell.cpp9
-rw-r--r--dali/internal/accessibility/bridge/bridge-table.cpp9
-rw-r--r--dali/internal/accessibility/bridge/bridge-text.cpp10
-rw-r--r--dali/internal/accessibility/bridge/bridge-text.h15
-rw-r--r--dali/internal/accessibility/bridge/bridge-value.cpp12
-rw-r--r--dali/internal/accessibility/bridge/dummy/dummy-atspi.h18
28 files changed, 1213 insertions, 1189 deletions
diff --git a/dali/devel-api/adaptor-framework/accessibility-bridge.h b/dali/devel-api/adaptor-framework/accessibility-bridge.h
index de570532d..e54458153 100644
--- a/dali/devel-api/adaptor-framework/accessibility-bridge.h
+++ b/dali/devel-api/adaptor-framework/accessibility-bridge.h
@@ -95,40 +95,30 @@ struct DALI_ADAPTOR_API Bridge
/**
* @brief Adds object on the top of the stack of "default label" sourcing objects.
*
- * @see GetDefaultLabel
+ * The "default label" is a reading material (text) derived from an accesibility object
+ * that could be read by screen-reader immediately after the navigation context has changed
+ * (window activates, popup shows up, tab changes) and before first UI element is highlighted.
*
* @param[in] object The accessible object
+ *
+ * @note This is a Tizen only feature not present in upstream ATSPI.
+ * Feature can be enabled/disabled for particular context root object
+ * by setting value of its accessibility attribute "default_label".
+ * Following strings are valid values for "default_label" attribute: "enabled", "disabled".
+ * Any other value will be interpreted as "enabled".
*/
virtual void RegisterDefaultLabel(Accessible* object) = 0;
/**
* @brief Removes object from the stack of "default label" sourcing objects.
*
- * @see GetDefaultLabel
+ * @see RegisterDefaultLabel
*
* @param[in] object The accessible object
*/
virtual void UnregisterDefaultLabel(Accessible* object) = 0;
/**
- * @brief Gets the top-most object from the stack of "default label" sourcing objects.
- *
- * The "default label" is a reading material (text) derived from an accesibility object
- * that could be read by screen-reader immediately after the navigation context has changed
- * (window activates, popup shows up, tab changes) and before first UI element is highlighted.
- *
- * @param[in] root The root of the navigation context for which to retrieve the default label.
- *
- * @return The handler to accessibility object
- * @note This is a Tizen only feature not present in upstream ATSPI.
- * Feature can be enabled/disabled for particular context root object
- * by setting value of its accessibility attribute "default_label".
- * 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;
-
- /**
* @brief Sets name of current application which will be visible on accessibility bus.
*
* @param[in] name The application name
@@ -230,15 +220,7 @@ struct DALI_ADAPTOR_API Bridge
/**
* @brief This method is called, when bridge is being activated.
*/
- virtual ForceUpResult ForceUp()
- {
- if(mData)
- {
- return ForceUpResult::ALREADY_UP;
- }
- mData = std::make_shared<Data>();
- return ForceUpResult::JUST_STARTED;
- }
+ virtual ForceUpResult ForceUp() = 0;
/**
* @brief This method is called, when bridge is being deactivated.
@@ -249,10 +231,7 @@ struct DALI_ADAPTOR_API Bridge
* @brief Checks if bridge is activated or not.
* @return True if brige is activated.
*/
- bool IsUp() const
- {
- return bool(mData);
- }
+ virtual bool IsUp() const = 0;
/**
* @brief Emits cursor-moved event on at-spi bus.
@@ -468,25 +447,10 @@ struct DALI_ADAPTOR_API Bridge
*
* @note Remote object pointed to by 'socket' must implement 'org.a11y.atspi.Socket'.
* @see EmbedSocket()
- * @see SetExtentsOffset()
*/
virtual void SetSocketOffset(ProxyAccessible* socket, std::int32_t x, std::int32_t y) = 0;
/**
- * @brief Sets the global extents offset.
- *
- * This offset will be added during serialization of GetExtents() return value to D-Bus.
- * Local calls to GetExtents() are unaffected.
- *
- * @param[in] x Horizontal offset
- * @param[in] y Vertical offset
- *
- * @see SetSocketOffset()
- * @see Dali::Accessibility::Component::GetExtents()
- */
- virtual void SetExtentsOffset(std::int32_t x, std::int32_t y) = 0;
-
- /**
* @brief Sets the preferred bus name.
*
* If the Bridge is enabled, it will immediately release the previous name and request the new one.
@@ -499,6 +463,24 @@ struct DALI_ADAPTOR_API Bridge
virtual void SetPreferredBusName(std::string_view preferredBusName) = 0;
/**
+ * @brief Registers accessible object to be known in bridge object.
+ *
+ * Bridge must known about all currently alive accessible objects, as some requst
+ * might come and object will be identified by number id (it's memory address).
+ * To avoid memory corruption number id is checked against set of known objects.
+ *
+ * @param[in] object The accessible object
+ **/
+ virtual void RegisterAccessible(const Accessible* object) override;
+
+ /**
+ * @brief Unregisters accessible object from the bridge object.
+ *
+ * @param[in] object The accessible object
+ **/
+ virtual void UnregisterAccessible(const Accessible* object) override;
+
+ /**
* @brief Returns instance of bridge singleton object.
*
* @return The current bridge object
@@ -564,9 +546,10 @@ struct DALI_ADAPTOR_API Bridge
}
protected:
+
+// TODO: rename and move to BridgeImpl
struct Data
{
- std::unordered_set<const Accessible*> mKnownObjects;
std::string mBusName;
Actor mHighlightActor;
Actor mCurrentlyHighlightedActor;
@@ -583,38 +566,11 @@ protected:
inline static AutoInitState mAutoInitState = AutoInitState::ENABLED;
+// TODO: check if these need to be static
inline static Signal<void()> mEnabledSignal;
inline static Signal<void()> mDisabledSignal;
inline static Signal<void()> mScreenReaderEnabledSignal;
inline static Signal<void()> mScreenReaderDisabledSignal;
-
- /**
- * @brief Registers accessible object to be known in bridge object.
- *
- * Bridge must known about all currently alive accessible objects, as some requst
- * might come and object will be identified by number id (it's memory address).
- * To avoid memory corruption number id is checked against set of known objects.
- *
- * @param[in] object The accessible object
- **/
- void RegisterAccessible(const Accessible* object);
-
- /**
- * @brief Unregisters accessible object from the bridge object.
- *
- * @param[in] object The accessible object
- **/
- void UnregisterAccessible(const Accessible* object);
-
- /**
- * @brief Tells bridge, that given object is considered root (doesn't have any parents).
- *
- * All root objects will have the same parent - application object. Application object
- * is controlled by bridge and private.
- *
- * @param[in] owner The accessible object
- **/
- void SetIsOnRootLevel(Accessible* owner);
};
/**
diff --git a/dali/devel-api/adaptor-framework/accessibility.cpp b/dali/devel-api/adaptor-framework/accessibility.cpp
index 8b7a10ff2..445501ffe 100644
--- a/dali/devel-api/adaptor-framework/accessibility.cpp
+++ b/dali/devel-api/adaptor-framework/accessibility.cpp
@@ -319,25 +319,6 @@ void Accessible::SetHighlightActor(Dali::Actor actor)
}
}
-void Bridge::ForceDown()
-{
- auto highlighted = Accessible::GetCurrentlyHighlightedActor();
- if(highlighted)
- {
- auto component = dynamic_cast<Component*>(Accessible::Get(highlighted));
- if(component)
- {
- component->ClearHighlight();
- }
- }
- mData = {};
-}
-
-void Bridge::SetIsOnRootLevel(Accessible* owner)
-{
- owner->mIsOnRootLevel = true;
-}
-
namespace
{
class AdaptorAccessible : public ActorAccessible
diff --git a/dali/devel-api/atspi-interfaces/accessible.h b/dali/devel-api/atspi-interfaces/accessible.h
index 1e6f25200..b33ff4460 100644
--- a/dali/devel-api/atspi-interfaces/accessible.h
+++ b/dali/devel-api/atspi-interfaces/accessible.h
@@ -369,6 +369,17 @@ public:
}
/**
+ * @brief Set the object as root level (doesn't have any parents).
+ *
+ * All root objects will have the same parent - application object. Application object
+ * is controlled by bridge and private.
+ **/
+ void SetIsOnRootLevel()
+ {
+ mIsOnRootLevel = true;
+ }
+
+ /**
* @brief Gets all suppressed events.
*
* @return All suppressed events
diff --git a/dali/internal/accessibility/bridge/accessible.cpp b/dali/internal/accessibility/bridge/accessible.cpp
index baf67035c..a3aa96daa 100644
--- a/dali/internal/accessibility/bridge/accessible.cpp
+++ b/dali/internal/accessibility/bridge/accessible.cpp
@@ -126,20 +126,7 @@ Address Accessible::GetAddress() const
}
std::ostringstream tmp;
tmp << this;
- auto bridgeData = bridge->mData;
- return {bridgeData ? bridgeData->mBusName : "", tmp.str()};
-}
-
-void Bridge::RegisterAccessible(const Accessible* object)
-{
- assert(mData);
- mData->mKnownObjects.insert(object);
-}
-
-void Bridge::UnregisterAccessible(const Accessible* object)
-{
- assert(mData);
- mData->mKnownObjects.erase(object);
+ return {bridge->GetBusName(), tmp.str()};
}
bool Accessible::IsHidden() const
diff --git a/dali/internal/accessibility/bridge/bridge-accessible.cpp b/dali/internal/accessibility/bridge/bridge-accessible.cpp
index c57a887c4..4616bccf6 100644
--- a/dali/internal/accessibility/bridge/bridge-accessible.cpp
+++ b/dali/internal/accessibility/bridge/bridge-accessible.cpp
@@ -365,13 +365,33 @@ static std::vector<Component*> GetNonDuplicatedScrollableParents(Accessible* chi
return scrollableParentsOfChild;
}
-} // anonymous namespace
+/**
+ * @brief Gets the window to which this accessible belongs (or an empty handle).
+ *
+ * @param accessible The accessible
+ * @return The window
+ */
-BridgeAccessible::BridgeAccessible()
+Dali::WeakHandle<Dali::Window> GetWindow(Dali::Accessibility::Accessible* accessible)
{
+ Dali::WeakHandle<Dali::Window> windowHandle;
+ Dali::Actor actor = accessible ? accessible->GetInternalActor() : Dali::Actor();
+
+ if(actor)
+ {
+ Dali::Window window = Dali::DevelWindow::Get(actor);
+ windowHandle = {window};
+ }
+
+ return windowHandle;
}
-void BridgeAccessible::RegisterInterfaces()
+} // anonymous namespace
+
+BridgeAccessible::BridgeAccessible(std::shared_ptr<BridgeData> bridgeData)
+: BridgeBase(std::move(bridgeData)) {}
+
+DBus::DBusInterfaceDescription BridgeAccessible::GetInterfaces() const
{
DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::ACCESSIBLE)};
AddGetPropertyToInterface(desc, "ChildCount", &BridgeAccessible::GetChildCount);
@@ -395,12 +415,12 @@ void BridgeAccessible::RegisterInterfaces()
AddFunctionToInterface(desc, "GetRelationSet", &BridgeAccessible::GetRelationSet);
AddFunctionToInterface(desc, "SetListenPostRender", &BridgeAccessible::SetListenPostRender);
AddFunctionToInterface(desc, "GetNodeInfo", &BridgeAccessible::GetNodeInfo);
- mDbusServer.addInterface("/", desc, true);
+ return desc;
}
Accessible* BridgeAccessible::FindSelf() const
{
- return FindCurrentObject();
+ return mBridgeData->FindCurrentObject();
}
Component* BridgeAccessible::GetObjectInRelation(Accessible* obj, RelationType relationType)
@@ -657,8 +677,9 @@ DBus::ValueOrError<Accessible*, uint8_t, Accessible*> BridgeAccessible::GetNavig
auto accessible = FindSelf();
auto cType = static_cast<CoordinateType>(coordinateType);
- x -= mData->mExtentsOffset.first;
- y -= mData->mExtentsOffset.second;
+ const auto extentsOffset = mBridgeData->GetExtentsOffset();
+ x -= extentsOffset.first;
+ y -= extentsOffset.second;
LOG() << "GetNavigableAtPoint: " << x << ", " << y << " type: " << coordinateType;
auto component = CalculateNavigableAccessibleAtPoint(accessible, {x, y}, cType, GET_NAVIGABLE_AT_POINT_MAX_RECURSION_DEPTH);
@@ -1072,3 +1093,70 @@ DBus::ValueOrError<void> BridgeAccessible::SetListenPostRender(bool enabled)
FindSelf()->SetListenPostRender(enabled);
return {};
}
+
+void BridgeAccessible::RegisterDefaultLabel(Dali::Accessibility::Accessible* object)
+{
+ CompressDefaultLabels();
+
+ Dali::WeakHandle<Dali::Window> window = GetWindow(object);
+ 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;
+ });
+
+ if(it == mDefaultLabels.end())
+ {
+ mDefaultLabels.push_back({window, object});
+ }
+ else if(it->first != window)
+ {
+ // TODO: Tentative implementation. It is yet to be specified what should happen
+ // when the same object is re-registered as a default label for another window.
+ *it = {window, object};
+ }
+ else // it->first == window && it->second == object
+ {
+ // Nothing to do
+ }
+}
+
+void BridgeAccessible::UnregisterDefaultLabel(Dali::Accessibility::Accessible* object)
+{
+ CompressDefaultLabels();
+
+ mDefaultLabels.remove_if([object](const DefaultLabelType& label) {
+ return object == label.second;
+ });
+}
+
+Dali::Accessibility::Accessible* BridgeAccessible::GetDefaultLabel(Dali::Accessibility::Accessible* root) const
+{
+ Dali::WeakHandle<Dali::Window> window = GetWindow(root);
+ if(!window.GetBaseHandle())
+ {
+ return root;
+ }
+
+ auto it = std::find_if(mDefaultLabels.rbegin(), mDefaultLabels.rend(), [&window](const DefaultLabelType& label) {
+ return window == label.first;
+ });
+
+ return (it == mDefaultLabels.rend()) ? root : it->second;
+}
+
+/**
+ * @brief Removes expired elements from the default label collection.
+ */
+void BridgeAccessible::CompressDefaultLabels()
+{
+ // 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
+ });
+}
diff --git a/dali/internal/accessibility/bridge/bridge-accessible.h b/dali/internal/accessibility/bridge/bridge-accessible.h
index 0f8533d99..29fe9b05a 100644
--- a/dali/internal/accessibility/bridge/bridge-accessible.h
+++ b/dali/internal/accessibility/bridge/bridge-accessible.h
@@ -34,25 +34,17 @@
*/
class BridgeAccessible : public virtual BridgeBase
{
-protected:
+public:
/**
* @brief Constructor.
*/
- BridgeAccessible();
-
- /**
- * @brief Registers Accessible functions to dbus interfaces.
- */
- void RegisterInterfaces();
+ explicit BridgeAccessible(std::shared_ptr<BridgeData> bridgeData);
/**
- * @brief Returns the Accessible object of the currently executed DBus method call.
- *
- * @return The Accessible object
+ * @brief Gets dbus interface description for Text type.
*/
- Dali::Accessibility::Accessible* FindSelf() const;
+ DBus::DBusInterfaceDescription GetInterfaces() override;
-public:
/**
* @brief Enumeration for NeighborSearchMode.
*/
@@ -233,8 +225,25 @@ public:
*/
NodeInfoType GetNodeInfo();
+ /**
+ * @copydoc Dali::Accessibility::Bridge::RegisterDefaultLabel()
+ */
+ void RegisterDefaultLabel(Dali::Accessibility::Accessible* object);
+
+ /**
+ * @copydoc Dali::Accessibility::Bridge::UnregisterDefaultLabel()
+ */
+ void UnregisterDefaultLabel(Dali::Accessibility::Accessible* object);
+
private:
/**
+ * @brief Returns the Accessible object of the currently executed DBus method call.
+ *
+ * @return The Accessible object
+ */
+ Dali::Accessibility::Accessible* FindSelf() const;
+
+ /**
* @brief Calculates Neighbor candidate object in root node.
*
* The DFS algorithm in the method is implemented in iterative way.
@@ -314,6 +323,20 @@ private:
* @return The Component object
*/
Dali::Accessibility::Component* CalculateNavigableAccessibleAtPoint(Dali::Accessibility::Accessible* root, Dali::Accessibility::Point point, Dali::Accessibility::CoordinateType type, unsigned int maxRecursionDepth);
+
+ /**
+ * @brief Gets the top-most object from the stack of "default label" sourcing objects.
+ *
+ * @param[in] root The root of the navigation context for which to retrieve the default label.
+ *
+ * @return The handler to accessibility object
+ */
+ Accessible* GetDefaultLabel(Accessible* root) const;
+
+ // 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 DefaultLabelsType = std::list<DefaultLabelType>;
+ DefaultLabelsType mDefaultLabels;
};
#endif // DALI_INTERNAL_ACCESSIBILITY_BRIDGE_ACCESSIBLE_H
diff --git a/dali/internal/accessibility/bridge/bridge-action.cpp b/dali/internal/accessibility/bridge/bridge-action.cpp
index 90d1674c8..f54e081fc 100644
--- a/dali/internal/accessibility/bridge/bridge-action.cpp
+++ b/dali/internal/accessibility/bridge/bridge-action.cpp
@@ -20,7 +20,11 @@
using namespace Dali::Accessibility;
-void BridgeAction::RegisterInterfaces()
+
+BridgeAction::BridgeAction(std::shared_ptr<BridgeData> bridgeData)
+: BridgeBase(std::move(bridgeData)) {}
+
+DBus::DBusInterfaceDescription BridgeAction::GetInterfaces() const
{
DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::ACTION)};
@@ -32,12 +36,13 @@ void BridgeAction::RegisterInterfaces()
AddFunctionToInterface(desc, "GetKeyBinding", &BridgeAction::GetActionKeyBinding);
AddFunctionToInterface(desc, "DoAction", &BridgeAction::DoAction);
AddFunctionToInterface(desc, "DoActionName", &BridgeAction::DoActionName);
- mDbusServer.addInterface("/", desc, true);
+
+ return desc;
}
Action* BridgeAction::FindSelf() const
{
- return FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::ACTION>();
+ return mBridgeData->FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::ACTION>();
}
DBus::ValueOrError<std::string> BridgeAction::GetActionName(int32_t index)
diff --git a/dali/internal/accessibility/bridge/bridge-application.cpp b/dali/internal/accessibility/bridge/bridge-application.cpp
index 9806bad2f..6bb7f8201 100644
--- a/dali/internal/accessibility/bridge/bridge-application.cpp
+++ b/dali/internal/accessibility/bridge/bridge-application.cpp
@@ -23,17 +23,21 @@
using namespace Dali::Accessibility;
-void BridgeApplication::RegisterInterfaces()
+BridgeApplication::BridgeApplication(std::shared_ptr<BridgeData> bridgeData)
+: BridgeBase(std::move(bridgeData)) {}
+
+DBus::DBusInterfaceDescription BridgeApplication::GetInterfaces() const
{
DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::APPLICATION)};
AddGetPropertyToInterface(desc, "ToolkitName", &BridgeApplication::GetToolkitName);
AddGetPropertyToInterface(desc, "Version", &BridgeApplication::GetVersion);
- mDbusServer.addInterface("/", desc, true);
+
+ return desc;
}
Application* BridgeApplication::FindSelf() const
{
- return FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::APPLICATION>();
+ return mBridgeData->FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::APPLICATION>();
}
std::string BridgeApplication::GetToolkitName()
diff --git a/dali/internal/accessibility/bridge/bridge-base.cpp b/dali/internal/accessibility/bridge/bridge-base.cpp
index a819f259a..e69de29bb 100644
--- a/dali/internal/accessibility/bridge/bridge-base.cpp
+++ b/dali/internal/accessibility/bridge/bridge-base.cpp
@@ -1,417 +0,0 @@
-/*
- * Copyright (c) 2021 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// CLASS HEADER
-#include <dali/internal/accessibility/bridge/bridge-base.h>
-
-// EXTERNAL INCLUDES
-#include <dali/devel-api/common/stage.h>
-#include <atomic>
-#include <cstdlib>
-#include <memory>
-
-// INTERNAL INCLUDES
-#include <dali/devel-api/adaptor-framework/window-devel.h>
-#include <dali/public-api/adaptor-framework/timer.h>
-
-using namespace Dali::Accessibility;
-
-static Dali::Timer tickTimer;
-
-BridgeBase::BridgeBase()
-{
-}
-
-BridgeBase::~BridgeBase()
-{
- mApplication.mChildren.clear();
-}
-
-void BridgeBase::AddCoalescableMessage(CoalescableMessages kind, Dali::Accessibility::Accessible* obj, float delay, std::function<void()> functor)
-{
- if(delay < 0)
- {
- delay = 0;
- }
- auto countdownBase = static_cast<unsigned int>(delay * 10);
-
- auto it = mCoalescableMessages.insert({{kind, obj}, {countdownBase, countdownBase, {}}});
- if(it.second)
- {
- functor();
- }
- else
- {
- std::get<1>(it.first->second) = countdownBase;
- std::get<2>(it.first->second) = std::move(functor);
- }
-
- if(!tickTimer)
- {
- tickTimer = Dali::Timer::New(100);
- tickTimer.TickSignal().Connect(this, &BridgeBase::TickCoalescableMessages);
- }
-
- if(!tickTimer.IsRunning())
- {
- tickTimer.Start();
- }
-}
-
-bool BridgeBase::TickCoalescableMessages()
-{
- for(auto it = mCoalescableMessages.begin(); it != mCoalescableMessages.end();)
- {
- auto& countdown = std::get<0>(it->second);
- auto countdownBase = std::get<1>(it->second);
- auto& functor = std::get<2>(it->second);
- if(countdown)
- {
- --countdown;
- }
- else
- {
- if(functor)
- {
- functor();
- functor = {};
- countdown = countdownBase;
- }
- else
- {
- it = mCoalescableMessages.erase(it);
- continue;
- }
- }
- ++it;
- }
- return !mCoalescableMessages.empty();
-}
-
-void BridgeBase::UpdateRegisteredEvents()
-{
- using ReturnType = std::vector<std::tuple<std::string, std::string>>;
- mRegistry.method<DBus::ValueOrError<ReturnType>()>("GetRegisteredEvents").asyncCall([this](DBus::ValueOrError<ReturnType> msg) {
- if(!msg)
- {
- LOG() << "Get registered events failed";
- return;
- }
-
- IsBoundsChangedEventAllowed = false;
-
- ReturnType values = std::get<ReturnType>(msg.getValues());
- for(long unsigned int i = 0; i < values.size(); i++)
- {
- if(!std::get<1>(values[i]).compare("Object:BoundsChanged"))
- {
- IsBoundsChangedEventAllowed = true;
- }
- }
- });
-}
-
-BridgeBase::ForceUpResult BridgeBase::ForceUp()
-{
- //TODO: checking mBusName is enough? or a new variable to check bridge state?
- if(Bridge::ForceUp() == ForceUpResult::ALREADY_UP && !GetBusName().empty())
- {
- return ForceUpResult::ALREADY_UP;
- }
- auto proxy = DBus::DBusClient{dbusLocators::atspi::BUS, dbusLocators::atspi::OBJ_PATH, dbusLocators::atspi::BUS_INTERFACE, DBus::ConnectionType::SESSION};
- auto addr = proxy.method<std::string()>(dbusLocators::atspi::GET_ADDRESS).call();
-
- if(!addr)
- {
- DALI_LOG_ERROR("failed at call '%s': %s\n", dbusLocators::atspi::GET_ADDRESS, addr.getError().message.c_str());
- return ForceUpResult::FAILED;
- }
-
- mConnectionPtr = DBusWrapper::Installed()->eldbus_address_connection_get_impl(std::get<0>(addr));
- mData->mBusName = DBus::getConnectionName(mConnectionPtr);
- mDbusServer = {mConnectionPtr};
-
- {
- DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::CACHE)};
- AddFunctionToInterface(desc, "GetItems", &BridgeBase::GetItems);
- mDbusServer.addInterface(AtspiDbusPathCache, desc);
- }
- {
- DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::APPLICATION)};
- AddGetSetPropertyToInterface(desc, "Id", &BridgeBase::GetId, &BridgeBase::SetId);
- mDbusServer.addInterface(AtspiPath, desc);
- }
-
- mRegistry = {AtspiDbusNameRegistry, AtspiDbusPathRegistry, Accessible::GetInterfaceName(AtspiInterface::REGISTRY), mConnectionPtr};
-
- UpdateRegisteredEvents();
-
- mRegistry.addSignal<void(void)>("EventListenerRegistered", [this](void) {
- UpdateRegisteredEvents();
- });
-
- mRegistry.addSignal<void(void)>("EventListenerDeregistered", [this](void) {
- UpdateRegisteredEvents();
- });
-
- return ForceUpResult::JUST_STARTED;
-}
-
-void BridgeBase::ForceDown()
-{
- Bridge::ForceDown();
- mRegistry = {};
- mDbusServer = {};
- mConnectionPtr = {};
-}
-
-const std::string& BridgeBase::GetBusName() const
-{
- static std::string empty;
- return mData ? mData->mBusName : empty;
-}
-
-Accessible* BridgeBase::FindByPath(const std::string& name) const
-{
- try
- {
- return Find(name);
- }
- catch(std::domain_error&)
- {
- return nullptr;
- }
-}
-
-void BridgeBase::AddTopLevelWindow(Accessible* windowAccessible)
-{
- if(windowAccessible->GetInternalActor() == nullptr)
- {
- return;
- }
-
- // Prevent adding the default window twice.
- if(!mApplication.mChildren.empty() &&
- mApplication.mChildren[0]->GetInternalActor() == windowAccessible->GetInternalActor())
- {
- return;
- }
-
- // Adds Window to a list of Windows.
- mApplication.mChildren.push_back(windowAccessible);
- SetIsOnRootLevel(windowAccessible);
-}
-
-void BridgeBase::RemoveTopLevelWindow(Accessible* windowAccessible)
-{
- for(auto i = 0u; i < mApplication.mChildren.size(); ++i)
- {
- if(mApplication.mChildren[i] == windowAccessible)
- {
- mApplication.mChildren.erase(mApplication.mChildren.begin() + i);
- break;
- }
- }
-}
-
-void BridgeBase::CompressDefaultLabels()
-{
- // 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
- });
-}
-
-void BridgeBase::RegisterDefaultLabel(Accessible* object)
-{
- CompressDefaultLabels();
-
- Dali::WeakHandle<Dali::Window> window = GetWindow(object);
- 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;
- });
-
- if(it == mDefaultLabels.end())
- {
- mDefaultLabels.push_back({window, object});
- }
- else if(it->first != window)
- {
- // TODO: Tentative implementation. It is yet to be specified what should happen
- // when the same object is re-registered as a default label for another window.
- *it = {window, object};
- }
- else // it->first == window && it->second == object
- {
- // Nothing to do
- }
-}
-
-void BridgeBase::UnregisterDefaultLabel(Accessible* object)
-{
- CompressDefaultLabels();
-
- mDefaultLabels.remove_if([object](const DefaultLabelType& label) {
- return object == label.second;
- });
-}
-
-Accessible* BridgeBase::GetDefaultLabel(Accessible* root) const
-{
- Dali::WeakHandle<Dali::Window> window = GetWindow(root);
- if(!window.GetBaseHandle())
- {
- return root;
- }
-
- auto it = std::find_if(mDefaultLabels.rbegin(), mDefaultLabels.rend(), [&window](const DefaultLabelType& label) {
- return window == label.first;
- });
-
- return (it == mDefaultLabels.rend()) ? root : it->second;
-}
-
-std::string BridgeBase::StripPrefix(const std::string& path)
-{
- auto size = strlen(AtspiPath);
- return path.substr(size + 1);
-}
-
-Accessible* BridgeBase::Find(const std::string& path) const
-{
- if(path == "root")
- {
- return &mApplication;
- }
-
- void* accessible;
- std::istringstream tmp{path};
- if(!(tmp >> accessible))
- {
- throw std::domain_error{"invalid path '" + path + "'"};
- }
-
- auto it = mData->mKnownObjects.find(static_cast<Accessible*>(accessible));
- if(it == mData->mKnownObjects.end() || (*it)->IsHidden())
- {
- throw std::domain_error{"unknown object '" + path + "'"};
- }
-
- return static_cast<Accessible*>(accessible);
-}
-
-Accessible* BridgeBase::Find(const Address& ptr) const
-{
- assert(ptr.GetBus() == mData->mBusName);
- return Find(ptr.GetPath());
-}
-
-Accessible* BridgeBase::FindCurrentObject() const
-{
- auto path = DBus::DBusServer::getCurrentObjectPath();
- auto size = strlen(AtspiPath);
- if(path.size() <= size)
- {
- throw std::domain_error{"invalid path '" + path + "'"};
- }
- if(path.substr(0, size) != AtspiPath)
- {
- throw std::domain_error{"invalid path '" + path + "'"};
- }
- if(path[size] != '/')
- {
- throw std::domain_error{"invalid path '" + path + "'"};
- }
- return Find(StripPrefix(path));
-}
-
-void BridgeBase::SetId(int id)
-{
- this->mId = id;
-}
-
-int BridgeBase::GetId()
-{
- return this->mId;
-}
-
-auto BridgeBase::GetItems() -> DBus::ValueOrError<std::vector<CacheElementType>>
-{
- auto root = &mApplication;
-
- std::vector<CacheElementType> res;
-
- std::function<void(Accessible*)> proc =
- [&](Accessible* item) {
- res.emplace_back(std::move(CreateCacheElement(root)));
- for(auto i = 0u; i < item->GetChildCount(); ++i)
- {
- proc(item->GetChildAtIndex(i));
- }
- };
-
- return res;
-}
-
-auto BridgeBase::CreateCacheElement(Accessible* item) -> CacheElementType
-{
- if(!item)
- {
- return {};
- }
-
- auto root = &mApplication;
- auto parent = item->GetParent();
-
- std::vector<Address> children;
- for(auto i = 0u; i < item->GetChildCount(); ++i)
- {
- children.emplace_back(item->GetChildAtIndex(i)->GetAddress());
- }
-
- return std::make_tuple(
- item->GetAddress(),
- root->GetAddress(),
- parent ? parent->GetAddress() : Address{},
- children,
- item->GetInterfacesAsStrings(),
- item->GetName(),
- item->GetRole(),
- item->GetDescription(),
- item->GetStates().GetRawData());
-}
-
-Dali::WeakHandle<Dali::Window> BridgeBase::GetWindow(Dali::Accessibility::Accessible* accessible)
-{
- Dali::WeakHandle<Dali::Window> windowHandle;
- Dali::Actor actor = accessible ? accessible->GetInternalActor() : Dali::Actor();
-
- if(actor)
- {
- Dali::Window window = Dali::DevelWindow::Get(actor);
- windowHandle = {window};
- }
-
- return windowHandle;
-}
diff --git a/dali/internal/accessibility/bridge/bridge-base.h b/dali/internal/accessibility/bridge/bridge-base.h
index 9396f4222..6f2f3e1f1 100644
--- a/dali/internal/accessibility/bridge/bridge-base.h
+++ b/dali/internal/accessibility/bridge/bridge-base.h
@@ -35,343 +35,22 @@
#include <dali/devel-api/atspi-interfaces/socket.h>
#include <dali/internal/accessibility/bridge/accessibility-common.h>
-/**
- * @brief The ApplicationAccessible class is to define Accessibility Application.
- */
-class ApplicationAccessible : public virtual Dali::Accessibility::Accessible,
- public virtual Dali::Accessibility::Application,
- public virtual Dali::Accessibility::Collection,
- public virtual Dali::Accessibility::Component,
- public virtual Dali::Accessibility::Socket
-{
-public:
- Dali::Accessibility::ProxyAccessible mParent;
- std::vector<Dali::Accessibility::Accessible*> mChildren;
- std::string mName;
- std::string mToolkitName{"dali"};
- bool mIsEmbedded{false};
-
- std::string GetName() const override
- {
- return mName;
- }
-
- std::string GetDescription() const override
- {
- return "";
- }
-
- Dali::Accessibility::Accessible* GetParent() override
- {
- return &mParent;
- }
-
- size_t GetChildCount() const override
- {
- return mChildren.size();
- }
-
- std::vector<Dali::Accessibility::Accessible*> GetChildren() override
- {
- return mChildren;
- }
-
- Dali::Accessibility::Accessible* GetChildAtIndex(size_t index) override
- {
- auto size = mChildren.size();
- if(index >= size)
- {
- throw std::domain_error{"invalid index " + std::to_string(index) + " for object with " + std::to_string(size) + " children"};
- }
- return mChildren[index];
- }
-
- size_t GetIndexInParent() override
- {
- if(mIsEmbedded)
- {
- return 0u;
- }
-
- throw std::domain_error{"can't call GetIndexInParent on application object"};
- }
-
- Dali::Accessibility::Role GetRole() const override
- {
- return Dali::Accessibility::Role::APPLICATION;
- }
-
- Dali::Accessibility::States GetStates() override
- {
- Dali::Accessibility::States result;
-
- for(auto* child : mChildren)
- {
- result = result | child->GetStates();
- }
-
- // The Application object should never have the SENSITIVE state
- result[Dali::Accessibility::State::SENSITIVE] = false;
-
- return result;
- }
-
- Dali::Accessibility::Attributes GetAttributes() const override
- {
- return {};
- }
-
- /**
- * @brief Gets the Accessible object from the window.
- *
- * @param[in] window The window to find
- * @return Null if mChildren is empty, otherwise the Accessible object
- * @note Currently, the default window would be returned when mChildren is not empty.
- */
- Dali::Accessibility::Accessible* GetWindowAccessible(Dali::Window window)
- {
- if(mChildren.empty())
- {
- return nullptr;
- }
-
- Dali::Layer rootLayer = window.GetRootLayer();
-
- // Find a child which is related to the window.
- for(auto i = 0u; i < mChildren.size(); ++i)
- {
- if(rootLayer == mChildren[i]->GetInternalActor())
- {
- return mChildren[i];
- }
- }
-
- // If can't find its children, return the default window.
- return mChildren[0];
- }
-
- bool DoGesture(const Dali::Accessibility::GestureInfo& gestureInfo) override
- {
- return false;
- }
-
- std::vector<Dali::Accessibility::Relation> GetRelationSet() override
- {
- return {};
- }
-
- Dali::Actor GetInternalActor() override
- {
- return Dali::Actor{};
- }
-
- Dali::Accessibility::Address GetAddress() const override
- {
- return {"", "root"};
- }
-
- // Application
-
- std::string GetToolkitName() const override
- {
- return mToolkitName;
- }
-
- std::string GetVersion() const override
- {
- return std::to_string(Dali::ADAPTOR_MAJOR_VERSION) + "." + std::to_string(Dali::ADAPTOR_MINOR_VERSION);
- }
-
- // Socket
-
- Dali::Accessibility::Address Embed(Dali::Accessibility::Address plug) override
- {
- mIsEmbedded = true;
- mParent.SetAddress(plug);
-
- return GetAddress();
- }
-
- void Unembed(Dali::Accessibility::Address plug) override
- {
- if(mParent.GetAddress() == plug)
- {
- mIsEmbedded = false;
- mParent.SetAddress({});
- Dali::Accessibility::Bridge::GetCurrentBridge()->SetExtentsOffset(0, 0);
- }
- }
-
- void SetOffset(std::int32_t x, std::int32_t y) override
- {
- if(!mIsEmbedded)
- {
- return;
- }
-
- Dali::Accessibility::Bridge::GetCurrentBridge()->SetExtentsOffset(x, y);
- }
-
- // Component
-
- Dali::Rect<> GetExtents(Dali::Accessibility::CoordinateType type) const override
- {
- using limits = std::numeric_limits<float>;
-
- float minX = limits::max();
- float minY = limits::max();
- float maxX = limits::min();
- float maxY = limits::min();
-
- for(Dali::Accessibility::Accessible* child : mChildren)
- {
- auto* component = Dali::Accessibility::Component::DownCast(child);
- if(!component)
- {
- continue;
- }
-
- auto extents = component->GetExtents(type);
-
- minX = std::min(minX, extents.x);
- minY = std::min(minY, extents.y);
- maxX = std::max(maxX, extents.x + extents.width);
- maxY = std::max(maxY, extents.y + extents.height);
- }
-
- return {minX, minY, maxX - minX, maxY - minY};
- }
-
- Dali::Accessibility::ComponentLayer GetLayer() const override
- {
- return Dali::Accessibility::ComponentLayer::WINDOW;
- }
-
- std::int16_t GetMdiZOrder() const override
- {
- return 0;
- }
-
- bool GrabFocus() override
- {
- return false;
- }
-
- double GetAlpha() const override
- {
- return 0.0;
- }
-
- bool GrabHighlight() override
- {
- return false;
- }
-
- bool ClearHighlight() override
- {
- return false;
- }
-
- bool IsScrollable() const override
- {
- return false;
- }
-};
-
-/**
- * @brief Enumeration for CoalescableMessages.
- */
-enum class CoalescableMessages
-{
- BOUNDS_CHANGED, ///< Bounds changed
- SET_OFFSET, ///< Set offset
- POST_RENDER, ///< Post render
-};
-
-// Custom specialization of std::hash
-namespace std
-{
-template<>
-struct hash<std::pair<CoalescableMessages, Dali::Accessibility::Accessible*>>
-{
- size_t operator()(std::pair<CoalescableMessages, Dali::Accessibility::Accessible*> value) const
- {
- return (static_cast<size_t>(value.first) * 131) ^ reinterpret_cast<size_t>(value.second);
- }
-};
-} // namespace std
/**
* @brief The BridgeBase class is basic class for Bridge functions.
*/
-class BridgeBase : public Dali::Accessibility::Bridge, public Dali::ConnectionTracker
+class BridgeBase
{
- std::unordered_map<std::pair<CoalescableMessages, Dali::Accessibility::Accessible*>, std::tuple<unsigned int, unsigned int, std::function<void()>>> mCoalescableMessages;
-
- /**
- * @brief Removes all CoalescableMessages using Tick signal.
- *
- * @return False if mCoalescableMessages is empty, otherwise true.
- */
- bool TickCoalescableMessages();
-
public:
- /**
- * @brief Adds CoalescableMessages, Accessible, and delay time to mCoalescableMessages.
- *
- * @param[in] kind CoalescableMessages enum value
- * @param[in] obj Accessible object
- * @param[in] delay The delay time
- * @param[in] functor The function to be called // NEED TO UPDATE!
- */
- void AddCoalescableMessage(CoalescableMessages kind, Dali::Accessibility::Accessible* obj, float delay, std::function<void()> functor);
-
- /**
- * @brief Callback when the visibility of the window is changed.
- *
- * @param[in] window The window to be changed
- * @param[in] visible The visibility of the window
- */
- void OnWindowVisibilityChanged(Dali::Window window, bool visible);
-
- /**
- * @copydoc Dali::Accessibility::Bridge::GetBusName()
- */
- const std::string& GetBusName() const override;
-
- /**
- * @copydoc Dali::Accessibility::Bridge::AddTopLevelWindow()
- */
- void AddTopLevelWindow(Dali::Accessibility::Accessible* windowAccessible) override;
-
- /**
- * @copydoc Dali::Accessibility::Bridge::RemoveTopLevelWindow()
- */
- void RemoveTopLevelWindow(Dali::Accessibility::Accessible* windowAccessible) override;
-
- /**
- * @copydoc Dali::Accessibility::Bridge::RegisterDefaultLabel()
- */
- void RegisterDefaultLabel(Dali::Accessibility::Accessible* object) override;
-
- /**
- * @copydoc Dali::Accessibility::Bridge::UnregisterDefaultLabel()
- */
- void UnregisterDefaultLabel(Dali::Accessibility::Accessible* object) override;
+ explicit BridgeBase(std::shared_ptr<BridgeData> bridgeData)
+ : mBridgeData{std::move(bridgeData)} {}
/**
- * @copydoc Dali::Accessibility::Bridge::GetDefaultLabel()
+ * @brief Gets dbus interface description for given type.
*/
- Dali::Accessibility::Accessible* GetDefaultLabel(Dali::Accessibility::Accessible* root) const override;
-
- /**
- * @copydoc Dali::Accessibility::Bridge::GetApplication()
- */
- Dali::Accessibility::Accessible* GetApplication() const override
- {
- return &mApplication;
- }
+ virtual DBus::DBusInterfaceDescription GetInterfaces() const = 0;
+protected:
/**
* @brief Adds function to dbus interface.
*/
@@ -509,190 +188,7 @@ public:
});
}
- /**
- * @brief Gets the string of the path excluding the specified prefix.
- *
- * @param path The path to get
- * @return The string stripped of the specific prefix
- */
- static std::string StripPrefix(const std::string& path);
-
- /**
- * @brief Finds the Accessible object according to the path.
- *
- * @param[in] path The path for Accessible object
- * @return The Accessible object corresponding to the path
- */
- Dali::Accessibility::Accessible* Find(const std::string& path) const;
-
- /**
- * @brief Finds the Accessible object with the given address.
- *
- * @param[in] ptr The unique Address of the object
- * @return The Accessible object corresponding to the path
- */
- Dali::Accessibility::Accessible* Find(const Dali::Accessibility::Address& ptr) const;
-
- /**
- * @brief Returns the target object of the currently executed DBus method call.
- *
- * @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* 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()
- */
- Dali::Accessibility::Accessible* FindByPath(const std::string& name) const override;
-
- /**
- * @copydoc Dali::Accessibility::Bridge::SetApplicationName()
- */
- void SetApplicationName(std::string name) override
- {
- mApplication.mName = std::move(name);
- }
-
- /**
- * @copydoc Dali::Accessibility::Bridge::SetToolkitName()
- */
- void SetToolkitName(std::string_view toolkitName) override
- {
- mApplication.mToolkitName = std::string{toolkitName};
- }
-
-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 DefaultLabelsType = std::list<DefaultLabelType>;
-
- mutable ApplicationAccessible mApplication;
- DefaultLabelsType mDefaultLabels;
- bool mIsScreenReaderSuppressed = false;
-
-private:
- /**
- * @brief Sets an ID.
- * @param[in] id An ID (integer value)
- */
- void SetId(int id);
-
- /**
- * @brief Gets the ID.
- * @return The ID to be set
- */
- int GetId();
-
- /**
- * @brief Update registered events.
- */
- void UpdateRegisteredEvents();
-
- using CacheElementType = std::tuple<
- Dali::Accessibility::Address,
- Dali::Accessibility::Address,
- Dali::Accessibility::Address,
- std::vector<Dali::Accessibility::Address>,
- std::vector<std::string>,
- std::string,
- Dali::Accessibility::Role,
- std::string,
- std::array<uint32_t, 2>>;
-
- /**
- * @brief Gets Items // NEED TO UPDATE!
- *
- * @return
- */
- DBus::ValueOrError<std::vector<CacheElementType>> GetItems();
-
- /**
- * @brief Creates CacheElement.
- *
- * CreateCacheElement method works for GetItems which is a part of ATSPI protocol.
- * ATSPI client library (libatspi from at-spi2-core) depending on cacheing policy configuration uses GetItems
- * to pre-load entire accessible tree from application to its own cache in single dbus call.
- * Otherwise the particular nodes in a tree are cached lazily when client library tries to access them.
- * @param item Accessible to get information
- * @return The elements to be cached
- */
- CacheElementType CreateCacheElement(Dali::Accessibility::Accessible* item);
-
- /**
- * @brief Removes expired elements from the default label collection.
- */
- void CompressDefaultLabels();
-
- /**
- * @brief Gets the window to which this accessible belongs (or an empty handle).
- *
- * @param accessible The accessible
- * @return The window
- */
- static Dali::WeakHandle<Dali::Window> GetWindow(Dali::Accessibility::Accessible* accessible);
-
-protected:
- BridgeBase();
- virtual ~BridgeBase();
-
- /**
- * @copydoc Dali::Accessibility::Bridge::ForceUp()
- */
- ForceUpResult ForceUp() override;
-
- /**
- * @copydoc Dali::Accessibility::Bridge::ForceDown()
- */
- void ForceDown() override;
-
- DBus::DBusServer mDbusServer;
- DBusWrapper::ConnectionPtr mConnectionPtr;
- int mId = 0;
- DBus::DBusClient mRegistry;
- bool IsBoundsChangedEventAllowed{false};
+ const std::shared_ptr<BridgeData> mBridgeData;
};
#endif // DALI_INTERNAL_ACCESSIBILITY_BRIDGE_BASE_H
diff --git a/dali/internal/accessibility/bridge/bridge-collection.cpp b/dali/internal/accessibility/bridge/bridge-collection.cpp
index 20111301d..08d40469b 100644
--- a/dali/internal/accessibility/bridge/bridge-collection.cpp
+++ b/dali/internal/accessibility/bridge/bridge-collection.cpp
@@ -43,18 +43,21 @@ enum class AtspiCollection
};
} // anonymous namespace
-void BridgeCollection::RegisterInterfaces()
+BridgeCollection::BridgeCollection(std::shared_ptr<BridgeData> bridgeData)
+: BridgeBase(std::move(bridgeData)) {}
+
+DBus::DBusInterfaceDescription BridgeCollection::GetInterfaces() const
{
DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::COLLECTION)};
AddFunctionToInterface(desc, "GetMatches", &BridgeCollection::GetMatches);
AddFunctionToInterface(desc, "GetMatchesInMatches", &BridgeCollection::GetMatchesInMatches);
- mDbusServer.addInterface("/", desc, true);
+ return desc;
}
Collection* BridgeCollection::FindSelf() const
{
- return FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::COLLECTION>();
+ return mBridgeData->FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::COLLECTION>();
}
/**
@@ -500,7 +503,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::FindCurrentObject();
+ auto self = mBridgeData->FindCurrentObject();
auto matcher = Comparer{&rule};
VisitNodes(self, res, matcher, count);
@@ -532,7 +535,7 @@ DBus::ValueOrError<std::vector<Accessible*> > BridgeCollection::GetMatchesInMatc
std::vector<Accessible*> res;
std::vector<Accessible*> firstRes;
std::vector<Accessible*> secondRes;
- auto self = BridgeBase::FindCurrentObject();
+ auto self = mBridgeData->FindCurrentObject();
auto firstMatcher = Comparer{&firstRule};
auto secondMatcher = Comparer{&secondRule};
VisitNodes(self, firstRes, firstMatcher, firstCount);
diff --git a/dali/internal/accessibility/bridge/bridge-collection.h b/dali/internal/accessibility/bridge/bridge-collection.h
index 32ea9c154..441dd6865 100644
--- a/dali/internal/accessibility/bridge/bridge-collection.h
+++ b/dali/internal/accessibility/bridge/bridge-collection.h
@@ -57,14 +57,6 @@ private:
*/
static void VisitNodes(Dali::Accessibility::Accessible* obj, std::vector<Dali::Accessibility::Accessible*>& result, Comparer& comparer, size_t maxCount);
-protected:
- BridgeCollection() = default;
-
- /**
- * @brief Registers Collection functions to dbus interfaces.
- */
- void RegisterInterfaces();
-
/**
* @brief Returns the Collection object of the currently executed DBus method call.
*
@@ -73,6 +65,13 @@ protected:
Dali::Accessibility::Collection* FindSelf() const;
public:
+ explicit BridgeCollection(std::shared_ptr<BridgeData> bridgeData);
+
+ /**
+ * @brief Gets dbus interface description for Collection type.
+ */
+ DBus::DBusInterfaceDescription GetInterfaces() override;
+
/**
* MatchRule type is a tuple that only carries data of de-serialized parameter from BridgeCollection::GetMatches dbus method.
*/
diff --git a/dali/internal/accessibility/bridge/bridge-component.cpp b/dali/internal/accessibility/bridge/bridge-component.cpp
index ef0ff0fb4..0cc698bf7 100644
--- a/dali/internal/accessibility/bridge/bridge-component.cpp
+++ b/dali/internal/accessibility/bridge/bridge-component.cpp
@@ -22,11 +22,10 @@
using namespace Dali::Accessibility;
-BridgeComponent::BridgeComponent()
-{
-}
+BridgeComponent::BridgeComponent(std::shared_ptr<BridgeData> bridgeData)
+: BridgeBase(std::move(bridgeData)) {}
-void BridgeComponent::RegisterInterfaces()
+DBus::DBusInterfaceDescription BridgeComponent::GetInterfaces() const
{
// The second arguments below are the names (or signatures) of DBus methods.
// Screen Reader will call the methods with the exact names as specified in the AT-SPI Component interface:
@@ -44,12 +43,12 @@ void BridgeComponent::RegisterInterfaces()
AddFunctionToInterface(desc, "GrabHighlight", &BridgeComponent::GrabHighlight);
AddFunctionToInterface(desc, "GrabFocus", &BridgeComponent::GrabFocus);
AddFunctionToInterface(desc, "ClearHighlight", &BridgeComponent::ClearHighlight);
- mDbusServer.addInterface("/", desc, true);
+ return desc;
}
Component* BridgeComponent::FindSelf() const
{
- return FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::COMPONENT>();
+ return mBridgeData->FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::COMPONENT>();
}
DBus::ValueOrError<bool> BridgeComponent::IsAccessibleContainingPoint(int32_t x, int32_t y, uint32_t coordType)
@@ -66,8 +65,9 @@ DBus::ValueOrError<std::tuple<int32_t, int32_t, int32_t, int32_t> > BridgeCompon
{
auto rect = FindSelf()->GetExtents(static_cast<CoordinateType>(coordType));
- rect.x += mData->mExtentsOffset.first;
- rect.y += mData->mExtentsOffset.second;
+ const auto extentsOffset = mBridgeData->GetExtentsOffset();
+ rect.x += extentsOffset.first;
+ rect.y += extentsOffset.second;
return std::tuple<int32_t, int32_t, int32_t, int32_t>{rect.x, rect.y, rect.width, rect.height};
}
@@ -76,8 +76,9 @@ DBus::ValueOrError<int32_t, int32_t> BridgeComponent::GetPosition(uint32_t coord
{
auto rect = FindSelf()->GetExtents(static_cast<CoordinateType>(coordType));
- rect.x += mData->mExtentsOffset.first;
- rect.y += mData->mExtentsOffset.second;
+ const auto extentsOffset = mBridgeData->GetExtentsOffset();
+ rect.x += extentsOffset.first;
+ rect.y += extentsOffset.second;
return {static_cast<int32_t>(rect.x), static_cast<int32_t>(rect.y)};
}
diff --git a/dali/internal/accessibility/bridge/bridge-component.h b/dali/internal/accessibility/bridge/bridge-component.h
index ec24f422a..78a045922 100644
--- a/dali/internal/accessibility/bridge/bridge-component.h
+++ b/dali/internal/accessibility/bridge/bridge-component.h
@@ -34,17 +34,6 @@
*/
class BridgeComponent : public virtual BridgeBase
{
-protected:
- /**
- * @brief Constructor.
- */
- BridgeComponent();
-
- /**
- * @brief Registers Component functions to dbus interfaces.
- */
- void RegisterInterfaces();
-
/**
* @brief Returns the Component object of the currently executed DBus method call.
*
@@ -53,6 +42,13 @@ protected:
Dali::Accessibility::Component* FindSelf() const;
public:
+ explicit BridgeComponent(std::shared_ptr<BridgeData> bridgeData);
+
+ /**
+ * @brief Gets dbus interface description for Component type.
+ */
+ DBus::DBusInterfaceDescription GetInterfaces() override;
+
/**
* @copydoc Dali::Accessibility::Component::IsAccessibleContainingPoint()
*/
diff --git a/dali/internal/accessibility/bridge/bridge-data.cpp b/dali/internal/accessibility/bridge/bridge-data.cpp
new file mode 100644
index 000000000..a8bf12cda
--- /dev/null
+++ b/dali/internal/accessibility/bridge/bridge-data.cpp
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/internal/accessibility/bridge/bridge-data.h>
+#include <dali/internal/accessibility/bridge/dbus/dbus.h>
+
+using namespace Dali::Accessibility;
+
+std::string BridgeData::StripPrefix(const std::string& path)
+{
+ auto size = strlen(AtspiPath);
+ return path.substr(size + 1);
+}
+
+Accessible* BridgeData::Find(const std::string& path) const
+{
+ if(path == "root")
+ {
+ return &mApplication;
+ }
+
+ void* accessible;
+ std::istringstream tmp{path};
+ if(!(tmp >> accessible))
+ {
+ throw std::domain_error{"invalid path '" + path + "'"};
+ }
+
+ auto it = mKnownObjects.find(static_cast<Accessible*>(accessible));
+ if(it == mKnownObjects.end() || (*it)->IsHidden())
+ {
+ throw std::domain_error{"unknown object '" + path + "'"};
+ }
+
+ return static_cast<Accessible*>(accessible);
+}
+
+Accessible* BridgeData::FindCurrentObject() const
+{
+ auto path = DBus::DBusServer::getCurrentObjectPath();
+ auto size = strlen(AtspiPath);
+ if(path.size() <= size)
+ {
+ throw std::domain_error{"invalid path '" + path + "'"};
+ }
+ if(path.substr(0, size) != AtspiPath)
+ {
+ throw std::domain_error{"invalid path '" + path + "'"};
+ }
+ if(path[size] != '/')
+ {
+ throw std::domain_error{"invalid path '" + path + "'"};
+ }
+ return Find(StripPrefix(path));
+}
+
+void BridgeData::AddKnownObject(const Accessible* object)
+{
+ mKnownObjects.insert(object);
+}
+
+void BridgeData::RemoveKnownObject(const Accessible* object)
+{
+ mKnownObjects.erase(object);
+}
+
+void BridgeData::SetExtentsOffset(int32_t x, int32_t y)
+{
+ mExtentsOffset = {x, y};
+}
+
+OffsetType BridgeData::GetExtentsOffset() const
+{
+ return mExtentsOffset;
+}
diff --git a/dali/internal/accessibility/bridge/bridge-data.h b/dali/internal/accessibility/bridge/bridge-data.h
new file mode 100644
index 000000000..8627d665f
--- /dev/null
+++ b/dali/internal/accessibility/bridge/bridge-data.h
@@ -0,0 +1,122 @@
+#ifndef DALI_INTERNAL_ACCESSIBILITY_ACCESSIBLE_OBJECTS_HOLDER_H
+#define DALI_INTERNAL_ACCESSIBILITY_ACCESSIBLE_OBJECTS_HOLDER_H
+
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/devel-api/atspi-interfaces/accessible.h>
+
+/**
+ * @brief The BridgeText class is to correspond with Dali::Accessibility::Text.
+ */
+class BridgeData
+{
+public:
+ /**
+ * @brief Gets the string of the path excluding the specified prefix.
+ *
+ * @param path The path to get
+ * @return The string stripped of the specific prefix
+ */
+ static std::string StripPrefix(const std::string& path);
+
+ /**
+ * @brief Finds the Accessible object according to the path.
+ *
+ * @param[in] path The path for Accessible object
+ * @return The Accessible object corresponding to the path
+ */
+ Dali::Accessibility::Accessible* Find(const std::string& path) const;
+
+ /**
+ * @brief Returns the target object of the currently executed DBus method call.
+ *
+ * @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* 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;
+ }
+
+ void AddKnownObject(const Accessible* object);
+
+ void RemoveKnownObject(const Accessible* object);
+
+ /**
+ * @brief Sets the global extents offset.
+ *
+ * This offset will be added during serialization of GetExtents() return value to D-Bus.
+ * Local calls to GetExtents() are unaffected.
+ *
+ * @param[in] x Horizontal offset
+ * @param[in] y Vertical offset
+ *
+ * @see Dali::Accessibility::Bridge::SetSocketOffset()
+ * @see Dali::Accessibility::Component::GetExtents()
+ */
+ using OffsetType = pair::<int32_t, int32_t>;
+ void SetExtentsOffset(int32_t x, int32_t y);
+
+ OffsetType GetExtentsOffset() const;
+
+private:
+ std::unordered_set<const Accessible*> mKnownObjects;
+ OffsetType mExtentsOffset{0, 0};
+};
+
+#endif // DALI_INTERNAL_ACCESSIBILITY_ACCESSIBLE_OBJECTS_HOLDER_H
diff --git a/dali/internal/accessibility/bridge/bridge-editable-text.cpp b/dali/internal/accessibility/bridge/bridge-editable-text.cpp
index 7053c7705..d2f5f3ad4 100644
--- a/dali/internal/accessibility/bridge/bridge-editable-text.cpp
+++ b/dali/internal/accessibility/bridge/bridge-editable-text.cpp
@@ -23,7 +23,10 @@
using namespace Dali::Accessibility;
-void BridgeEditableText::RegisterInterfaces()
+BridgeEditableText::BridgeEditableText(std::shared_ptr<BridgeData> bridgeData)
+: BridgeBase(std::move(bridgeData)) {}
+
+DBus::DBusInterfaceDescription BridgeEditableText::GetInterfaces() const
{
DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::EDITABLE_TEXT)};
AddFunctionToInterface(desc, "CopyText", &BridgeEditableText::CopyText);
@@ -32,12 +35,13 @@ void BridgeEditableText::RegisterInterfaces()
AddFunctionToInterface(desc, "InsertText", &BridgeEditableText::InsertText);
AddFunctionToInterface(desc, "PasteText", &BridgeEditableText::PasteText);
AddFunctionToInterface(desc, "SetTextContents", &BridgeEditableText::SetTextContents);
- mDbusServer.addInterface("/", desc, true);
+
+ return desc;
}
EditableText* BridgeEditableText::FindSelf() const
{
- return FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::EDITABLE_TEXT>();
+ return mBridgeData->FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::EDITABLE_TEXT>();
}
DBus::ValueOrError<bool> BridgeEditableText::CopyText(int32_t startPosition, int32_t endPosition)
diff --git a/dali/internal/accessibility/bridge/bridge-hyperlink.cpp b/dali/internal/accessibility/bridge/bridge-hyperlink.cpp
index 992d2cf5d..1fa7f2ed2 100644
--- a/dali/internal/accessibility/bridge/bridge-hyperlink.cpp
+++ b/dali/internal/accessibility/bridge/bridge-hyperlink.cpp
@@ -23,7 +23,10 @@
using namespace Dali::Accessibility;
-void BridgeHyperlink::RegisterInterfaces()
+BridgeHyperlink::BridgeHyperlink(std::shared_ptr<BridgeData> bridgeData)
+: BridgeBase(std::move(bridgeData)) {}
+
+DBus::DBusInterfaceDescription BridgeHyperlink::GetInterfaces() const
{
DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::HYPERLINK)};
AddGetPropertyToInterface(desc, "NAnchors", &BridgeHyperlink::GetAnchorCount);
@@ -32,12 +35,13 @@ void BridgeHyperlink::RegisterInterfaces()
AddFunctionToInterface(desc, "GetObject", &BridgeHyperlink::GetAnchorAccessible);
AddFunctionToInterface(desc, "GetURI", &BridgeHyperlink::GetAnchorUri);
AddFunctionToInterface(desc, "IsValid", &BridgeHyperlink::IsValid);
- mDbusServer.addInterface("/", desc, true);
+
+ return desc;
}
Hyperlink* BridgeHyperlink::FindSelf() const
{
- return FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::HYPERLINK>();
+ return mBridgeData->FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::HYPERLINK>();
}
DBus::ValueOrError<int32_t> BridgeHyperlink::GetEndIndex()
diff --git a/dali/internal/accessibility/bridge/bridge-hypertext.cpp b/dali/internal/accessibility/bridge/bridge-hypertext.cpp
index b5f3b3b46..c89c1c504 100644
--- a/dali/internal/accessibility/bridge/bridge-hypertext.cpp
+++ b/dali/internal/accessibility/bridge/bridge-hypertext.cpp
@@ -23,18 +23,22 @@
using namespace Dali::Accessibility;
-void BridgeHypertext::RegisterInterfaces()
+BridgeHypertext::BridgeHypertext(std::shared_ptr<BridgeData> bridgeData)
+: BridgeBase(std::move(bridgeData)) {}
+
+DBus::DBusInterfaceDescription BridgeHypertext::GetInterfaces() const
{
DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::HYPERTEXT)};
AddFunctionToInterface(desc, "GetNLinks", &BridgeHypertext::GetLinkCount);
AddFunctionToInterface(desc, "GetLink", &BridgeHypertext::GetLink);
AddFunctionToInterface(desc, "GetLinkIndex", &BridgeHypertext::GetLinkIndex);
- mDbusServer.addInterface("/", desc, true);
+
+ return desc;
}
Hypertext* BridgeHypertext::FindSelf() const
{
- return FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::HYPERTEXT>();
+ return mBridgeData->FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::HYPERTEXT>();
}
DBus::ValueOrError<int32_t> BridgeHypertext::GetLinkCount()
diff --git a/dali/internal/accessibility/bridge/bridge-impl.cpp b/dali/internal/accessibility/bridge/bridge-impl.cpp
index 5dba57950..da55bdebc 100644
--- a/dali/internal/accessibility/bridge/bridge-impl.cpp
+++ b/dali/internal/accessibility/bridge/bridge-impl.cpp
@@ -43,6 +43,7 @@
#include <dali/internal/accessibility/bridge/bridge-text.h>
#include <dali/internal/accessibility/bridge/bridge-value.h>
#include <dali/internal/accessibility/bridge/dummy/dummy-atspi.h>
+#include <dali/internal/accessibility/bridge/accessible-objects-holder.h>
#include <dali/internal/adaptor/common/adaptor-impl.h>
#include <dali/internal/system/common/environment-variables.h>
@@ -58,26 +59,300 @@ std::string GetAccessiblePath(Accessible* accessible)
return address ? ATSPI_PREFIX_PATH + address.GetPath() : ATSPI_NULL_PATH;
}
+Dali::Timer tickTimer; // TODO: 1) move this to member variable; 2) should Reset
+
+/**
+ * @brief Enumeration for CoalescableMessages.
+ */
+enum class CoalescableMessages
+{
+ BOUNDS_CHANGED, ///< Bounds changed
+ SET_OFFSET, ///< Set offset
+ POST_RENDER, ///< Post render
+};
+
+using CoalescableMessagesKey = std::pair<CoalescableMessages, Dali::Accessibility::Accessible*>;
+using CoalescableMessagesEntry = std::tuple<unsigned int, unsigned int, std::function<void()>>;
+using CoalescableMessagesMap = std::unordered_map<CoalescableMessagesKey, CoalescableMessagesEntry>;
+
+using CacheElementType = std::tuple<
+ Dali::Accessibility::Address,
+ Dali::Accessibility::Address,
+ Dali::Accessibility::Address,
+ std::vector<Dali::Accessibility::Address>,
+ std::vector<std::string>,
+ std::string,
+ Dali::Accessibility::Role,
+ std::string,
+ std::array<uint32_t, 2>>;
+
} // unnamed namespace
+// Custom specialization of std::hash
+namespace std
+{
+template<>
+struct hash<std::pair<CoalescableMessages, Dali::Accessibility::Accessible*>>
+{
+ size_t operator()(std::pair<CoalescableMessages, Dali::Accessibility::Accessible*> value) const
+ {
+ return (static_cast<size_t>(value.first) * 131) ^ reinterpret_cast<size_t>(value.second);
+ }
+};
+} // namespace std
+
+/**
+ * @brief The ApplicationAccessible class is to define Accessibility Application.
+ */
+class ApplicationAccessible : public virtual Dali::Accessibility::Accessible,
+ public virtual Dali::Accessibility::Application,
+ public virtual Dali::Accessibility::Collection,
+ public virtual Dali::Accessibility::Component,
+ public virtual Dali::Accessibility::Socket
+{
+ std::shared_ptr<BridgeData> mBridgeData;
+public:
+ Dali::Accessibility::ProxyAccessible mParent;
+ std::vector<Dali::Accessibility::Accessible*> mChildren;
+ std::string mName;
+ std::string mToolkitName{"dali"};
+ bool mIsEmbedded{false};
+
+ ApplicationAccessible(std::shared_ptr<BridgeData> bridgeData)
+ : mBridgeData{std::move(bridgeData)} {}
+
+ std::string GetName() const override
+ {
+ return mName;
+ }
+
+ std::string GetDescription() const override
+ {
+ return "";
+ }
+
+ Dali::Accessibility::Accessible* GetParent() override
+ {
+ return &mParent;
+ }
+
+ size_t GetChildCount() const override
+ {
+ return mChildren.size();
+ }
+
+ std::vector<Dali::Accessibility::Accessible*> GetChildren() override
+ {
+ return mChildren;
+ }
+
+ Dali::Accessibility::Accessible* GetChildAtIndex(size_t index) override
+ {
+ auto size = mChildren.size();
+ if(index >= size)
+ {
+ throw std::domain_error{"invalid index " + std::to_string(index) + " for object with " + std::to_string(size) + " children"};
+ }
+ return mChildren[index];
+ }
+
+ size_t GetIndexInParent() override
+ {
+ if(mIsEmbedded)
+ {
+ return 0u;
+ }
+
+ throw std::domain_error{"can't call GetIndexInParent on application object"};
+ }
+
+ Dali::Accessibility::Role GetRole() const override
+ {
+ return Dali::Accessibility::Role::APPLICATION;
+ }
+
+ Dali::Accessibility::States GetStates() override
+ {
+ Dali::Accessibility::States result;
+
+ for(auto* child : mChildren)
+ {
+ result = result | child->GetStates();
+ }
+
+ // The Application object should never have the SENSITIVE state
+ result[Dali::Accessibility::State::SENSITIVE] = false;
+
+ return result;
+ }
+
+ Dali::Accessibility::Attributes GetAttributes() const override
+ {
+ return {};
+ }
+
+ /**
+ * @brief Gets the Accessible object from the window.
+ *
+ * @param[in] window The window to find
+ * @return Null if mChildren is empty, otherwise the Accessible object
+ * @note Currently, the default window would be returned when mChildren is not empty.
+ */
+ Dali::Accessibility::Accessible* GetWindowAccessible(Dali::Window window)
+ {
+ if(mChildren.empty())
+ {
+ return nullptr;
+ }
+
+ Dali::Layer rootLayer = window.GetRootLayer();
+
+ // Find a child which is related to the window.
+ for(auto i = 0u; i < mChildren.size(); ++i)
+ {
+ if(rootLayer == mChildren[i]->GetInternalActor())
+ {
+ return mChildren[i];
+ }
+ }
+
+ // If can't find its children, return the default window.
+ return mChildren[0];
+ }
+
+ bool DoGesture(const Dali::Accessibility::GestureInfo& gestureInfo) override
+ {
+ return false;
+ }
+
+ std::vector<Dali::Accessibility::Relation> GetRelationSet() override
+ {
+ return {};
+ }
+
+ Dali::Actor GetInternalActor() override
+ {
+ return Dali::Actor{};
+ }
+
+ Dali::Accessibility::Address GetAddress() const override
+ {
+ return {"", "root"};
+ }
+
+ // Application
+
+ std::string GetToolkitName() const override
+ {
+ return mToolkitName;
+ }
+
+ std::string GetVersion() const override
+ {
+ return std::to_string(Dali::ADAPTOR_MAJOR_VERSION) + "." + std::to_string(Dali::ADAPTOR_MINOR_VERSION);
+ }
+
+ // Socket
+
+ Dali::Accessibility::Address Embed(Dali::Accessibility::Address plug) override
+ {
+ mIsEmbedded = true;
+ mParent.SetAddress(plug);
+
+ return GetAddress();
+ }
+
+ void Unembed(Dali::Accessibility::Address plug) override
+ {
+ if(mParent.GetAddress() == plug)
+ {
+ mIsEmbedded = false;
+ mParent.SetAddress({});
+ mBridgeData->SetExtentsOffset(0, 0);
+ }
+ }
+
+ void SetOffset(std::int32_t x, std::int32_t y) override
+ {
+ if(!mIsEmbedded)
+ {
+ return;
+ }
+
+ mBridgeData->SetExtentsOffset(x, y);
+ }
+
+ // Component
+
+ Dali::Rect<> GetExtents(Dali::Accessibility::CoordinateType type) const override
+ {
+ using limits = std::numeric_limits<float>;
+
+ float minX = limits::max();
+ float minY = limits::max();
+ float maxX = limits::min();
+ float maxY = limits::min();
+
+ for(Dali::Accessibility::Accessible* child : mChildren)
+ {
+ auto* component = Dali::Accessibility::Component::DownCast(child);
+ if(!component)
+ {
+ continue;
+ }
+
+ auto extents = component->GetExtents(type);
+
+ minX = std::min(minX, extents.x);
+ minY = std::min(minY, extents.y);
+ maxX = std::max(maxX, extents.x + extents.width);
+ maxY = std::max(maxY, extents.y + extents.height);
+ }
+
+ return {minX, minY, maxX - minX, maxY - minY};
+ }
+
+ Dali::Accessibility::ComponentLayer GetLayer() const override
+ {
+ return Dali::Accessibility::ComponentLayer::WINDOW;
+ }
+
+ std::int16_t GetMdiZOrder() const override
+ {
+ return 0;
+ }
+
+ bool GrabFocus() override
+ {
+ return false;
+ }
+
+ double GetAlpha() const override
+ {
+ return 0.0;
+ }
+
+ bool GrabHighlight() override
+ {
+ return false;
+ }
+
+ bool ClearHighlight() override
+ {
+ return false;
+ }
+
+ bool IsScrollable() const override
+ {
+ return false;
+ }
+};
+
/**
* @brief The BridgeImpl class is to implement some Bridge functions.
*/
-class BridgeImpl : public virtual BridgeBase,
- public BridgeAccessible,
- public BridgeComponent,
- public BridgeCollection,
- public BridgeAction,
- public BridgeValue,
- public BridgeText,
- public BridgeEditableText,
- public BridgeSelection,
- public BridgeApplication,
- public BridgeHypertext,
- public BridgeHyperlink,
- public BridgeSocket,
- public BridgeTable,
- public BridgeTableCell
+class BridgeImpl : public Dali::Accessibility::Bridge,
+ public Dali::ConnectionTracker
{
DBus::DBusClient mAccessibilityStatusClient{};
DBus::DBusClient mRegistryClient{};
@@ -93,9 +368,43 @@ class BridgeImpl : public virtual BridgeBase,
Dali::Timer mReadScreenReaderEnabledTimer;
Dali::Timer mForceUpTimer;
std::string mPreferredBusName;
+ CoalescableMessagesMap mCoalescableMessages;
+ std::shared_ptr<BridgeData> mBridgeData;
+ const ApplicationAccessible mApplication;
+ const std::vector<BridgeBase> mBridgeObjects;
+ const BridgeAccessible& mBridgeAccessibleRef;
+ bool mIsScreenReaderSuppressed = false;
+
+ DBus::DBusServer mDbusServer;
+ DBusWrapper::ConnectionPtr mConnectionPtr;
+ int mId = 0;
+ DBus::DBusClient mRegistry;
+ bool IsBoundsChangedEventAllowed{false};
public:
- BridgeImpl() = default;
+ BridgeImpl()
+ : mBridgeData{std::make_shared<BridgeData>()}
+ , mApplication{mBridgeData}
+ {
+ mBridgeObjects =
+ {
+ BridgeAccessible{mBridgeData},
+ BridgeComponent{mBridgeData},
+ BridgeCollection{mBridgeData},
+ BridgeAction{mBridgeData},
+ BridgeValue{mBridgeData},
+ BridgeText{mBridgeData},
+ BridgeEditableText{mBridgeData},
+ BridgeSelection{mBridgeData},
+ BridgeApplication{mBridgeData},
+ BridgeHypertext{mBridgeData},
+ BridgeHyperlink{mBridgeData},
+ BridgeSocket{mBridgeData},
+ BridgeTable{mBridgeData},
+ BridgeTableCell{mBridgeData}
+ }
+ mBridgeAccessibleRef = mBridgeObjects[0];
+ }
/**
* @copydoc Dali::Accessibility::Bridge::EmitKeyEvent()
@@ -239,12 +548,7 @@ public:
mHighlightedActor = {};
mHighlightClearAction = {};
- BridgeAccessible::ForceDown();
- mRegistryClient = {};
- mDirectReadingClient = {};
- mDirectReadingCallbacks.clear();
- mApplication.mChildren.clear();
- ClearTimer();
+ ResetResources();
}
void ClearTimer()
@@ -313,12 +617,15 @@ public:
*/
ForceUpResult ForceUp() override
{
- auto forceUpResult = BridgeAccessible::ForceUp();
- if(forceUpResult == ForceUpResult::ALREADY_UP)
+ //TODO: checking mBusName is enough? or a new variable to check bridge state?
+ auto forceUpResult = InitializeData();
+ if(forceUpResult == ForceUpResult::ALREADY_UP && !GetBusName().empty())
{
return forceUpResult;
}
- else if(forceUpResult == ForceUpResult::FAILED)
+
+ forceUpResult = InitializeDbus();
+ if(forceUpResult == ForceUpResult::FAILED)
{
if(!mForceUpTimer)
{
@@ -329,20 +636,10 @@ public:
return forceUpResult;
}
- BridgeAccessible::RegisterInterfaces();
- BridgeComponent::RegisterInterfaces();
- BridgeCollection::RegisterInterfaces();
- BridgeAction::RegisterInterfaces();
- BridgeValue::RegisterInterfaces();
- BridgeText::RegisterInterfaces();
- BridgeEditableText::RegisterInterfaces();
- BridgeSelection::RegisterInterfaces();
- BridgeApplication::RegisterInterfaces();
- BridgeHypertext::RegisterInterfaces();
- BridgeHyperlink::RegisterInterfaces();
- BridgeSocket::RegisterInterfaces();
- BridgeTable::RegisterInterfaces();
- BridgeTableCell::RegisterInterfaces();
+ for (const auto& bridgeObject : mBridgeObjects)
+ {
+ RegisterInterfaces(bridgeObject);
+ }
RegisterAccessible(&mApplication);
@@ -370,6 +667,11 @@ public:
return ForceUpResult::JUST_STARTED;
}
+ bool IsUp() const override
+ {
+ return bool(mData);
+ }
+
/**
* @brief Sends a signal to dbus that the window is created.
*
@@ -841,14 +1143,6 @@ public:
});
}
- void SetExtentsOffset(std::int32_t x, std::int32_t y) override
- {
- if(mData)
- {
- mData->mExtentsOffset = {x, y};
- }
- }
-
void SetPreferredBusName(std::string_view preferredBusName) override
{
if(preferredBusName == mPreferredBusName)
@@ -1181,7 +1475,351 @@ public:
{"", "root"});
}
+ const std::string& GetBusName() const override
+ {
+ static std::string empty;
+ return mData ? mData->mBusName : empty;
+ }
+
+ void AddTopLevelWindow(Dali::Accessibility::Accessible* windowAccessible) override
+ {
+ if(windowAccessible->GetInternalActor() == nullptr)
+ {
+ return;
+ }
+
+ // Prevent adding the default window twice.
+ if(!mApplication.mChildren.empty() &&
+ mApplication.mChildren[0]->GetInternalActor() == windowAccessible->GetInternalActor())
+ {
+ return;
+ }
+
+ // Adds Window to a list of Windows.
+ mApplication.mChildren.push_back(windowAccessible);
+ windowAccessible->SetIsOnRootLevel();
+ }
+
+ void RemoveTopLevelWindow(Dali::Accessibility::Accessible* windowAccessible) override
+ {
+ for(auto i = 0u; i < mApplication.mChildren.size(); ++i)
+ {
+ if(mApplication.mChildren[i] == windowAccessible)
+ {
+ mApplication.mChildren.erase(mApplication.mChildren.begin() + i);
+ break;
+ }
+ }
+ }
+
+ void RegisterDefaultLabel(Dali::Accessibility::Accessible* object) override
+ {
+ mBridgeAccessibleRef.RegisterDefaultLabel(object);
+ }
+
+ void UnregisterDefaultLabel(Dali::Accessibility::Accessible* object) override
+ {
+ mBridgeAccessibleRef.UnregisterDefaultLabel(object);
+ }
+
+ Dali::Accessibility::Accessible* GetApplication() const override
+ {
+ return &mApplication;
+ }
+
+ void SetApplicationName(std::string name) override
+ {
+ mApplication.mName = std::move(name);
+ }
+
+ void SetToolkitName(std::string_view toolkitName) override
+ {
+ mApplication.mToolkitName = std::string{toolkitName};
+ }
+
+ void RegisterAccessible(const Accessible* object) override
+ {
+ assert(mBridgeData);
+ mBridgeData->AddKnownObject(object);
+ }
+
+ void UnregisterAccessible(const Accessible* object) override
+ {
+ assert(mBridgeData);
+ mBridgeData->RemoveKnownObject(object);
+ }
+
+ Accessible* FindByPath(const std::string& name) const override
+ {
+ try
+ {
+ return mBridgeData->Find(name);
+ }
+ catch(std::domain_error&)
+ {
+ return nullptr;
+ }
+ }
+
private:
+
+ /**
+ * @brief Adds CoalescableMessages, Accessible, and delay time to mCoalescableMessages.
+ *
+ * @param[in] kind CoalescableMessages enum value
+ * @param[in] obj Accessible object
+ * @param[in] delay The delay time
+ * @param[in] functor The function to be called // NEED TO UPDATE!
+ */
+ void AddCoalescableMessage(CoalescableMessages kind, Dali::Accessibility::Accessible* obj, float delay, std::function<void()> functor)
+ {
+ if(delay < 0)
+ {
+ delay = 0;
+ }
+ auto countdownBase = static_cast<unsigned int>(delay * 10);
+
+ auto it = mCoalescableMessages.insert({{kind, obj}, {countdownBase, countdownBase, {}}});
+ if(it.second)
+ {
+ functor();
+ }
+ else
+ {
+ std::get<1>(it.first->second) = countdownBase;
+ std::get<2>(it.first->second) = std::move(functor);
+ }
+
+ if(!tickTimer)
+ {
+ tickTimer = Dali::Timer::New(100);
+ tickTimer.TickSignal().Connect(this, &BridgeImpl::TickCoalescableMessages);
+ }
+
+ if(!tickTimer.IsRunning())
+ {
+ tickTimer.Start();
+ }
+ }
+
+ /**
+ * @brief Removes all CoalescableMessages using Tick signal.
+ *
+ * @return False if mCoalescableMessages is empty, otherwise true.
+ */
+ bool TickCoalescableMessages()
+ {
+ for(auto it = mCoalescableMessages.begin(); it != mCoalescableMessages.end();)
+ {
+ auto& countdown = std::get<0>(it->second);
+ auto countdownBase = std::get<1>(it->second);
+ auto& functor = std::get<2>(it->second);
+ if(countdown)
+ {
+ --countdown;
+ }
+ else
+ {
+ if(functor)
+ {
+ functor();
+ functor = {};
+ countdown = countdownBase;
+ }
+ else
+ {
+ it = mCoalescableMessages.erase(it);
+ continue;
+ }
+ }
+ ++it;
+ }
+ return !mCoalescableMessages.empty();
+ }
+
+ /**
+ * @brief Update registered events.
+ */
+ void UpdateRegisteredEvents()
+ {
+ using ReturnType = std::vector<std::tuple<std::string, std::string>>;
+ mRegistry.method<DBus::ValueOrError<ReturnType>()>("GetRegisteredEvents").asyncCall([this](DBus::ValueOrError<ReturnType> msg) {
+ if(!msg)
+ {
+ LOG() << "Get registered events failed";
+ return;
+ }
+
+ IsBoundsChangedEventAllowed = false;
+
+ ReturnType values = std::get<ReturnType>(msg.getValues());
+ for(long unsigned int i = 0; i < values.size(); i++)
+ {
+ if(!std::get<1>(values[i]).compare("Object:BoundsChanged"))
+ {
+ IsBoundsChangedEventAllowed = true;
+ }
+ }
+ });
+ }
+
+ ForceUpResult InitializeData()
+ {
+ if(mData)
+ {
+ return ForceUpResult::ALREADY_UP;
+ }
+ mData = std::make_shared<Data>();
+ return ForceUpResult::JUST_STARTED;
+ }
+
+ ForceUpResult InitializeDbus()
+ {
+ auto proxy = DBus::DBusClient{dbusLocators::atspi::BUS, dbusLocators::atspi::OBJ_PATH, dbusLocators::atspi::BUS_INTERFACE, DBus::ConnectionType::SESSION};
+ auto addr = proxy.method<std::string()>(dbusLocators::atspi::GET_ADDRESS).call();
+
+ if(!addr)
+ {
+ DALI_LOG_ERROR("failed at call '%s': %s\n", dbusLocators::atspi::GET_ADDRESS, addr.getError().message.c_str());
+ return ForceUpResult::FAILED;
+ }
+
+ mConnectionPtr = DBusWrapper::Installed()->eldbus_address_connection_get_impl(std::get<0>(addr));
+ mData->mBusName = DBus::getConnectionName(mConnectionPtr);
+ mDbusServer = {mConnectionPtr};
+
+ {
+ DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::CACHE)};
+ AddFunctionToInterface(desc, "GetItems", &BridgeImpl::GetItems);
+ mDbusServer.addInterface(AtspiDbusPathCache, desc);
+ }
+ {
+ DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::APPLICATION)};
+ AddGetSetPropertyToInterface(desc, "Id", &BridgeImpl::GetId, &BridgeImpl::SetId);
+ mDbusServer.addInterface(AtspiPath, desc);
+ }
+
+ mRegistry = {AtspiDbusNameRegistry, AtspiDbusPathRegistry, Accessible::GetInterfaceName(AtspiInterface::REGISTRY), mConnectionPtr};
+
+ UpdateRegisteredEvents();
+
+ mRegistry.addSignal<void(void)>("EventListenerRegistered", [this](void) {
+ UpdateRegisteredEvents();
+ });
+
+ mRegistry.addSignal<void(void)>("EventListenerDeregistered", [this](void) {
+ UpdateRegisteredEvents();
+ });
+
+ return ForceUpResult::JUST_STARTED;
+ }
+
+ void ResetResources()
+ {
+ ClearHighlightData();
+ mRegistry = {};
+ mDbusServer = {};
+ mConnectionPtr = {};
+ mRegistryClient = {};
+ mDirectReadingClient = {};
+ mDirectReadingCallbacks.clear();
+ mApplication.mChildren.clear();
+ ClearTimer();
+ }
+
+ void ClearHighlightData()
+ {
+ if(mData && mData->mCurrentlyHighlightedActor)
+ {
+ auto component = dynamic_cast<Component*>(Accessible::Get(mData->mCurrentlyHighlightedActor));
+ if(component)
+ {
+ component->ClearHighlight();
+ }
+ }
+ mData = {};
+ }
+
+ /**
+ * @brief Sets an ID.
+ * @param[in] id An ID (integer value)
+ */
+ void SetId(int id)
+ {
+ mId = id;
+ }
+
+ /**
+ * @brief Gets the ID.
+ * @return The ID to be set
+ */
+ int GetId()
+ {
+ return mId;
+ }
+
+ /**
+ * @brief Gets Items // NEED TO UPDATE!
+ *
+ * @return
+ */
+ auto GetItems() -> DBus::ValueOrError<std::vector<CacheElementType>>
+ {
+ auto root = &mApplication;
+
+ std::vector<CacheElementType> res;
+
+ // TODO: make this usable
+ std::function<void(Accessible*)> proc =
+ [&](Accessible* item) {
+ res.emplace_back(std::move(CreateCacheElement(root)));
+ for(auto i = 0u; i < item->GetChildCount(); ++i)
+ {
+ proc(item->GetChildAtIndex(i));
+ }
+ };
+
+ return res;
+ }
+
+ /**
+ * @brief Creates CacheElement.
+ *
+ * CreateCacheElement method works for GetItems which is a part of ATSPI protocol.
+ * ATSPI client library (libatspi from at-spi2-core) depending on cacheing policy configuration uses GetItems
+ * to pre-load entire accessible tree from application to its own cache in single dbus call.
+ * Otherwise the particular nodes in a tree are cached lazily when client library tries to access them.
+ * @param item Accessible to get information
+ * @return The elements to be cached
+ */
+ auto CreateCacheElement(Accessible* item) -> CacheElementType
+ {
+ if(!item)
+ {
+ return {};
+ }
+
+ auto root = &mApplication;
+ auto parent = item->GetParent();
+
+ std::vector<Address> children;
+ for(auto i = 0u; i < item->GetChildCount(); ++i)
+ {
+ children.emplace_back(item->GetChildAtIndex(i)->GetAddress());
+ }
+
+ return std::make_tuple(
+ item->GetAddress(),
+ root->GetAddress(),
+ parent ? parent->GetAddress() : Address{},
+ children,
+ item->GetInterfacesAsStrings(),
+ item->GetName(),
+ item->GetRole(),
+ item->GetDescription(),
+ item->GetStates().GetRawData());
+ }
+
DBus::DBusClient CreateSocketClient(const Address& socket)
{
return {socket.GetBus(), ATSPI_PREFIX_PATH + socket.GetPath(), Accessible::GetInterfaceName(AtspiInterface::SOCKET), mConnectionPtr};
@@ -1206,6 +1844,12 @@ private:
DBus::releaseBusName(mConnectionPtr, busName);
}
+
+ void RegisterInterfaces(const BridgeBase& bridgeObject)
+ {
+ mDbusServer.addInterface("/", bridgeObject.GetInterface(), true);
+ }
+
}; // BridgeImpl
namespace // unnamed namespace
diff --git a/dali/internal/accessibility/bridge/bridge-selection.cpp b/dali/internal/accessibility/bridge/bridge-selection.cpp
index 071367084..4d45b4d23 100644
--- a/dali/internal/accessibility/bridge/bridge-selection.cpp
+++ b/dali/internal/accessibility/bridge/bridge-selection.cpp
@@ -20,7 +20,10 @@
using namespace Dali::Accessibility;
-void BridgeSelection::RegisterInterfaces()
+BridgeSelection::BridgeSelection(std::shared_ptr<BridgeData> bridgeData)
+: BridgeBase(std::move(bridgeData)) {}
+
+DBus::DBusInterfaceDescription BridgeSelection::GetInterfaces() const
{
DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::SELECTION)};
AddGetPropertyToInterface(desc, "NSelectedChildren", &BridgeSelection::GetSelectedChildrenCount);
@@ -31,12 +34,13 @@ void BridgeSelection::RegisterInterfaces()
AddFunctionToInterface(desc, "SelectAll", &BridgeSelection::SelectAll);
AddFunctionToInterface(desc, "ClearSelection", &BridgeSelection::ClearSelection);
AddFunctionToInterface(desc, "DeselectChild", &BridgeSelection::DeselectChild);
- mDbusServer.addInterface("/", desc, true);
+
+ return desc;
}
Selection* BridgeSelection::FindSelf() const
{
- return FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::SELECTION>();
+ return mBridgeData->FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::SELECTION>();
}
DBus::ValueOrError<int32_t> BridgeSelection::GetSelectedChildrenCount()
diff --git a/dali/internal/accessibility/bridge/bridge-socket.cpp b/dali/internal/accessibility/bridge/bridge-socket.cpp
index 621a43335..af99a0ac3 100644
--- a/dali/internal/accessibility/bridge/bridge-socket.cpp
+++ b/dali/internal/accessibility/bridge/bridge-socket.cpp
@@ -20,7 +20,10 @@
using namespace Dali::Accessibility;
-void BridgeSocket::RegisterInterfaces()
+BridgeSocket::BridgeSocket(std::shared_ptr<BridgeData> bridgeData)
+: BridgeBase(std::move(bridgeData)) {}
+
+DBus::DBusInterfaceDescription BridgeSocket::GetInterfaces() const
{
DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::SOCKET)};
@@ -28,12 +31,12 @@ void BridgeSocket::RegisterInterfaces()
AddFunctionToInterface(desc, "Unembed", &BridgeSocket::Unembed);
AddFunctionToInterface(desc, "SetOffset", &BridgeSocket::SetOffset);
- mDbusServer.addInterface("/", desc, true);
+ return desc;
}
Socket* BridgeSocket::FindSelf() const
{
- return FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::SOCKET>();
+ return mBridgeData->FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::SOCKET>();
}
DBus::ValueOrError<Address> BridgeSocket::Embed(Address plug)
diff --git a/dali/internal/accessibility/bridge/bridge-table-cell.cpp b/dali/internal/accessibility/bridge/bridge-table-cell.cpp
index b4680f8a7..09133e4d1 100644
--- a/dali/internal/accessibility/bridge/bridge-table-cell.cpp
+++ b/dali/internal/accessibility/bridge/bridge-table-cell.cpp
@@ -23,7 +23,10 @@
using namespace Dali::Accessibility;
-void BridgeTableCell::RegisterInterfaces()
+BridgeTableCell::BridgeTableCell(std::shared_ptr<BridgeData> bridgeData)
+: BridgeBase(std::move(bridgeData)) {}
+
+DBus::DBusInterfaceDescription BridgeTableCell::GetInterfaces() const
{
DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::TABLE_CELL)};
@@ -33,12 +36,12 @@ void BridgeTableCell::RegisterInterfaces()
AddGetPropertyToInterface(desc, "ColumnSpan", &BridgeTableCell::GetCellColumnSpan);
AddFunctionToInterface(desc, "GetRowColumnSpan", &BridgeTableCell::GetCellRowColumnSpan);
- mDbusServer.addInterface("/", desc, true);
+ return desc;
}
TableCell* BridgeTableCell::FindSelf() const
{
- return FindCurrentObjectWithInterface<AtspiInterface::TABLE_CELL>();
+ return mBridgeData->FindCurrentObjectWithInterface<AtspiInterface::TABLE_CELL>();
}
DBus::ValueOrError<Accessible*> BridgeTableCell::GetTable()
diff --git a/dali/internal/accessibility/bridge/bridge-table.cpp b/dali/internal/accessibility/bridge/bridge-table.cpp
index 81ec834cc..df56bd899 100644
--- a/dali/internal/accessibility/bridge/bridge-table.cpp
+++ b/dali/internal/accessibility/bridge/bridge-table.cpp
@@ -23,7 +23,10 @@
using namespace Dali::Accessibility;
-void BridgeTable::RegisterInterfaces()
+BridgeTable::BridgeTable(std::shared_ptr<BridgeData> bridgeData)
+: BridgeBase(std::move(bridgeData)) {}
+
+DBus::DBusInterfaceDescription BridgeTable::GetInterfaces() const
{
DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::TABLE)};
@@ -54,12 +57,12 @@ void BridgeTable::RegisterInterfaces()
AddFunctionToInterface(desc, "RemoveColumnSelection", &BridgeTable::RemoveColumnSelection);
AddFunctionToInterface(desc, "GetRowColumnExtentsAtIndex", &BridgeTable::GetRowColumnSpan);
- mDbusServer.addInterface("/", desc, true);
+ return desc;
}
Table* BridgeTable::FindSelf() const
{
- return FindCurrentObjectWithInterface<AtspiInterface::TABLE>();
+ return mBridgeData->FindCurrentObjectWithInterface<AtspiInterface::TABLE>();
}
DBus::ValueOrError<std::int32_t> BridgeTable::GetRowCount()
diff --git a/dali/internal/accessibility/bridge/bridge-text.cpp b/dali/internal/accessibility/bridge/bridge-text.cpp
index 2707e4415..4276d52d6 100644
--- a/dali/internal/accessibility/bridge/bridge-text.cpp
+++ b/dali/internal/accessibility/bridge/bridge-text.cpp
@@ -23,7 +23,10 @@
using namespace Dali::Accessibility;
-void BridgeText::RegisterInterfaces()
+BridgeText::BridgeText(std::shared_ptr<BridgeData> bridgeData)
+: BridgeBase(std::move(bridgeData)) {}
+
+DBus::DBusInterfaceDescription BridgeText::GetInterfaces() const
{
// The second arguments below are the names (or signatures) of DBus methods.
// Screen Reader will call the methods with the exact names as specified in the AT-SPI Text interface:
@@ -39,12 +42,13 @@ void BridgeText::RegisterInterfaces()
AddFunctionToInterface(desc, "SetSelection", &BridgeText::SetRangeOfSelection);
AddFunctionToInterface(desc, "RemoveSelection", &BridgeText::RemoveSelection);
AddFunctionToInterface(desc, "GetRangeExtents", &BridgeText::GetRangeExtents);
- mDbusServer.addInterface("/", desc, true);
+
+ return desc;
}
Text* BridgeText::FindSelf() const
{
- return FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::TEXT>();
+ return mAccessibleObjectsHolder->FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::TEXT>();
}
DBus::ValueOrError<std::string> BridgeText::GetText(int startOffset, int endOffset)
diff --git a/dali/internal/accessibility/bridge/bridge-text.h b/dali/internal/accessibility/bridge/bridge-text.h
index cc50c3f27..46a33e7ba 100644
--- a/dali/internal/accessibility/bridge/bridge-text.h
+++ b/dali/internal/accessibility/bridge/bridge-text.h
@@ -27,14 +27,6 @@
*/
class BridgeText : public virtual BridgeBase
{
-protected:
- BridgeText() = default;
-
- /**
- * @brief Registers Text functions to dbus interfaces.
- */
- void RegisterInterfaces();
-
/**
* @brief Returns the Text object of the currently executed DBus method call.
*
@@ -43,6 +35,13 @@ protected:
Dali::Accessibility::Text* FindSelf() const;
public:
+ explicit BridgeText(std::shared_ptr<BridgeData> bridgeData);
+
+ /**
+ * @brief Gets dbus interface description for Text type.
+ */
+ DBus::DBusInterfaceDescription GetInterfaces() override;
+
/**
* @copydoc Dali::Accessibility::Text::GetText()
*/
diff --git a/dali/internal/accessibility/bridge/bridge-value.cpp b/dali/internal/accessibility/bridge/bridge-value.cpp
index 37e752be2..fad773def 100644
--- a/dali/internal/accessibility/bridge/bridge-value.cpp
+++ b/dali/internal/accessibility/bridge/bridge-value.cpp
@@ -20,11 +20,10 @@
using namespace Dali::Accessibility;
-BridgeValue::BridgeValue()
-{
-}
+BridgeValue::BridgeValue(std::shared_ptr<BridgeData> bridgeData)
+: BridgeBase(std::move(bridgeData)) {}
-void BridgeValue::RegisterInterfaces()
+DBus::DBusInterfaceDescription BridgeValue::GetInterfaces() const
{
DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::VALUE)};
AddGetSetPropertyToInterface(desc, "CurrentValue", &BridgeValue::GetCurrentValue, &BridgeValue::SetCurrentValue);
@@ -32,12 +31,13 @@ void BridgeValue::RegisterInterfaces()
AddGetPropertyToInterface(desc, "MaximumValue", &BridgeValue::GetMaximumValue);
AddGetPropertyToInterface(desc, "MinimumIncrement", &BridgeValue::GetMinimumIncrement);
AddGetPropertyToInterface(desc, "MinimumValue", &BridgeValue::GetMinimumValue);
- mDbusServer.addInterface("/", desc, true);
+
+ return desc;
}
Value* BridgeValue::FindSelf() const
{
- return FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::VALUE>();
+ return mBridgeData->FindCurrentObjectWithInterface<Dali::Accessibility::AtspiInterface::VALUE>();
}
double BridgeValue::GetCurrentValue()
diff --git a/dali/internal/accessibility/bridge/dummy/dummy-atspi.h b/dali/internal/accessibility/bridge/dummy/dummy-atspi.h
index a5ed28962..031a36705 100644
--- a/dali/internal/accessibility/bridge/dummy/dummy-atspi.h
+++ b/dali/internal/accessibility/bridge/dummy/dummy-atspi.h
@@ -54,11 +54,6 @@ struct DummyBridge : Dali::Accessibility::Bridge
{
}
- Dali::Accessibility::Accessible* GetDefaultLabel(Dali::Accessibility::Accessible* root) const override
- {
- return nullptr;
- }
-
void SetApplicationName(std::string name) override
{
}
@@ -126,6 +121,11 @@ struct DummyBridge : Dali::Accessibility::Bridge
{
}
+ bool IsUp() const override
+ {
+ return false;
+ }
+
void EmitCursorMoved(Accessibility::Accessible* obj, unsigned int cursorPosition) override
{
}
@@ -226,11 +226,15 @@ struct DummyBridge : Dali::Accessibility::Bridge
{
}
- void SetExtentsOffset(std::int32_t x, std::int32_t y) override
+ void SetPreferredBusName(std::string_view preferredBusName) override
{
}
- void SetPreferredBusName(std::string_view preferredBusName) override
+ void RegisterAccessible(const Accessible* object) override
+ {
+ }
+
+ void UnregisterAccessible(const Accessible* object) override
{
}
};