1 #ifndef DALI_INTERNAL_ACCESSIBILITY_BRIDGE_BASE_H
2 #define DALI_INTERNAL_ACCESSIBILITY_BRIDGE_BASE_H
5 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
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>
28 #include <dali/devel-api/adaptor-framework/window-devel.h>
29 #include <dali/internal/accessibility/bridge/accessibility-common.h>
32 * @brief The AppAccessible class is to define Accessibility Application.
34 class AppAccessible : public virtual Dali::Accessibility::Accessible, public virtual Dali::Accessibility::Collection, public virtual Dali::Accessibility::Application
37 Dali::Accessibility::EmptyAccessibleWithAddress mParent;
38 std::vector<Dali::Accessibility::Accessible*> mChildren;
39 std::vector<Dali::Window> mWindows;
42 std::string GetName() override
47 std::string GetDescription() override
52 Dali::Accessibility::Accessible* GetParent() override
57 size_t GetChildCount() override
59 return mChildren.size();
62 Dali::Accessibility::Accessible* GetChildAtIndex(size_t index) override
64 auto size = mChildren.size();
67 throw std::domain_error{"invalid index " + std::to_string(index) + " for object with " + std::to_string(size) + " children"};
69 return mChildren[index];
72 size_t GetIndexInParent() override
74 throw std::domain_error{"can't call GetIndexInParent on application object"};
77 Dali::Accessibility::Role GetRole() override
79 return Dali::Accessibility::Role::APPLICATION;
82 Dali::Accessibility::States GetStates() override
87 Dali::Accessibility::Attributes GetAttributes() override
93 * @brief Gets the Accessible object from the window.
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.
99 Dali::Accessibility::Accessible* GetWindowAccessible(Dali::Window window)
101 if(mChildren.empty())
106 Dali::Layer rootLayer = window.GetRootLayer();
108 // Find a child which is related to the window.
109 for(auto i = 0u; i < mChildren.size(); ++i)
111 if(rootLayer == mChildren[i]->GetInternalActor())
117 // If can't find its children, return the default window.
121 bool DoGesture(const Dali::Accessibility::GestureInfo& gestureInfo) override
126 std::vector<Dali::Accessibility::Relation> GetRelationSet() override
131 Dali::Actor GetInternalActor() override
133 return Dali::Actor{};
136 Dali::Accessibility::Address GetAddress() override
141 std::string GetToolkitName() override
146 std::string GetVersion() override
148 return std::to_string(Dali::ADAPTOR_MAJOR_VERSION) + "." + std::to_string(Dali::ADAPTOR_MINOR_VERSION);
153 * @brief Enumeration for FilteredEvents.
155 enum class FilteredEvents
157 BOUNDS_CHANGED ///< Bounds changed
160 // Custom specialization of std::hash
164 struct hash<std::pair<FilteredEvents, Dali::Accessibility::Accessible*>>
166 size_t operator()(std::pair<FilteredEvents, Dali::Accessibility::Accessible*> value) const
168 return (static_cast<size_t>(value.first) * 131) ^ reinterpret_cast<size_t>(value.second);
174 * @brief The BridgeBase class is basic class for Bridge functions.
176 class BridgeBase : public Dali::Accessibility::Bridge, public Dali::ConnectionTracker
178 std::unordered_map<std::pair<FilteredEvents, Dali::Accessibility::Accessible*>, std::pair<unsigned int, std::function<void()>>> mFilteredEvents;
181 * @brief Removes all FilteredEvents using Tick signal.
183 * @return False if mFilteredEvents is empty, otherwise true.
185 bool TickFilteredEvents();
189 * @brief Adds FilteredEvents, Accessible, and delay time to mFilteredEvents.
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!
196 void AddFilteredEvent(FilteredEvents kind, Dali::Accessibility::Accessible* obj, float delay, std::function<void()> functor);
199 * @brief Callback when the visibility of the window is changed.
201 * @param[in] window The window to be changed
202 * @param[in] visible The visibility of the window
204 void OnWindowVisibilityChanged(Dali::Window window, bool visible);
207 * @brief Callback when the window focus is changed.
209 * @param[in] window The window whose focus is changed
210 * @param[in] focusIn Whether the focus is in/out
212 void OnWindowFocusChanged(Dali::Window window, bool focusIn);
215 * @copydoc Dali::Accessibility::Bridge::GetBusName()
217 const std::string& GetBusName() const override;
220 * @copydoc Dali::Accessibility::Bridge::AddTopLevelWindow()
222 void AddTopLevelWindow(Dali::Accessibility::Accessible* windowAccessible) override;
225 * @copydoc Dali::Accessibility::Bridge::RemoveTopLevelWindow()
227 void RemoveTopLevelWindow(Dali::Accessibility::Accessible* windowAccessible) override;
230 * @copydoc Dali::Accessibility::Bridge::RegisterDefaultLabel()
232 void RegisterDefaultLabel(Dali::Accessibility::Accessible* object) override;
235 * @copydoc Dali::Accessibility::Bridge::UnregisterDefaultLabel()
237 void UnregisterDefaultLabel(Dali::Accessibility::Accessible* object) override;
240 * @copydoc Dali::Accessibility::Bridge::GetDefaultLabel()
242 Dali::Accessibility::Accessible* GetDefaultLabel() const override
244 return mDefaultLabels.empty() ? nullptr : mDefaultLabels.back();
248 * @copydoc Dali::Accessibility::Bridge::GetApplication()
250 Dali::Accessibility::Accessible* GetApplication() const override
252 return &mApplication;
256 * @brief Adds function to dbus interface.
258 template<typename SELF, typename... RET, typename... ARGS>
259 void AddFunctionToInterface(
260 DBus::DBusInterfaceDescription& desc, const std::string& funcName, DBus::ValueOrError<RET...> (SELF::*funcPtr)(ARGS...))
262 if(auto self = dynamic_cast<SELF*>(this))
263 desc.addMethod<DBus::ValueOrError<RET...>(ARGS...)>(
265 [=](ARGS... args) -> DBus::ValueOrError<RET...> {
268 return (self->*funcPtr)(std::move(args)...);
270 catch(std::domain_error& e)
272 return DBus::Error{e.what()};
278 * @brief Adds 'Get' property to dbus interface.
280 template<typename T, typename SELF>
281 void AddGetPropertyToInterface(DBus::DBusInterfaceDescription& desc,
282 const std::string& funcName,
283 T (SELF::*funcPtr)())
285 if(auto self = dynamic_cast<SELF*>(this))
286 desc.addProperty<T>(funcName,
287 [=]() -> DBus::ValueOrError<T> {
290 return (self->*funcPtr)();
292 catch(std::domain_error& e)
294 return DBus::Error{e.what()};
301 * @brief Adds 'Set' property to dbus interface.
303 template<typename T, typename SELF>
304 void AddSetPropertyToInterface(DBus::DBusInterfaceDescription& desc,
305 const std::string& funcName,
306 void (SELF::*funcPtr)(T))
308 if(auto self = dynamic_cast<SELF*>(this))
309 desc.addProperty<T>(funcName, {}, [=](T t) -> DBus::ValueOrError<void> {
312 (self->*funcPtr)(std::move(t));
315 catch(std::domain_error& e)
317 return DBus::Error{e.what()};
323 * @brief Adds 'Set' and 'Get' properties to dbus interface.
325 template<typename T, typename T1, typename SELF>
326 void AddGetSetPropertyToInterface(DBus::DBusInterfaceDescription& desc,
327 const std::string& funcName,
328 T1 (SELF::*funcPtrGet)(),
329 DBus::ValueOrError<void> (SELF::*funcPtrSet)(T))
331 if(auto self = dynamic_cast<SELF*>(this))
334 [=]() -> DBus::ValueOrError<T> {
337 return (self->*funcPtrGet)();
339 catch(std::domain_error& e)
341 return DBus::Error{e.what()};
344 [=](T t) -> DBus::ValueOrError<void> {
347 (self->*funcPtrSet)(std::move(t));
350 catch(std::domain_error& e)
352 return DBus::Error{e.what()};
358 * @brief Adds 'Get' and 'Set' properties to dbus interface.
360 template<typename T, typename T1, typename SELF>
361 void AddGetSetPropertyToInterface(DBus::DBusInterfaceDescription& desc,
362 const std::string& funcName,
363 T1 (SELF::*funcPtrGet)(),
364 void (SELF::*funcPtrSet)(T))
366 if(auto self = dynamic_cast<SELF*>(this))
369 [=]() -> DBus::ValueOrError<T> {
372 return (self->*funcPtrGet)();
374 catch(std::domain_error& e)
376 return DBus::Error{e.what()};
379 [=](T t) -> DBus::ValueOrError<void> {
382 (self->*funcPtrSet)(std::move(t));
385 catch(std::domain_error& e)
387 return DBus::Error{e.what()};
393 * @brief Gets the string of the path excluding the specified prefix.
395 * @param path The path to get
396 * @return The string stripped of the specific prefix
398 static std::string StripPrefix(const std::string& path);
401 * @brief Finds the Accessible object according to the path.
403 * @param[in] path The path for Accessible object
404 * @return The Accessible object corresponding to the path
406 Dali::Accessibility::Accessible* Find(const std::string& path) const;
409 * @brief Finds the Accessible object with the given address.
411 * @param[in] ptr The unique Address of the object
412 * @return The Accessible object corresponding to the path
414 Dali::Accessibility::Accessible* Find(const Dali::Accessibility::Address& ptr) const;
417 * @brief Returns the target object of the currently executed DBus method call.
419 * And any subclasses redefine `FindSelf` with a different return type as a convenient wrapper around dynamic_cast.
420 * @return The Accessible object
421 * @note When a DBus method is called on some object, this target object (`currentObject`) is temporarily saved by the bridge,
422 * because DBus handles the invocation target separately from the method arguments.
423 * We then use the saved object inside the 'glue' method (e.g. BridgeValue::GetMinimum)
424 * to call the equivalent method on the respective C++ object (this could be ScrollBar::AccessibleImpl::GetMinimum in the example given).
426 Dali::Accessibility::Accessible* FindSelf() const;
429 * @copydoc Dali::Accessibility::Bridge::FindByPath()
431 Dali::Accessibility::Accessible* FindByPath(const std::string& name) const override;
434 * @copydoc Dali::Accessibility::Bridge::SetApplicationName()
436 void SetApplicationName(std::string name) override
438 mApplication.mName = std::move(name);
442 mutable AppAccessible mApplication;
443 std::vector<Dali::Accessibility::Accessible*> mDefaultLabels;
444 bool mIsScreenReaderSuppressed = false;
449 * @param[in] id An ID (integer value)
454 * @brief Gets the ID.
455 * @return The ID to be set
460 * @brief Update registered events.
462 void UpdateRegisteredEvents();
464 using CacheElementType = std::tuple<
465 Dali::Accessibility::Address,
466 Dali::Accessibility::Address,
467 Dali::Accessibility::Address,
468 std::vector<Dali::Accessibility::Address>,
469 std::vector<std::string>,
471 Dali::Accessibility::Role,
473 std::array<uint32_t, 2>>;
476 * @brief Gets Items // NEED TO UPDATE!
480 DBus::ValueOrError<std::vector<CacheElementType>> GetItems();
483 * @brief Creates CacheElement.
485 * CreateCacheElement method works for GetItems which is a part of ATSPI protocol.
486 * ATSPI client library (libatspi from at-spi2-core) depending on cacheing policy configuration uses GetItems
487 * to pre-load entire accessible tree from application to its own cache in single dbus call.
488 * Otherwise the particular nodes in a tree are cached lazily when client library tries to access them.
489 * @param item Accessible to get information
490 * @return The elements to be cached
492 CacheElementType CreateCacheElement(Dali::Accessibility::Accessible* item);
496 virtual ~BridgeBase();
499 * @copydoc Dali::Accessibility::Bridge::ForceUp()
501 ForceUpResult ForceUp() override;
504 * @copydoc Dali::Accessibility::Bridge::ForceDown()
506 void ForceDown() override;
508 DBus::DBusServer mDbusServer;
509 DBusWrapper::ConnectionPtr mConnectionPtr;
511 DBus::DBusClient mRegistry;
512 bool IsBoundsChangedEventAllowed{false};
515 #endif // DALI_INTERNAL_ACCESSIBILITY_BRIDGE_BASE_H