X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Faccessibility%2Fbridge%2Fbridge-base.cpp;h=30e6cf4f9f5f8662d6089bf3cb39f6dca2a481da;hb=HEAD;hp=9f88d3c7d0f436c4bd0aba01a0b207aa031658ee;hpb=bf2f87675e4b2a16a3f8f19afe7a3f483d0d22e7;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 9f88d3c..ba4e154 100644 --- a/dali/internal/accessibility/bridge/bridge-base.cpp +++ b/dali/internal/accessibility/bridge/bridge-base.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2024 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ #include // INTERNAL INCLUDES +#include #include using namespace Dali::Accessibility; @@ -38,57 +39,67 @@ BridgeBase::BridgeBase() BridgeBase::~BridgeBase() { mApplication.mChildren.clear(); - mApplication.mWindows.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() @@ -135,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(); @@ -163,6 +174,8 @@ BridgeBase::ForceUpResult BridgeBase::ForceUp() void BridgeBase::ForceDown() { Bridge::ForceDown(); + tickTimer.Reset(); + mCoalescableMessages.clear(); mRegistry = {}; mDbusServer = {}; mConnectionPtr = {}; @@ -186,31 +199,6 @@ Accessible* BridgeBase::FindByPath(const std::string& name) const } } -void BridgeBase::OnWindowVisibilityChanged(Dali::Window window, bool visible) -{ - if(visible) - { - // 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. - } - else - { - Dali::Accessibility::Bridge::GetCurrentBridge()->WindowHidden(window); // Called when Window is hidden and iconified. - } -} - -void BridgeBase::OnWindowFocusChanged(Dali::Window window, bool focusIn) -{ - 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) @@ -228,34 +216,10 @@ void BridgeBase::AddTopLevelWindow(Accessible* windowAccessible) // 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) - { - if(windowAccessible->GetInternalActor() == mApplication.mWindows[i].GetRootLayer()) - { - Dali::Accessibility::Bridge::GetCurrentBridge()->WindowHidden(mApplication.mWindows[i]); - 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; - } - } - - UnregisterDefaultLabel(windowAccessible); - for(auto i = 0u; i < mApplication.mChildren.size(); ++i) { if(mApplication.mChildren[i] == windowAccessible) @@ -266,21 +230,81 @@ void BridgeBase::RemoveTopLevelWindow(Accessible* windowAccessible) } } -void BridgeBase::RegisterDefaultLabel(Accessible* object) +void BridgeBase::CompressDefaultLabels() +{ + // Remove entries for objects which no longer exist + mDefaultLabels.remove_if([](const DefaultLabelType& label) { + // Check 1) window's weak handle; 2) accessible's ref object + return !label.first.GetBaseHandle() || label.second.expired(); + }); +} + +void BridgeBase::RegisterDefaultLabel(std::shared_ptr object) { - if(std::find(mDefaultLabels.begin(), mDefaultLabels.end(), object) == mDefaultLabels.end()) + CompressDefaultLabels(); + + Dali::WeakHandle window = GetWindow(object.get()); + if(!window.GetBaseHandle()) // true also if `object` is null { - mDefaultLabels.push_back(object); + 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) { + auto labelPtr = label.second.lock(); + return labelPtr && object == labelPtr; + }); + + 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(std::shared_ptr object) +{ + CompressDefaultLabels(); + + mDefaultLabels.remove_if([&object](const DefaultLabelType& label) { + auto labelPtr = label.second.lock(); + return labelPtr && object == labelPtr; + }); } -void BridgeBase::UnregisterDefaultLabel(Accessible* object) +Accessible* BridgeBase::GetDefaultLabel(Accessible* root) { - auto it = std::find(mDefaultLabels.begin(), mDefaultLabels.end(), object); - if(it != mDefaultLabels.end()) + CompressDefaultLabels(); + + Dali::WeakHandle 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; + }); + + Accessible* rawPtr = root; + if(it != mDefaultLabels.rend()) { - mDefaultLabels.erase(it); + if(auto labelPtr = it->second.lock()) + { + rawPtr = labelPtr.get(); + } } + + return rawPtr; } std::string BridgeBase::StripPrefix(const std::string& path) @@ -304,7 +328,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 + "'"}; } @@ -318,7 +342,7 @@ 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 size = strlen(AtspiPath); @@ -386,9 +410,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; +}