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 BridgeBase::ForceUpResult BridgeBase::ForceUp()
93 if(Bridge::ForceUp() == ForceUpResult::ALREADY_UP)
95 return ForceUpResult::ALREADY_UP;
97 auto proxy = DBus::DBusClient{dbusLocators::atspi::BUS, dbusLocators::atspi::OBJ_PATH, dbusLocators::atspi::BUS_INTERFACE, DBus::ConnectionType::SESSION};
98 auto addr = proxy.method<std::string()>(dbusLocators::atspi::GET_ADDRESS).call();
102 throw std::domain_error{std::string("failed at call '") + dbusLocators::atspi::GET_ADDRESS + "': " + addr.getError().message};
105 con = DBusWrapper::Installed()->eldbus_address_connection_get_impl(std::get<0>(addr));
106 data->busName = DBus::getConnectionName(con);
110 DBus::DBusInterfaceDescription desc{"org.a11y.atspi.Cache"};
111 AddFunctionToInterface(desc, "GetItems", &BridgeBase::GetItems);
112 dbusServer.addInterface("/org/a11y/atspi/cache", desc);
115 DBus::DBusInterfaceDescription desc{"org.a11y.atspi.Application"};
116 AddGetSetPropertyToInterface(desc, "Id", &BridgeBase::IdGet, &BridgeBase::IdSet);
117 dbusServer.addInterface(AtspiPath, desc);
120 return ForceUpResult::JUST_STARTED;
123 void BridgeBase::ForceDown()
130 const std::string& BridgeBase::GetBusName() const
132 static std::string empty;
133 return data ? data->busName : empty;
136 Accessible* BridgeBase::FindByPath(const std::string& name) const
142 catch(std::domain_error&)
148 void BridgeBase::AddPopup(Accessible* obj)
150 if(std::find(popups.begin(), popups.end(), obj) != popups.end())
154 popups.push_back(obj);
157 obj->Emit(WindowEvent::ACTIVATE, 0);
161 void BridgeBase::RemovePopup(Accessible* obj)
163 auto it = std::find(popups.begin(), popups.end(), obj);
164 if(it == popups.end())
171 obj->Emit(WindowEvent::DEACTIVATE, 0);
174 application.children.back()->Emit(WindowEvent::ACTIVATE, 0);
178 popups.back()->Emit(WindowEvent::ACTIVATE, 0);
183 void BridgeBase::AddTopLevelWindow(Accessible* root)
185 application.children.push_back(root);
186 SetIsOnRootLevel(root);
189 void BridgeBase::RemoveTopLevelWindow(Accessible* root)
191 for(auto i = 0u; i < application.children.size(); ++i)
193 if(application.children[i] == root)
195 application.children.erase(application.children.begin() + i);
201 std::string BridgeBase::StripPrefix(const std::string& path)
203 auto size = strlen(AtspiPath);
204 return path.substr(size + 1);
207 Accessible* BridgeBase::Find(const std::string& path) const
214 std::istringstream tmp{path};
217 throw std::domain_error{"invalid path '" + path + "'"};
219 auto it = data->knownObjects.find(static_cast<Accessible*>(p));
220 if(it == data->knownObjects.end())
222 throw std::domain_error{"unknown object '" + path + "'"};
224 return static_cast<Accessible*>(p);
227 Accessible* BridgeBase::Find(const Address& ptr) const
229 assert(ptr.GetBus() == data->busName);
230 return Find(ptr.GetPath());
233 Accessible* BridgeBase::FindSelf() const
235 auto pth = DBus::DBusServer::getCurrentObjectPath();
236 auto size = strlen(AtspiPath);
237 if(pth.size() <= size)
239 throw std::domain_error{"invalid path '" + pth + "'"};
241 if(pth.substr(0, size) != AtspiPath)
243 throw std::domain_error{"invalid path '" + pth + "'"};
247 throw std::domain_error{"invalid path '" + pth + "'"};
249 return Find(StripPrefix(pth));
252 void BridgeBase::IdSet(int id)
257 int BridgeBase::IdGet()
262 auto BridgeBase::GetItems() -> DBus::ValueOrError<std::vector<CacheElementType> >
264 auto root = &application;
266 std::vector<CacheElementType> res;
268 std::function<void(Accessible*)> proc =
269 [&](Accessible* item) {
270 res.emplace_back(std::move(CreateCacheElement(root)));
271 for(auto i = 0u; i < item->GetChildCount(); ++i)
273 proc(item->GetChildAtIndex(i));
280 auto BridgeBase::CreateCacheElement(Accessible* item) -> CacheElementType
287 auto root = &application;
288 auto parent = item->GetParent();
290 std::vector<Address> children;
291 for(auto i = 0u; i < item->GetChildCount(); ++i)
293 children.emplace_back(item->GetChildAtIndex(i)->GetAddress());
296 return std::make_tuple(
299 parent ? parent->GetAddress() : Address{},
301 item->GetInterfaces(),
304 item->GetDescription(),
305 item->GetStates().GetRawData());