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