#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;
mApplication.mChildren.clear();
}
-void BridgeBase::AddFilteredEvent(FilteredEvents kind, Dali::Accessibility::Accessible* obj, float delay, std::function<void()> functor)
+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 = mFilteredEvents.insert({{kind, obj}, {static_cast<unsigned int>(delay * 10), {}}});
+ auto it = mCoalescableMessages.insert({{kind, obj}, {countdownBase, countdownBase, {}}});
if(it.second)
{
functor();
}
else
{
- it.first->second.second = std::move(functor);
+ 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::TickFilteredEvents);
+ tickTimer.TickSignal().Connect(this, &BridgeBase::TickCoalescableMessages);
+ }
+
+ if(!tickTimer.IsRunning())
+ {
+ tickTimer.Start();
}
}
-bool BridgeBase::TickFilteredEvents()
+bool BridgeBase::TickCoalescableMessages()
{
- for(auto it = mFilteredEvents.begin(); it != mFilteredEvents.end();)
+ for(auto it = mCoalescableMessages.begin(); it != mCoalescableMessages.end();)
{
- if(it->second.first)
+ auto& countdown = std::get<0>(it->second);
+ auto countdownBase = std::get<1>(it->second);
+ auto& functor = std::get<2>(it->second);
+ if(countdown)
{
- --it->second.first;
+ --countdown;
}
else
{
- if(it->second.second)
+ if(functor)
{
- it->second.second();
- it->second.second = {};
+ functor();
+ functor = {};
+ countdown = countdownBase;
}
else
{
- it = mFilteredEvents.erase(it);
+ it = mCoalescableMessages.erase(it);
continue;
}
}
++it;
}
- return !mFilteredEvents.empty();
+ return !mCoalescableMessages.empty();
}
void BridgeBase::UpdateRegisteredEvents()
// Adds Window to a list of Windows.
mApplication.mChildren.push_back(windowAccessible);
SetIsOnRootLevel(windowAccessible);
-
- RegisterDefaultLabel(windowAccessible);
}
void BridgeBase::RemoveTopLevelWindow(Accessible* windowAccessible)
{
- UnregisterDefaultLabel(windowAccessible);
-
for(auto i = 0u; i < mApplication.mChildren.size(); ++i)
{
if(mApplication.mChildren[i] == windowAccessible)
}
}
+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)
{
- if(std::find(mDefaultLabels.begin(), mDefaultLabels.end(), object) == mDefaultLabels.end())
+ 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)
{
- mDefaultLabels.push_back(object);
+ // 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)
{
- auto it = std::find(mDefaultLabels.begin(), mDefaultLabels.end(), object);
- if(it != mDefaultLabels.end())
+ 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())
{
- mDefaultLabels.erase(it);
+ 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)
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;
+}