X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Faccessibility%2Fbridge%2Fbridge-base.cpp;h=a819f259a9685d59939437002f2ea0fee25795d5;hb=6851c4bb5f5a3f0f36f606f2a84a2ef9739d2643;hp=ee1987f305ca923e67f1e9992b71f9ed840daea2;hpb=4340b7d75db9314f270b09343c703fc2961094c4;p=platform%2Fcore%2Fuifw%2Fdali-adaptor.git diff --git a/dali/internal/accessibility/bridge/bridge-base.cpp b/dali/internal/accessibility/bridge/bridge-base.cpp index ee1987f..a819f25 100644 --- a/dali/internal/accessibility/bridge/bridge-base.cpp +++ b/dali/internal/accessibility/bridge/bridge-base.cpp @@ -19,73 +19,87 @@ #include // EXTERNAL INCLUDES +#include #include #include #include // INTERNAL INCLUDES +#include #include using namespace Dali::Accessibility; static Dali::Timer tickTimer; -BridgeBase::~BridgeBase() +BridgeBase::BridgeBase() { } -BridgeBase::BridgeBase() +BridgeBase::~BridgeBase() { + mApplication.mChildren.clear(); } -void BridgeBase::AddFilteredEvent(FilteredEvents kind, Dali::Accessibility::Accessible* obj, float delay, std::function functor) +void BridgeBase::AddCoalescableMessage(CoalescableMessages kind, Dali::Accessibility::Accessible* obj, float delay, std::function functor) { if(delay < 0) { delay = 0; } + auto countdownBase = static_cast(delay * 10); - auto it = mFilteredEvents.insert({{kind, obj}, {static_cast(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() @@ -113,7 +127,8 @@ void BridgeBase::UpdateRegisteredEvents() 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; } @@ -122,7 +137,8 @@ BridgeBase::ForceUpResult BridgeBase::ForceUp() 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; } mConnectionPtr = DBusWrapper::Installed()->eldbus_address_connection_get_impl(std::get<0>(addr)); @@ -130,17 +146,17 @@ BridgeBase::ForceUpResult BridgeBase::ForceUp() mDbusServer = {mConnectionPtr}; { - DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceCache}; + DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::CACHE)}; AddFunctionToInterface(desc, "GetItems", &BridgeBase::GetItems); mDbusServer.addInterface(AtspiDbusPathCache, desc); } { - DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceApplication}; + DBus::DBusInterfaceDescription desc{Accessible::GetInterfaceName(AtspiInterface::APPLICATION)}; AddGetSetPropertyToInterface(desc, "Id", &BridgeBase::GetId, &BridgeBase::SetId); mDbusServer.addInterface(AtspiPath, desc); } - mRegistry = {AtspiDbusNameRegistry, AtspiDbusPathRegistry, AtspiDbusInterfaceRegistry, mConnectionPtr}; + mRegistry = {AtspiDbusNameRegistry, AtspiDbusPathRegistry, Accessible::GetInterfaceName(AtspiInterface::REGISTRY), mConnectionPtr}; UpdateRegisteredEvents(); @@ -181,58 +197,99 @@ Accessible* BridgeBase::FindByPath(const std::string& name) const } } -void BridgeBase::AddPopup(Accessible* object) +void BridgeBase::AddTopLevelWindow(Accessible* windowAccessible) { - if(std::find(mPopups.begin(), mPopups.end(), object) != mPopups.end()) + if(windowAccessible->GetInternalActor() == nullptr) { return; } - mPopups.push_back(object); - if(IsUp()) + + // Prevent adding the default window twice. + if(!mApplication.mChildren.empty() && + mApplication.mChildren[0]->GetInternalActor() == windowAccessible->GetInternalActor()) { - object->Emit(WindowEvent::ACTIVATE, 0); + return; } + + // Adds Window to a list of Windows. + mApplication.mChildren.push_back(windowAccessible); + SetIsOnRootLevel(windowAccessible); } -void BridgeBase::RemovePopup(Accessible* object) +void BridgeBase::RemoveTopLevelWindow(Accessible* windowAccessible) { - auto it = std::find(mPopups.begin(), mPopups.end(), object); - if(it == mPopups.end()) + 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 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; } - mPopups.erase(it); - if(IsUp()) + auto it = std::find_if(mDefaultLabels.begin(), mDefaultLabels.end(), [object](const DefaultLabelType& label) { + return object == label.second; + }); + + if(it == mDefaultLabels.end()) { - object->Emit(WindowEvent::DEACTIVATE, 0); - if(mPopups.empty()) - { - mApplication.mChildren.back()->Emit(WindowEvent::ACTIVATE, 0); - } - else - { - mPopups.back()->Emit(WindowEvent::ACTIVATE, 0); - } + 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::AddTopLevelWindow(Accessible* root) +void BridgeBase::UnregisterDefaultLabel(Accessible* object) { - mApplication.mChildren.push_back(root); - SetIsOnRootLevel(root); + CompressDefaultLabels(); + + mDefaultLabels.remove_if([object](const DefaultLabelType& label) { + return object == label.second; + }); } -void BridgeBase::RemoveTopLevelWindow(Accessible* root) +Accessible* BridgeBase::GetDefaultLabel(Accessible* root) const { - for(auto i = 0u; i < mApplication.mChildren.size(); ++i) + Dali::WeakHandle window = GetWindow(root); + if(!window.GetBaseHandle()) { - if(mApplication.mChildren[i] == root) - { - mApplication.mChildren.erase(mApplication.mChildren.begin() + i); - break; - } + 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) @@ -248,7 +305,7 @@ Accessible* BridgeBase::Find(const std::string& path) const return &mApplication; } - void* accessible; + void* accessible; std::istringstream tmp{path}; if(!(tmp >> accessible)) { @@ -256,7 +313,7 @@ Accessible* BridgeBase::Find(const std::string& path) const } auto it = mData->mKnownObjects.find(static_cast(accessible)); - if(it == mData->mKnownObjects.end()) + if(it == mData->mKnownObjects.end() || (*it)->IsHidden()) { throw std::domain_error{"unknown object '" + path + "'"}; } @@ -270,9 +327,9 @@ Accessible* BridgeBase::Find(const Address& ptr) const return Find(ptr.GetPath()); } -Accessible* BridgeBase::FindSelf() const +Accessible* BridgeBase::FindCurrentObject() const { - auto path = DBus::DBusServer::getCurrentObjectPath(); + auto path = DBus::DBusServer::getCurrentObjectPath(); auto size = strlen(AtspiPath); if(path.size() <= size) { @@ -338,9 +395,23 @@ auto BridgeBase::CreateCacheElement(Accessible* item) -> CacheElementType root->GetAddress(), parent ? parent->GetAddress() : Address{}, children, - item->GetInterfaces(), + item->GetInterfacesAsStrings(), item->GetName(), item->GetRole(), item->GetDescription(), item->GetStates().GetRawData()); } + +Dali::WeakHandle BridgeBase::GetWindow(Dali::Accessibility::Accessible* accessible) +{ + Dali::WeakHandle windowHandle; + Dali::Actor actor = accessible ? accessible->GetInternalActor() : Dali::Actor(); + + if(actor) + { + Dali::Window window = Dali::DevelWindow::Get(actor); + windowHandle = {window}; + } + + return windowHandle; +}