2 * Copyright (c) 2019 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(); )
75 if (it->second.second)
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 );
107 dbusServer = { 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 + "'"};
245 if( pth[size] != '/' )
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 )
271 res.emplace_back( std::move( CreateCacheElement( root ) ) );
272 for( auto i = 0u; i < item->GetChildCount(); ++i )
274 proc( item->GetChildAtIndex( i ) );
281 auto BridgeBase::CreateCacheElement( Accessible* item ) -> CacheElementType
288 auto root = &application;
289 auto parent = item->GetParent();
291 std::vector< Address > children;
292 for( auto i = 0u; i < item->GetChildCount(); ++i )
294 children.emplace_back( item->GetChildAtIndex( i )->GetAddress() );
297 return std::make_tuple(
300 parent ? parent->GetAddress() : Address{},
302 item->GetInterfaces(),
305 item->GetDescription(),
306 item->GetStates().GetRawData()