#include <dali/internal/accessibility/bridge/bridge-base.h>
// EXTERNAL INCLUDES
+#include <dali/devel-api/common/stage.h>
#include <atomic>
#include <cstdlib>
#include <memory>
static Dali::Timer tickTimer;
-BridgeBase::~BridgeBase()
+BridgeBase::BridgeBase()
{
}
-BridgeBase::BridgeBase()
+BridgeBase::~BridgeBase()
{
+ mApplication.mChildren.clear();
+ mApplication.mWindows.clear();
}
-void BridgeBase::addFilteredEvent(FilteredEvents kind, Dali::Accessibility::Accessible* obj, float delay, std::function<void()> functor)
+void BridgeBase::AddFilteredEvent(FilteredEvents kind, Dali::Accessibility::Accessible* obj, float delay, std::function<void()> functor)
{
if(delay < 0)
{
delay = 0;
}
- auto it = filteredEvents.insert({{kind, obj}, {static_cast<unsigned int>(delay * 10), {}}});
+ auto it = mFilteredEvents.insert({{kind, obj}, {static_cast<unsigned int>(delay * 10), {}}});
if(it.second)
{
functor();
if(!tickTimer)
{
tickTimer = Dali::Timer::New(100);
- tickTimer.TickSignal().Connect(this, &BridgeBase::tickFilteredEvents);
+ tickTimer.TickSignal().Connect(this, &BridgeBase::TickFilteredEvents);
}
}
-bool BridgeBase::tickFilteredEvents()
+bool BridgeBase::TickFilteredEvents()
{
- for(auto it = filteredEvents.begin(); it != filteredEvents.end();)
+ for(auto it = mFilteredEvents.begin(); it != mFilteredEvents.end();)
{
if(it->second.first)
{
}
else
{
- it = filteredEvents.erase(it);
+ it = mFilteredEvents.erase(it);
continue;
}
}
++it;
}
- return !filteredEvents.empty();
+ return !mFilteredEvents.empty();
}
-void BridgeBase::RegisteredEventsUpdate()
+void BridgeBase::UpdateRegisteredEvents()
{
using ReturnType = std::vector<std::tuple<std::string, std::string>>;
- registry.method<DBus::ValueOrError<ReturnType>()>("GetRegisteredEvents").asyncCall([this](DBus::ValueOrError<ReturnType> msg) {
+ mRegistry.method<DBus::ValueOrError<ReturnType>()>("GetRegisteredEvents").asyncCall([this](DBus::ValueOrError<ReturnType> msg) {
if(!msg)
{
LOG() << "Get registered events failed";
return;
}
- allowObjectBoundsChangedEvent = false;
+ 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"))
{
- allowObjectBoundsChangedEvent = true;
+ IsBoundsChangedEventAllowed = true;
}
}
});
BridgeBase::ForceUpResult BridgeBase::ForceUp()
{
- if(Bridge::ForceUp() == ForceUpResult::ALREADY_UP)
+ //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;
}
if(!addr)
{
- throw std::domain_error{std::string("failed at call '") + dbusLocators::atspi::GET_ADDRESS + "': " + addr.getError().message};
+ DALI_LOG_ERROR("failed at call '%s': %s\n", dbusLocators::atspi::GET_ADDRESS, addr.getError().message.c_str());
+ return ForceUpResult::FAILED;
}
- con = DBusWrapper::Installed()->eldbus_address_connection_get_impl(std::get<0>(addr));
- mData->mBusName = DBus::getConnectionName(con);
- dbusServer = {con};
+ mConnectionPtr = DBusWrapper::Installed()->eldbus_address_connection_get_impl(std::get<0>(addr));
+ mData->mBusName = DBus::getConnectionName(mConnectionPtr);
+ mDbusServer = {mConnectionPtr};
{
- DBus::DBusInterfaceDescription desc{"org.a11y.atspi.Cache"};
+ DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceCache};
AddFunctionToInterface(desc, "GetItems", &BridgeBase::GetItems);
- dbusServer.addInterface("/org/a11y/atspi/cache", desc);
+ mDbusServer.addInterface(AtspiDbusPathCache, desc);
}
{
- DBus::DBusInterfaceDescription desc{"org.a11y.atspi.Application"};
- AddGetSetPropertyToInterface(desc, "Id", &BridgeBase::IdGet, &BridgeBase::IdSet);
- dbusServer.addInterface(AtspiPath, desc);
+ DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceApplication};
+ AddGetSetPropertyToInterface(desc, "Id", &BridgeBase::GetId, &BridgeBase::SetId);
+ mDbusServer.addInterface(AtspiPath, desc);
}
- registry = {AtspiDbusNameRegistry, AtspiDbusPathRegistry, AtspiDbusInterfaceRegistry, con};
+ mRegistry = {AtspiDbusNameRegistry, AtspiDbusPathRegistry, AtspiDbusInterfaceRegistry, mConnectionPtr};
- RegisteredEventsUpdate();
+ UpdateRegisteredEvents();
- registry.addSignal<void(void)>("EventListenerRegistered", [this](void) {
- RegisteredEventsUpdate();
+ mRegistry.addSignal<void(void)>("EventListenerRegistered", [this](void) {
+ UpdateRegisteredEvents();
});
- registry.addSignal<void(void)>("EventListenerDeregistered", [this](void) {
- RegisteredEventsUpdate();
+ mRegistry.addSignal<void(void)>("EventListenerDeregistered", [this](void) {
+ UpdateRegisteredEvents();
});
return ForceUpResult::JUST_STARTED;
void BridgeBase::ForceDown()
{
Bridge::ForceDown();
- registry = {};
- dbusServer = {};
- con = {};
+ mRegistry = {};
+ mDbusServer = {};
+ mConnectionPtr = {};
}
const std::string& BridgeBase::GetBusName() const
}
}
-void BridgeBase::AddPopup(Accessible* object)
+void BridgeBase::OnWindowVisibilityChanged(Dali::Window window, bool visible)
{
- if(std::find(popups.begin(), popups.end(), object) != popups.end())
+ if(visible)
{
- return;
+ // TODO : Should we check 'out of screen' here? -> Then, we need an actor of this change.
+ Dali::Accessibility::Bridge::GetCurrentBridge()->WindowShown(window); // Called when Window is shown.
}
- popups.push_back(object);
- if(IsUp())
+ else
{
- object->Emit(WindowEvent::ACTIVATE, 0);
+ Dali::Accessibility::Bridge::GetCurrentBridge()->WindowHidden(window); // Called when Window is hidden and iconified.
}
}
-void BridgeBase::RemovePopup(Accessible* object)
+void BridgeBase::OnWindowFocusChanged(Dali::Window window, bool focusIn)
{
- auto it = std::find(popups.begin(), popups.end(), object);
- if(it == popups.end())
+ if(focusIn)
+ {
+ Dali::Accessibility::Bridge::GetCurrentBridge()->WindowFocused(window); // Called when Window is focused.
+ }
+ else
+ {
+ Dali::Accessibility::Bridge::GetCurrentBridge()->WindowUnfocused(window); // Called when Window is out of focus.
+ }
+}
+
+void BridgeBase::AddTopLevelWindow(Accessible* windowAccessible)
+{
+ if(windowAccessible->GetInternalActor() == nullptr)
{
return;
}
- popups.erase(it);
- if(IsUp())
+
+ // 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);
+
+ RegisterDefaultLabel(windowAccessible);
+
+ Dali::Window window = Dali::DevelWindow::Get(windowAccessible->GetInternalActor());
+ if(window)
+ {
+ mApplication.mWindows.push_back(window);
+ Dali::DevelWindow::VisibilityChangedSignal(window).Connect(this, &BridgeBase::OnWindowVisibilityChanged);
+ window.FocusChangeSignal().Connect(this, &BridgeBase::OnWindowFocusChanged);
+ }
+}
+
+void BridgeBase::RemoveTopLevelWindow(Accessible* windowAccessible)
+{
+ for(auto i = 0u; i < mApplication.mWindows.size(); ++i)
{
- object->Emit(WindowEvent::DEACTIVATE, 0);
- if(popups.empty())
+ if(windowAccessible->GetInternalActor() == mApplication.mWindows[i].GetRootLayer())
{
- application.children.back()->Emit(WindowEvent::ACTIVATE, 0);
+ Dali::DevelWindow::VisibilityChangedSignal(mApplication.mWindows[i]).Disconnect(this, &BridgeBase::OnWindowVisibilityChanged);
+ mApplication.mWindows[i].FocusChangeSignal().Disconnect(this, &BridgeBase::OnWindowFocusChanged);
+ mApplication.mWindows.erase(mApplication.mWindows.begin() + i);
+ break;
}
- else
+ }
+
+ UnregisterDefaultLabel(windowAccessible);
+
+ for(auto i = 0u; i < mApplication.mChildren.size(); ++i)
+ {
+ if(mApplication.mChildren[i] == windowAccessible)
{
- popups.back()->Emit(WindowEvent::ACTIVATE, 0);
+ mApplication.mChildren.erase(mApplication.mChildren.begin() + i);
+ break;
}
}
}
-void BridgeBase::AddTopLevelWindow(Accessible* root)
+void BridgeBase::RegisterDefaultLabel(Accessible* object)
{
- application.children.push_back(root);
- SetIsOnRootLevel(root);
+ if(std::find(mDefaultLabels.begin(), mDefaultLabels.end(), object) == mDefaultLabels.end())
+ {
+ mDefaultLabels.push_back(object);
+ }
}
-void BridgeBase::RemoveTopLevelWindow(Accessible* root)
+void BridgeBase::UnregisterDefaultLabel(Accessible* object)
{
- for(auto i = 0u; i < application.children.size(); ++i)
+ auto it = std::find(mDefaultLabels.begin(), mDefaultLabels.end(), object);
+ if(it != mDefaultLabels.end())
{
- if(application.children[i] == root)
- {
- application.children.erase(application.children.begin() + i);
- break;
- }
+ mDefaultLabels.erase(it);
}
}
{
if(path == "root")
{
- return &application;
+ return &mApplication;
}
- void* accessible;
+ void* accessible;
std::istringstream tmp{path};
if(!(tmp >> accessible))
{
Accessible* BridgeBase::FindSelf() const
{
- auto path = DBus::DBusServer::getCurrentObjectPath();
+ auto path = DBus::DBusServer::getCurrentObjectPath();
auto size = strlen(AtspiPath);
if(path.size() <= size)
{
return Find(StripPrefix(path));
}
-void BridgeBase::IdSet(int id)
+void BridgeBase::SetId(int id)
{
- this->id = id;
+ this->mId = id;
}
-int BridgeBase::IdGet()
+int BridgeBase::GetId()
{
- return this->id;
+ return this->mId;
}
auto BridgeBase::GetItems() -> DBus::ValueOrError<std::vector<CacheElementType>>
{
- auto root = &application;
+ auto root = &mApplication;
std::vector<CacheElementType> res;
return {};
}
- auto root = &application;
+ auto root = &mApplication;
auto parent = item->GetParent();
std::vector<Address> children;