2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/accessibility/bridge/bridge-base.h>
27 #include <dali/public-api/adaptor-framework/timer.h>
29 using namespace Dali::Accessibility;
31 static Dali::Timer tickTimer;
33 BridgeBase::~BridgeBase()
37 BridgeBase::BridgeBase()
41 void BridgeBase::addFilteredEvent(FilteredEvents kind, Dali::Accessibility::Accessible* obj, float delay, std::function<void()> functor)
48 auto it = filteredEvents.insert({{kind, obj}, {static_cast<unsigned int>(delay * 10), {}}});
55 it.first->second.second = std::move(functor);
60 tickTimer = Dali::Timer::New(100);
61 tickTimer.TickSignal().Connect(this, &BridgeBase::tickFilteredEvents);
65 bool BridgeBase::tickFilteredEvents()
67 for(auto it = filteredEvents.begin(); it != filteredEvents.end();)
78 it->second.second = {};
82 it = filteredEvents.erase(it);
88 return !filteredEvents.empty();
91 void BridgeBase::RegisteredEventsUpdate()
93 using ReturnType = std::vector<std::tuple<std::string, std::string>>;
94 registry.method<DBus::ValueOrError<ReturnType>()>("GetRegisteredEvents").asyncCall([this](DBus::ValueOrError<ReturnType> msg) {
97 LOG() << "Get registered events failed";
101 allowObjectBoundsChangedEvent = false;
103 ReturnType values = std::get<ReturnType>(msg.getValues());
104 for(long unsigned int i = 0; i < values.size(); i++)
106 if(!std::get<1>(values[i]).compare("Object:BoundsChanged"))
108 allowObjectBoundsChangedEvent = true;
114 BridgeBase::ForceUpResult BridgeBase::ForceUp()
116 if(Bridge::ForceUp() == ForceUpResult::ALREADY_UP)
118 return ForceUpResult::ALREADY_UP;
120 auto proxy = DBus::DBusClient{dbusLocators::atspi::BUS, dbusLocators::atspi::OBJ_PATH, dbusLocators::atspi::BUS_INTERFACE, DBus::ConnectionType::SESSION};
121 auto addr = proxy.method<std::string()>(dbusLocators::atspi::GET_ADDRESS).call();
125 throw std::domain_error{std::string("failed at call '") + dbusLocators::atspi::GET_ADDRESS + "': " + addr.getError().message};
128 con = DBusWrapper::Installed()->eldbus_address_connection_get_impl(std::get<0>(addr));
129 mData->mBusName = DBus::getConnectionName(con);
133 DBus::DBusInterfaceDescription desc{"org.a11y.atspi.Cache"};
134 AddFunctionToInterface(desc, "GetItems", &BridgeBase::GetItems);
135 dbusServer.addInterface("/org/a11y/atspi/cache", desc);
138 DBus::DBusInterfaceDescription desc{"org.a11y.atspi.Application"};
139 AddGetSetPropertyToInterface(desc, "Id", &BridgeBase::IdGet, &BridgeBase::IdSet);
140 dbusServer.addInterface(AtspiPath, desc);
143 registry = {AtspiDbusNameRegistry, AtspiDbusPathRegistry, AtspiDbusInterfaceRegistry, con};
145 RegisteredEventsUpdate();
147 registry.addSignal<void(void)>("EventListenerRegistered", [this](void) {
148 RegisteredEventsUpdate();
151 registry.addSignal<void(void)>("EventListenerDeregistered", [this](void) {
152 RegisteredEventsUpdate();
155 return ForceUpResult::JUST_STARTED;
158 void BridgeBase::ForceDown()
166 const std::string& BridgeBase::GetBusName() const
168 static std::string empty;
169 return mData ? mData->mBusName : empty;
172 Accessible* BridgeBase::FindByPath(const std::string& name) const
178 catch(std::domain_error&)
184 void BridgeBase::AddPopup(Accessible* object)
186 if(std::find(popups.begin(), popups.end(), object) != popups.end())
190 popups.push_back(object);
193 object->Emit(WindowEvent::ACTIVATE, 0);
197 void BridgeBase::RemovePopup(Accessible* object)
199 auto it = std::find(popups.begin(), popups.end(), object);
200 if(it == popups.end())
207 object->Emit(WindowEvent::DEACTIVATE, 0);
210 application.children.back()->Emit(WindowEvent::ACTIVATE, 0);
214 popups.back()->Emit(WindowEvent::ACTIVATE, 0);
219 void BridgeBase::AddTopLevelWindow(Accessible* root)
221 application.children.push_back(root);
222 SetIsOnRootLevel(root);
225 void BridgeBase::RemoveTopLevelWindow(Accessible* root)
227 for(auto i = 0u; i < application.children.size(); ++i)
229 if(application.children[i] == root)
231 application.children.erase(application.children.begin() + i);
237 std::string BridgeBase::StripPrefix(const std::string& path)
239 auto size = strlen(AtspiPath);
240 return path.substr(size + 1);
243 Accessible* BridgeBase::Find(const std::string& path) const
251 std::istringstream tmp{path};
252 if(!(tmp >> accessible))
254 throw std::domain_error{"invalid path '" + path + "'"};
257 auto it = mData->mKnownObjects.find(static_cast<Accessible*>(accessible));
258 if(it == mData->mKnownObjects.end())
260 throw std::domain_error{"unknown object '" + path + "'"};
263 return static_cast<Accessible*>(accessible);
266 Accessible* BridgeBase::Find(const Address& ptr) const
268 assert(ptr.GetBus() == mData->mBusName);
269 return Find(ptr.GetPath());
272 Accessible* BridgeBase::FindSelf() const
274 auto path = DBus::DBusServer::getCurrentObjectPath();
275 auto size = strlen(AtspiPath);
276 if(path.size() <= size)
278 throw std::domain_error{"invalid path '" + path + "'"};
280 if(path.substr(0, size) != AtspiPath)
282 throw std::domain_error{"invalid path '" + path + "'"};
284 if(path[size] != '/')
286 throw std::domain_error{"invalid path '" + path + "'"};
288 return Find(StripPrefix(path));
291 void BridgeBase::IdSet(int id)
296 int BridgeBase::IdGet()
301 auto BridgeBase::GetItems() -> DBus::ValueOrError<std::vector<CacheElementType>>
303 auto root = &application;
305 std::vector<CacheElementType> res;
307 std::function<void(Accessible*)> proc =
308 [&](Accessible* item) {
309 res.emplace_back(std::move(CreateCacheElement(root)));
310 for(auto i = 0u; i < item->GetChildCount(); ++i)
312 proc(item->GetChildAtIndex(i));
319 auto BridgeBase::CreateCacheElement(Accessible* item) -> CacheElementType
326 auto root = &application;
327 auto parent = item->GetParent();
329 std::vector<Address> children;
330 for(auto i = 0u; i < item->GetChildCount(); ++i)
332 children.emplace_back(item->GetChildAtIndex(i)->GetAddress());
335 return std::make_tuple(
338 parent ? parent->GetAddress() : Address{},
340 item->GetInterfaces(),
343 item->GetDescription(),
344 item->GetStates().GetRawData());