Revert "[Tizen](ATSPI) Fix Native TC fails"
[platform/core/uifw/dali-adaptor.git] / dali / internal / accessibility / bridge / bridge-base.cpp
1 /*
2  * Copyright (c) 2019 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/accessibility/bridge/bridge-base.h>
20
21 // EXTERNAL INCLUDES
22 #include <atomic>
23 #include <cstdlib>
24 #include <memory>
25
26 // INTERNAL INCLUDES
27 #include <dali/public-api/adaptor-framework/timer.h>
28
29 using namespace Dali::Accessibility;
30
31 static Dali::Timer tickTimer;
32
33 BridgeBase::~BridgeBase()
34 {
35 }
36
37 BridgeBase::BridgeBase()
38 {
39 }
40
41 void BridgeBase::addFilteredEvent(FilteredEvents kind, Dali::Accessibility::Accessible* obj, float delay, std::function<void()> functor)
42 {
43   if (delay < 0)
44     delay = 0;
45   auto it = filteredEvents.insert({ { kind, obj }, { static_cast<unsigned int>(delay * 10), {} } });
46   if (it.second)
47     functor();
48   else
49     it.first->second.second = std::move(functor);
50   if (!tickTimer) {
51     tickTimer = Dali::Timer::New(100);
52     tickTimer.TickSignal().Connect(this, &BridgeBase::tickFilteredEvents);
53   }
54 }
55
56 bool BridgeBase::tickFilteredEvents()
57 {
58   for(auto it = filteredEvents.begin(); it != filteredEvents.end(); ) {
59     if (it->second.first) {
60       --it->second.first;
61     }
62     else {
63       if (it->second.second) {
64         it->second.second();
65         it->second.second = {};
66       }
67       else {
68         it = filteredEvents.erase(it);
69         continue;
70       }
71     }
72     ++it;
73   }
74   return !filteredEvents.empty();
75 }
76
77 BridgeBase::ForceUpResult BridgeBase::ForceUp()
78 {
79   if( Bridge::ForceUp() == ForceUpResult::ALREADY_UP )
80     return ForceUpResult::ALREADY_UP;
81   auto proxy = DBus::DBusClient{dbusLocators::atspi::BUS, dbusLocators::atspi::OBJ_PATH,
82                                 dbusLocators::atspi::BUS_INTERFACE, DBus::ConnectionType::SESSION};
83   auto addr = proxy.method< std::string() >( dbusLocators::atspi::GET_ADDRESS ).call();
84
85   if( !addr )
86     throw std::domain_error{std::string( "failed at call '" ) + dbusLocators::atspi::GET_ADDRESS +
87                           "': " + addr.getError().message};
88
89   con = DBusWrapper::Installed()->eldbus_address_connection_get_impl( std::get< 0 >( addr ) );
90   data->busName = DBus::getConnectionName( con );
91   dbusServer = {con};
92
93   {
94     DBus::DBusInterfaceDescription desc{"org.a11y.atspi.Cache"};
95     AddFunctionToInterface( desc, "GetItems", &BridgeBase::GetItems );
96     dbusServer.addInterface( "/org/a11y/atspi/cache", desc );
97   }
98   {
99     DBus::DBusInterfaceDescription desc{"org.a11y.atspi.Application"};
100     AddGetSetPropertyToInterface( desc, "Id", &BridgeBase::IdGet, &BridgeBase::IdSet );
101     dbusServer.addInterface( AtspiPath, desc );
102   }
103   return ForceUpResult::JUST_STARTED;
104 }
105
106 void BridgeBase::ForceDown()
107 {
108   Bridge::ForceDown();
109   dbusServer = {};
110   con = {};
111 }
112
113 const std::string& BridgeBase::GetBusName() const
114 {
115   static std::string empty;
116   return data ? data->busName : empty;
117 }
118
119 Accessible* BridgeBase::FindByPath( const std::string& name ) const
120 {
121   try
122   {
123     return Find( name );
124   }
125   catch( std::domain_error )
126   {
127     return nullptr;
128   }
129 }
130
131 void BridgeBase::AddPopup( Accessible* obj )
132 {
133   if( std::find( popups.begin(), popups.end(), obj ) != popups.end() ) return;
134   popups.push_back( obj );
135   if (IsUp())
136   {
137     obj->Emit( WindowEvent::ACTIVATE, 0 );
138   }
139 }
140
141 void BridgeBase::RemovePopup( Accessible* obj )
142 {
143   auto it = std::find( popups.begin(), popups.end(), obj );
144   if( it == popups.end() ) return;
145   popups.erase( it );
146   if (IsUp())
147   {
148     obj->Emit( WindowEvent::DEACTIVATE, 0 );
149     if( popups.empty() )
150     {
151       application.children.back()->Emit( WindowEvent::ACTIVATE, 0 );
152     }
153     else
154     {
155       popups.back()->Emit( WindowEvent::ACTIVATE, 0 );
156     }
157   }
158
159 }
160
161 void BridgeBase::AddTopLevelWindow( Accessible* root )
162 {
163   application.children.push_back( root );
164   SetIsOnRootLevel( root );
165 }
166
167 void BridgeBase::RemoveTopLevelWindow( Accessible* root )
168 {
169         for(auto i = 0u; i < application.children.size(); ++i) {
170                 if( application.children[i] == root )
171                 {
172                         application.children.erase(application.children.begin() + i);
173                         break;
174                 }
175         }
176 }
177
178 // Accessible *BridgeBase::getApplicationRoot() const
179 // {
180 //     return rootElement;
181 // }
182
183 std::string BridgeBase::StripPrefix( const std::string& path )
184 {
185   auto size = strlen( AtspiPath );
186   return path.substr( size + 1 );
187 }
188
189 Accessible* BridgeBase::Find( const std::string& path ) const
190 {
191   if( path == "root" )
192     return &application;
193   void* p;
194   std::istringstream tmp{ path };
195   if (! ( tmp >> p) )
196     throw std::domain_error{"invalid path '" + path + "'"};
197   auto it = data->knownObjects.find( static_cast<Accessible*>( p ) );
198   if( it == data->knownObjects.end() )
199     throw std::domain_error{"unknown object '" + path + "'"};
200   return static_cast<Accessible*>( p );
201 }
202
203 Accessible* BridgeBase::Find( const Address& ptr ) const
204 {
205   assert( ptr.GetBus() == data->busName );
206   return Find( ptr.GetPath() );
207 }
208
209 Accessible* BridgeBase::FindSelf() const
210 {
211   auto pth = DBus::DBusServer::getCurrentObjectPath();
212   auto size = strlen( AtspiPath );
213   if( pth.size() <= size )
214     throw std::domain_error{"invalid path '" + pth + "'"};
215   if( pth.substr( 0, size ) != AtspiPath )
216     throw std::domain_error{"invalid path '" + pth + "'"};
217   if( pth[size] != '/' )
218     throw std::domain_error{"invalid path '" + pth + "'"};
219   return Find( StripPrefix( pth ) );
220 }
221
222 void BridgeBase::IdSet( int id )
223 {
224   this->id = id;
225 }
226 int BridgeBase::IdGet()
227 {
228   return this->id;
229 }
230
231 auto BridgeBase::GetItems() -> DBus::ValueOrError< std::vector< CacheElementType > >
232 {
233   auto root = &application;
234
235   std::vector< CacheElementType > res;
236
237         std::function< void(Accessible*) > proc = [&]( Accessible* item ) {
238         res.emplace_back( std::move( CreateCacheElement( root ) ) );
239
240                 for( auto i = 0u; i < item->GetChildCount(); ++i )
241                 {
242                         proc( item->GetChildAtIndex( i ) );
243                 }
244         };
245
246   return res;
247 }
248
249 auto BridgeBase::CreateCacheElement( Accessible* item ) -> CacheElementType
250 {
251   if( !item )
252     return {};
253
254   auto root = &application;
255   auto parent = item->GetParent();
256
257   std::vector< Address > children;
258   for( auto i = 0u; i < item->GetChildCount(); ++i )
259   {
260     children.emplace_back( item->GetChildAtIndex( i )->GetAddress() );
261   }
262
263   return std::make_tuple(
264       item->GetAddress(),
265       root->GetAddress(),
266       parent ? parent->GetAddress() : Address{},
267       children,
268       item->GetInterfaces(),
269       item->GetName(),
270       item->GetRole(),
271       item->GetDescription(),
272       item->GetStates().GetRawData() );
273 }