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