[AT-SPI] Clean up AT-SPI interfaces
[platform/core/uifw/dali-adaptor.git] / dali / internal / accessibility / bridge / bridge-base.h
1 #ifndef DALI_INTERNAL_ACCESSIBILITY_BRIDGE_BASE_H
2 #define DALI_INTERNAL_ACCESSIBILITY_BRIDGE_BASE_H
3
4 /*
5  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // EXTERNAL INCLUDES
22 #include <dali/public-api/actors/layer.h>
23 #include <dali/public-api/dali-adaptor-version.h>
24 #include <dali/public-api/signals/connection-tracker.h>
25 #include <memory>
26
27 // INTERNAL INCLUDES
28 #include <dali/devel-api/adaptor-framework/proxy-accessible.h>
29 #include <dali/devel-api/adaptor-framework/window-devel.h>
30 #include <dali/devel-api/atspi-interfaces/accessible.h>
31 #include <dali/devel-api/atspi-interfaces/application.h>
32 #include <dali/devel-api/atspi-interfaces/collection.h>
33 #include <dali/internal/accessibility/bridge/accessibility-common.h>
34
35 /**
36  * @brief The ApplicationAccessible class is to define Accessibility Application.
37  */
38 class ApplicationAccessible : public virtual Dali::Accessibility::Accessible, public virtual Dali::Accessibility::Collection, public virtual Dali::Accessibility::Application
39 {
40 public:
41   Dali::Accessibility::ProxyAccessible          mParent;
42   std::vector<Dali::Accessibility::Accessible*> mChildren;
43   std::vector<Dali::Window>                     mWindows;
44   std::string                                   mName;
45
46   std::string GetName() const override
47   {
48     return mName;
49   }
50
51   std::string GetDescription() const override
52   {
53     return "";
54   }
55
56   Dali::Accessibility::Accessible* GetParent() override
57   {
58     return &mParent;
59   }
60
61   size_t GetChildCount() const override
62   {
63     return mChildren.size();
64   }
65
66   Dali::Accessibility::Accessible* GetChildAtIndex(size_t index) override
67   {
68     auto size = mChildren.size();
69     if(index >= size)
70     {
71       throw std::domain_error{"invalid index " + std::to_string(index) + " for object with " + std::to_string(size) + " children"};
72     }
73     return mChildren[index];
74   }
75
76   size_t GetIndexInParent() override
77   {
78     throw std::domain_error{"can't call GetIndexInParent on application object"};
79   }
80
81   Dali::Accessibility::Role GetRole() const override
82   {
83     return Dali::Accessibility::Role::APPLICATION;
84   }
85
86   Dali::Accessibility::States GetStates() override
87   {
88     return {};
89   }
90
91   Dali::Accessibility::Attributes GetAttributes() const override
92   {
93     return {};
94   }
95
96   /**
97    * @brief Gets the Accessible object from the window.
98    *
99    * @param[in] window The window to find
100    * @return Null if mChildren is empty, otherwise the Accessible object
101    * @note Currently, the default window would be returned when mChildren is not empty.
102    */
103   Dali::Accessibility::Accessible* GetWindowAccessible(Dali::Window window)
104   {
105     if(mChildren.empty())
106     {
107       return nullptr;
108     }
109
110     Dali::Layer rootLayer = window.GetRootLayer();
111
112     // Find a child which is related to the window.
113     for(auto i = 0u; i < mChildren.size(); ++i)
114     {
115       if(rootLayer == mChildren[i]->GetInternalActor())
116       {
117         return mChildren[i];
118       }
119     }
120
121     // If can't find its children, return the default window.
122     return mChildren[0];
123   }
124
125   bool DoGesture(const Dali::Accessibility::GestureInfo& gestureInfo) override
126   {
127     return false;
128   }
129
130   std::vector<Dali::Accessibility::Relation> GetRelationSet() override
131   {
132     return {};
133   }
134
135   Dali::Actor GetInternalActor() override
136   {
137     return Dali::Actor{};
138   }
139
140   Dali::Accessibility::Address GetAddress() const override
141   {
142     return {"", "root"};
143   }
144
145   std::string GetToolkitName() const override
146   {
147     return {"dali"};
148   }
149
150   std::string GetVersion() const override
151   {
152     return std::to_string(Dali::ADAPTOR_MAJOR_VERSION) + "." + std::to_string(Dali::ADAPTOR_MINOR_VERSION);
153   }
154 };
155
156 /**
157  * @brief Enumeration for FilteredEvents.
158  */
159 enum class FilteredEvents
160 {
161   BOUNDS_CHANGED ///< Bounds changed
162 };
163
164 // Custom specialization of std::hash
165 namespace std
166 {
167 template<>
168 struct hash<std::pair<FilteredEvents, Dali::Accessibility::Accessible*>>
169 {
170   size_t operator()(std::pair<FilteredEvents, Dali::Accessibility::Accessible*> value) const
171   {
172     return (static_cast<size_t>(value.first) * 131) ^ reinterpret_cast<size_t>(value.second);
173   }
174 };
175 } // namespace std
176
177 /**
178  * @brief The BridgeBase class is basic class for Bridge functions.
179  */
180 class BridgeBase : public Dali::Accessibility::Bridge, public Dali::ConnectionTracker
181 {
182   std::unordered_map<std::pair<FilteredEvents, Dali::Accessibility::Accessible*>, std::pair<unsigned int, std::function<void()>>> mFilteredEvents;
183
184   /**
185    * @brief Removes all FilteredEvents using Tick signal.
186    *
187    * @return False if mFilteredEvents is empty, otherwise true.
188    */
189   bool TickFilteredEvents();
190
191 public:
192   /**
193    * @brief Adds FilteredEvents, Accessible, and delay time to mFilteredEvents.
194    *
195    * @param[in] kind FilteredEvents enum value
196    * @param[in] obj Accessible object
197    * @param[in] delay The delay time
198    * @param[in] functor The function to be called // NEED TO UPDATE!
199    */
200   void AddFilteredEvent(FilteredEvents kind, Dali::Accessibility::Accessible* obj, float delay, std::function<void()> functor);
201
202   /**
203    * @brief Callback when the visibility of the window is changed.
204    *
205    * @param[in] window The window to be changed
206    * @param[in] visible The visibility of the window
207    */
208   void OnWindowVisibilityChanged(Dali::Window window, bool visible);
209
210   /**
211    * @brief Callback when the window focus is changed.
212    *
213    * @param[in] window The window whose focus is changed
214    * @param[in] focusIn Whether the focus is in/out
215    */
216   void OnWindowFocusChanged(Dali::Window window, bool focusIn);
217
218   /**
219    * @copydoc Dali::Accessibility::Bridge::GetBusName()
220    */
221   const std::string& GetBusName() const override;
222
223   /**
224    * @copydoc Dali::Accessibility::Bridge::AddTopLevelWindow()
225    */
226   void AddTopLevelWindow(Dali::Accessibility::Accessible* windowAccessible) override;
227
228   /**
229    * @copydoc Dali::Accessibility::Bridge::RemoveTopLevelWindow()
230    */
231   void RemoveTopLevelWindow(Dali::Accessibility::Accessible* windowAccessible) override;
232
233   /**
234    * @copydoc Dali::Accessibility::Bridge::RegisterDefaultLabel()
235    */
236   void RegisterDefaultLabel(Dali::Accessibility::Accessible* object) override;
237
238   /**
239    * @copydoc Dali::Accessibility::Bridge::UnregisterDefaultLabel()
240    */
241   void UnregisterDefaultLabel(Dali::Accessibility::Accessible* object) override;
242
243   /**
244    * @copydoc Dali::Accessibility::Bridge::GetDefaultLabel()
245    */
246   Dali::Accessibility::Accessible* GetDefaultLabel() const override
247   {
248     return mDefaultLabels.empty() ? nullptr : mDefaultLabels.back();
249   }
250
251   /**
252    * @copydoc Dali::Accessibility::Bridge::GetApplication()
253    */
254   Dali::Accessibility::Accessible* GetApplication() const override
255   {
256     return &mApplication;
257   }
258
259   /**
260    * @brief Adds function to dbus interface.
261    */
262   template<typename SELF, typename... RET, typename... ARGS>
263   void AddFunctionToInterface(
264     DBus::DBusInterfaceDescription& desc, const std::string& funcName, DBus::ValueOrError<RET...> (SELF::*funcPtr)(ARGS...))
265   {
266     if(auto self = dynamic_cast<SELF*>(this))
267       desc.addMethod<DBus::ValueOrError<RET...>(ARGS...)>(
268         funcName,
269         [=](ARGS... args) -> DBus::ValueOrError<RET...> {
270           try
271           {
272             return (self->*funcPtr)(std::move(args)...);
273           }
274           catch(std::domain_error& e)
275           {
276             return DBus::Error{e.what()};
277           }
278         });
279   }
280
281   /**
282    * @brief Adds 'Get' property to dbus interface.
283    */
284   template<typename T, typename SELF>
285   void AddGetPropertyToInterface(DBus::DBusInterfaceDescription& desc,
286                                  const std::string&              funcName,
287                                  T (SELF::*funcPtr)())
288   {
289     if(auto self = dynamic_cast<SELF*>(this))
290       desc.addProperty<T>(funcName,
291                           [=]() -> DBus::ValueOrError<T> {
292                             try
293                             {
294                               return (self->*funcPtr)();
295                             }
296                             catch(std::domain_error& e)
297                             {
298                               return DBus::Error{e.what()};
299                             }
300                           },
301                           {});
302   }
303
304   /**
305    * @brief Adds 'Set' property to dbus interface.
306    */
307   template<typename T, typename SELF>
308   void AddSetPropertyToInterface(DBus::DBusInterfaceDescription& desc,
309                                  const std::string&              funcName,
310                                  void (SELF::*funcPtr)(T))
311   {
312     if(auto self = dynamic_cast<SELF*>(this))
313       desc.addProperty<T>(funcName, {}, [=](T t) -> DBus::ValueOrError<void> {
314         try
315         {
316           (self->*funcPtr)(std::move(t));
317           return {};
318         }
319         catch(std::domain_error& e)
320         {
321           return DBus::Error{e.what()};
322         }
323       });
324   }
325
326   /**
327    * @brief Adds 'Set' and 'Get' properties to dbus interface.
328    */
329   template<typename T, typename T1, typename SELF>
330   void AddGetSetPropertyToInterface(DBus::DBusInterfaceDescription& desc,
331                                     const std::string&              funcName,
332                                     T1 (SELF::*funcPtrGet)(),
333                                     DBus::ValueOrError<void> (SELF::*funcPtrSet)(T))
334   {
335     if(auto self = dynamic_cast<SELF*>(this))
336       desc.addProperty<T>(
337         funcName,
338         [=]() -> DBus::ValueOrError<T> {
339           try
340           {
341             return (self->*funcPtrGet)();
342           }
343           catch(std::domain_error& e)
344           {
345             return DBus::Error{e.what()};
346           }
347         },
348         [=](T t) -> DBus::ValueOrError<void> {
349           try
350           {
351             (self->*funcPtrSet)(std::move(t));
352             return {};
353           }
354           catch(std::domain_error& e)
355           {
356             return DBus::Error{e.what()};
357           }
358         });
359   }
360
361   /**
362    * @brief Adds 'Get' and 'Set' properties to dbus interface.
363    */
364   template<typename T, typename T1, typename SELF>
365   void AddGetSetPropertyToInterface(DBus::DBusInterfaceDescription& desc,
366                                     const std::string&              funcName,
367                                     T1 (SELF::*funcPtrGet)(),
368                                     void (SELF::*funcPtrSet)(T))
369   {
370     if(auto self = dynamic_cast<SELF*>(this))
371       desc.addProperty<T>(
372         funcName,
373         [=]() -> DBus::ValueOrError<T> {
374           try
375           {
376             return (self->*funcPtrGet)();
377           }
378           catch(std::domain_error& e)
379           {
380             return DBus::Error{e.what()};
381           }
382         },
383         [=](T t) -> DBus::ValueOrError<void> {
384           try
385           {
386             (self->*funcPtrSet)(std::move(t));
387             return {};
388           }
389           catch(std::domain_error& e)
390           {
391             return DBus::Error{e.what()};
392           }
393         });
394   }
395
396   /**
397    * @brief Gets the string of the path excluding the specified prefix.
398    *
399    * @param path The path to get
400    * @return The string stripped of the specific prefix
401    */
402   static std::string StripPrefix(const std::string& path);
403
404   /**
405    * @brief Finds the Accessible object according to the path.
406    *
407    * @param[in] path The path for Accessible object
408    * @return The Accessible object corresponding to the path
409    */
410   Dali::Accessibility::Accessible* Find(const std::string& path) const;
411
412   /**
413    * @brief Finds the Accessible object with the given address.
414    *
415    * @param[in] ptr The unique Address of the object
416    * @return The Accessible object corresponding to the path
417    */
418   Dali::Accessibility::Accessible* Find(const Dali::Accessibility::Address& ptr) const;
419
420   /**
421    * @brief Returns the target object of the currently executed DBus method call.
422    *
423    * And any subclasses redefine `FindSelf` with a different return type as a convenient wrapper around dynamic_cast.
424    * @return The Accessible object
425    * @note When a DBus method is called on some object, this target object (`currentObject`) is temporarily saved by the bridge,
426    * because DBus handles the invocation target separately from the method arguments.
427    * We then use the saved object inside the 'glue' method (e.g. BridgeValue::GetMinimum)
428    * to call the equivalent method on the respective C++ object (this could be ScrollBar::AccessibleImpl::GetMinimum in the example given).
429    */
430   Dali::Accessibility::Accessible* FindSelf() const;
431
432   /**
433    * @copydoc Dali::Accessibility::Bridge::FindByPath()
434    */
435   Dali::Accessibility::Accessible* FindByPath(const std::string& name) const override;
436
437   /**
438    * @copydoc Dali::Accessibility::Bridge::SetApplicationName()
439    */
440   void SetApplicationName(std::string name) override
441   {
442     mApplication.mName = std::move(name);
443   }
444
445 protected:
446   mutable ApplicationAccessible                 mApplication;
447   std::vector<Dali::Accessibility::Accessible*> mDefaultLabels;
448   bool                                          mIsScreenReaderSuppressed = false;
449
450 private:
451   /**
452    * @brief Sets an ID.
453    * @param[in] id An ID (integer value)
454    */
455   void SetId(int id);
456
457   /**
458    * @brief Gets the ID.
459    * @return The ID to be set
460    */
461   int GetId();
462
463   /**
464    * @brief Update registered events.
465    */
466   void UpdateRegisteredEvents();
467
468   using CacheElementType = std::tuple<
469     Dali::Accessibility::Address,
470     Dali::Accessibility::Address,
471     Dali::Accessibility::Address,
472     std::vector<Dali::Accessibility::Address>,
473     std::vector<std::string>,
474     std::string,
475     Dali::Accessibility::Role,
476     std::string,
477     std::array<uint32_t, 2>>;
478
479   /**
480    * @brief Gets Items  // NEED TO UPDATE!
481    *
482    * @return
483    */
484   DBus::ValueOrError<std::vector<CacheElementType>> GetItems();
485
486   /**
487    * @brief Creates CacheElement.
488    *
489    * CreateCacheElement method works for GetItems which is a part of ATSPI protocol.
490    * ATSPI client library (libatspi from at-spi2-core) depending on cacheing policy configuration uses GetItems
491    * to pre-load entire accessible tree from application to its own cache in single dbus call.
492    * Otherwise the particular nodes in a tree are cached lazily when client library tries to access them.
493    * @param item Accessible to get information
494    * @return The elements to be cached
495    */
496   CacheElementType CreateCacheElement(Dali::Accessibility::Accessible* item);
497
498 protected:
499   BridgeBase();
500   virtual ~BridgeBase();
501
502   /**
503    * @copydoc Dali::Accessibility::Bridge::ForceUp()
504    */
505   ForceUpResult ForceUp() override;
506
507   /**
508    * @copydoc Dali::Accessibility::Bridge::ForceDown()
509    */
510   void ForceDown() override;
511
512   DBus::DBusServer           mDbusServer;
513   DBusWrapper::ConnectionPtr mConnectionPtr;
514   int                        mId = 0;
515   DBus::DBusClient           mRegistry;
516   bool                       IsBoundsChangedEventAllowed{false};
517 };
518
519 #endif // DALI_INTERNAL_ACCESSIBILITY_BRIDGE_BASE_H