(Canvas Renderer) Moved Devel Headers into sub-folder to improve SAM score
[platform/core/uifw/dali-adaptor.git] / dali / devel-api / adaptor-framework / accessibility-bridge.h
1 #ifndef DALI_ADAPTOR_ACCESSIBILITY_BRIDGE_H
2 #define DALI_ADAPTOR_ACCESSIBILITY_BRIDGE_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/actor.h>
23 #include <dali/public-api/math/rect.h>
24 #include <functional>
25 #include <memory>
26 #include <stdexcept>
27 #include <string>
28 #include <unordered_set>
29
30 // INTERNAL INCLUDES
31 #include <dali/devel-api/adaptor-framework/accessibility.h>
32 #include <dali/public-api/adaptor-framework/window.h>
33
34 namespace Dali
35 {
36 namespace Accessibility
37 {
38 class Accessible;
39 class ProxyAccessible;
40
41 /**
42  * @brief Base class for different accessibility bridges.
43  *
44  * Bridge is resposible for initializing and managing connection on accessibility bus.
45  * Accessibility clients will not get any information about UI without initialized and upraised bridge.
46  * Concrete implementation depends on the accessibility technology available on the platform.
47  *
48  * @note This class is singleton.
49  */
50 struct DALI_ADAPTOR_API Bridge
51 {
52   enum class ForceUpResult
53   {
54     JUST_STARTED,
55     ALREADY_UP,
56     FAILED
57   };
58
59   /**
60    * @brief Destructor
61    */
62   virtual ~Bridge() = default;
63
64   /**
65    * @brief Gets bus name which bridge is initialized on.
66    *
67    * @return The bus name
68    */
69   virtual const std::string& GetBusName() const = 0;
70
71   /**
72    * @brief Registers top level window.
73    *
74    * Hierarchy of objects visible for accessibility clients is based on tree-like
75    * structure created from Actors objects. This method allows to connect chosen
76    * object as direct ancestor of application and therefore make it visible for
77    * accessibility clients.
78    *
79    * @param[in] object The accessible object
80    */
81   virtual void AddTopLevelWindow(Accessible* object) = 0;
82
83   /**
84    * @brief Removes top level window.
85    *
86    * Hierarchy of objects visible for accessibility clients is based on tree-like
87    * structure created from Actors objects. This method removes previously added
88    * window from visible accessibility objects.
89    *
90    * @param[in] object The accessible object
91    */
92   virtual void RemoveTopLevelWindow(Accessible* object) = 0;
93
94   /**
95    * @brief Adds object on the top of the stack of "default label" sourcing objects.
96    *
97    * @see GetDefaultLabel
98    *
99    * @param[in] object The accessible object
100    */
101   virtual void RegisterDefaultLabel(Accessible* object) = 0;
102
103   /**
104    * @brief Removes object from the stack of "default label" sourcing objects.
105    *
106    * @see GetDefaultLabel
107    *
108    * @param[in] object The accessible object
109    */
110   virtual void UnregisterDefaultLabel(Accessible* object) = 0;
111
112   /**
113    * @brief Gets the top-most object from the stack of "default label" sourcing objects.
114    *
115    * The "default label" is a reading material (text) derived from an accesibility object
116    * that could be read by screen-reader immediately after the navigation context has changed
117    * (window activates, popup shows up, tab changes) and before first UI element is highlighted.
118    *
119    * @return The handler to accessibility object
120    * @note This is a Tizen only feature not present in upstream ATSPI.
121    * Feature can be enabled/disabled for particular context root object
122    * by setting value of its accessibility attribute "default_label".
123    * Following strings are valid values for "default_label" attribute: "enabled", "disabled".
124    * Any other value will be interpreted as "enabled".
125    */
126   virtual Accessible* GetDefaultLabel() const = 0;
127
128   /**
129    * @brief Sets name of current application which will be visible on accessibility bus.
130    *
131    * @param[in] name The application name
132    */
133   virtual void SetApplicationName(std::string name) = 0;
134
135   /**
136    * @brief Sets the name of the GUI toolkit that AT-SPI clients can query.
137    *
138    * The default name is "dali".
139    *
140    * @param toolkitName The toolkit name
141    */
142   virtual void SetToolkitName(std::string_view toolkitName) = 0;
143
144   /**
145    * @brief Gets object being root of accessibility tree.
146    *
147    * @return handler to accessibility object
148    */
149   virtual Accessible* GetApplication() const = 0;
150
151   /**
152    * @brief Finds an object in accessibility tree.
153    *
154    * @param[in] path The path to object
155    *
156    * @return The handler to accessibility object
157    */
158   virtual Accessible* FindByPath(const std::string& path) const = 0;
159
160   /**
161    * @brief Notifies accessibility dbus that window has just been shown.
162    *
163    * @param[in] window The window to be shown
164    */
165   virtual void WindowShown(Window window) = 0;
166
167   /**
168    * @brief Notifies accessibility dbus that window has just been hidden.
169    *
170    * @param[in] window The window to be hidden
171    */
172   virtual void WindowHidden(Window window) = 0;
173
174   /**
175    * @brief Notifies accessibility dbus that window has just been focused.
176    *
177    * @param[in] window The window to be focused
178    */
179   virtual void WindowFocused(Window window) = 0;
180
181   /**
182    * @brief Notifies accessibility dbus that window has just been out of focus.
183    *
184    * @param[in] window The window to be out of focus
185    */
186   virtual void WindowUnfocused(Window window) = 0;
187
188   /**
189    * @brief Initializes accessibility bus.
190    */
191   virtual void Initialize() = 0;
192
193   /**
194    * @brief Terminates accessibility bus.
195    */
196   virtual void Terminate() = 0;
197
198   /**
199    * @brief This method is called, when bridge is being activated.
200    */
201   virtual ForceUpResult ForceUp()
202   {
203     if(mData)
204     {
205       return ForceUpResult::ALREADY_UP;
206     }
207     mData          = std::make_shared<Data>();
208     mData->mBridge = this;
209     return ForceUpResult::JUST_STARTED;
210   }
211
212   /**
213    * @brief This method is called, when bridge is being deactivated.
214    */
215   virtual void ForceDown() = 0;
216
217   /**
218    * @brief Checks if bridge is activated or not.
219    * @return True if brige is activated.
220    */
221   bool IsUp() const
222   {
223     return bool(mData);
224   }
225
226   /**
227    * @brief Emits cursor-moved event on at-spi bus.
228    *
229    * @param[in] obj The accessible object
230    * @param[in] cursorPosition The new cursor position
231    **/
232   virtual void EmitCursorMoved(Accessible* obj, unsigned int cursorPosition) = 0;
233
234   /**
235    * @brief Emits active-descendant-changed event on at-spi bus.
236    *
237    * @param[in] obj The accessible object
238    * @param[in] child The child of the object
239    **/
240   virtual void EmitActiveDescendantChanged(Accessible* obj, Accessible* child) = 0;
241
242   /**
243    * @brief Emits text-changed event on at-spi bus.
244    *
245    * @param[in] obj The accessible object
246    * @param[in] state The changed state for text, such as Inserted or Deleted
247    * @param[in] position The cursor position
248    * @param[in] length The text length
249    * @param[in] content The changed text
250    **/
251   virtual void EmitTextChanged(Accessible* obj, TextChangedState state, unsigned int position, unsigned int length, const std::string& content) = 0;
252
253   /**
254    * @brief Emits MoveOuted event on at-spi bus.
255    *
256    * @param[in] obj Accessible object
257    * @param[in] type Direction type when an Accessible object moves out of screen
258    **/
259   virtual void EmitMovedOutOfScreen(Accessible* obj, ScreenRelativeMoveType type) = 0;
260
261   /**
262    * @brief Emits "org.a11y.atspi.Socket.Available" event on AT-SPI bus.
263    *
264    * @param obj Accessible object
265    */
266   virtual void EmitSocketAvailable(Accessible* obj) = 0;
267
268   /**
269    * @brief Emits state-changed event on at-spi bus.
270    *
271    * @param[in] obj The accessible object
272    * @param[in] state The accessibility state (SHOWING, HIGHLIGHTED, etc)
273    * @param[in] newValue Whether the state value is changed to new value or not.
274    * @param[in] reserved Reserved. (Currently, this argument is not implemented in dali)
275    **/
276   virtual void EmitStateChanged(Accessible* obj, State state, int newValue, int reserved = 0) = 0;
277
278   /**
279    * @brief Emits window event on at-spi bus.
280    *
281    * @param[in] obj The accessible object
282    * @param[in] event The enumerated window event
283    * @param[in] detail The additional parameter which interpretation depends on chosen event
284    **/
285   virtual void Emit(Accessible* obj, WindowEvent event, unsigned int detail = 0) = 0;
286
287   /**
288    * @brief Emits property-changed event on at-spi bus.
289    *
290    * @param[in] obj The accessible object
291    * @param[in] event Property changed event
292    **/
293   virtual void Emit(Accessible* obj, ObjectPropertyChangeEvent event) = 0;
294
295   /**
296    * @brief Emits bounds-changed event on at-spi bus.
297    *
298    * @param[in] obj The accessible object
299    * @param[in] rect The rectangle for changed bounds
300    **/
301   virtual void EmitBoundsChanged(Accessible* obj, Rect<> rect) = 0;
302
303   /**
304    * @brief Emits key event on at-spi bus.
305    *
306    * Screen-reader might receive this event and reply, that given keycode is consumed. In that case
307    * further processing of the keycode should be ignored.
308    *
309    * @param[in] type Key event type
310    * @param[in] keyCode Key code
311    * @param[in] keyName Key name
312    * @param[in] timeStamp Time stamp
313    * @param[in] isText Whether it's text or not
314    * @return Whether this event is consumed or not
315    **/
316   virtual Consumed Emit(KeyEventType type, unsigned int keyCode, const std::string& keyName, unsigned int timeStamp, bool isText) = 0;
317
318   /**
319    * @brief Reads given text by screen reader
320    *
321    * @param[in] text The text to read
322    * @param[in] discardable If TRUE, reading can be discarded by subsequent reading requests,
323    * if FALSE the reading must finish before next reading request can be started
324    * @param[in] callback the callback function that is called on reading signals emitted
325    * during processing of this reading request.
326    * Callback can be one of the following signals:
327    * ReadingCancelled, ReadingStopped, ReadingSkipped
328    */
329   virtual void Say(const std::string& text, bool discardable, std::function<void(std::string)> callback) = 0;
330
331   /**
332    * @brief Force accessibility client to pause.
333    */
334   virtual void Pause() = 0;
335
336   /**
337    * @brief Force accessibility client to resume.
338    */
339   virtual void Resume() = 0;
340
341   /**
342    * @brief Cancels anything screen-reader is reading / has queued to read
343    *
344    * @param[in] alsoNonDiscardable whether to cancel non-discardable readings as well
345    */
346   virtual void StopReading(bool alsoNonDiscardable) = 0;
347
348   /**
349    * @brief Suppresses reading of screen-reader
350    *
351    * @param[in] suppress whether to suppress reading of screen-reader
352    */
353   virtual void SuppressScreenReader(bool suppress) = 0;
354
355   /**
356    * @brief Gets screen reader status.
357    *
358    * @return True if screen reader is enabled
359    */
360   virtual bool GetScreenReaderEnabled() = 0;
361
362   /**
363    * @brief Gets ATSPI status.
364    *
365    * @return True if ATSPI is enabled
366    */
367   virtual bool IsEnabled() = 0;
368
369   /**
370    * @brief Calls socket.Embed(plug) via D-Bus.
371    *
372    * @param[in] plug The plug
373    * @param[in] socket The socket
374    *
375    * @return Address returned by the D-Bus call.
376    *
377    * @note Remote object pointed to by 'socket' must implement 'org.a11y.atspi.Socket'.
378    * @see UnembedSocket()
379    */
380   virtual Address EmbedSocket(const Address& plug, const Address& socket) = 0;
381
382   /**
383    * @brief Calls socket.Embedded(plug) via D-Bus.
384    *
385    * The "Embedded" D-Bus method is an ATK extension.
386    * See 'impl_Embedded' in AT_SPI2_ATK/atk-adaptor/adaptors/socket-adaptor.c for more information.
387    *
388    * @param[in] plug The plug
389    * @param[in] socket The socket
390    */
391   virtual void EmbedAtkSocket(const Address& plug, const Address& socket) = 0;
392
393   /**
394    * @brief Calls socket.Unmbed(plug) via D-Bus.
395    *
396    * @param[in] plug The plug
397    * @param[in] socket The socket
398    *
399    * @note Remote object pointed to by 'socket' must implement 'org.a11y.atspi.Socket'.
400    * @see EmbedSocket()
401    */
402   virtual void UnembedSocket(const Address& plug, const Address& socket) = 0;
403
404   /**
405    * @brief Calls socket.SetOffset(x, y) via D-Bus.
406    *
407    * The "SetOffset" D-Bus method is a DALi extension. It can be used to inform a DALi widget about
408    * its position on the screen.
409    *
410    * @param[in] socket The socket
411    * @param[in] x Horizontal offset
412    * @param[in] y Vertical offset
413    *
414    * @note Remote object pointed to by 'socket' must implement 'org.a11y.atspi.Socket'.
415    * @see EmbedSocket()
416    * @see SetExtentsOffset()
417    */
418   virtual void SetSocketOffset(ProxyAccessible* socket, std::int32_t x, std::int32_t y) = 0;
419
420   /**
421    * @brief Sets the global extents offset.
422    *
423    * This offset will be added during serialization of GetExtents() return value to D-Bus.
424    * Local calls to GetExtents() are unaffected.
425    *
426    * @param[in] x Horizontal offset
427    * @param[in] y Vertical offset
428    *
429    * @see SetSocketOffset()
430    * @see Dali::Accessibility::Component::GetExtents()
431    */
432   virtual void SetExtentsOffset(std::int32_t x, std::int32_t y) = 0;
433
434   /**
435    * @brief Sets the preferred bus name.
436    *
437    * If the Bridge is enabled, it will immediately release the previous name and request the new one.
438    *
439    * Otherwise, the Bridge will request this name on AT-SPI activation (and release it on deactivation).
440    * It is up to the caller to determine whether a given name will be available in the system.
441    *
442    * @param preferredBusName The preferred bus name
443    */
444   virtual void SetPreferredBusName(std::string_view preferredBusName) = 0;
445
446   /**
447    * @brief Returns instance of bridge singleton object.
448    *
449    * @return The current bridge object
450    **/
451   static std::shared_ptr<Bridge> GetCurrentBridge();
452
453   /**
454    * @brief Blocks auto-initialization of AT-SPI bridge
455    *
456    * Use this only if your application starts before DBus does, and call it early in main()
457    * (before GetCurrentBridge() is called by anyone). GetCurrentBridge() will then return an
458    * instance of DummyBridge.
459    *
460    * When DBus is ready, call EnableAutoInit(). Please note that GetCurrentBridge() may still
461    * return an instance of DummyBridge if AT-SPI was disabled at compile time or using an
462    * environment variable, or if creating the real bridge failed.
463    *
464    * @see Dali::Accessibility::DummyBridge
465    * @see Dali::Accessibility::Bridge::EnableAutoInit
466    */
467   static void DisableAutoInit();
468
469   /**
470    * @brief Re-enables auto-initialization of AT-SPI bridge
471    *
472    * Normal applications do not have to call this function. GetCurrentBridge() tries to
473    * initialize the AT-SPI bridge when it is called for the first time.
474    *
475    * @see Dali::Accessibility::Bridge::DisableAutoInit
476    * @see Dali::Accessibility::Bridge::AddTopLevelWindow
477    * @see Dali::Accessibility::Bridge::SetApplicationName
478    */
479   static void EnableAutoInit();
480
481   /**
482    * @brief Encodes a widget ID as a usable bus name.
483    *
484    * @param widgetInstanceId The instance ID of a widget
485    * @return std::string Encoded bus name
486    *
487    * @see SetPreferredBusName
488    */
489   static std::string MakeBusNameForWidget(std::string_view widgetInstanceId);
490
491   static Signal<void()>& EnabledSignal()
492   {
493     return mEnabledSignal;
494   }
495
496   static Signal<void()>& DisabledSignal()
497   {
498     return mDisabledSignal;
499   }
500
501   static Signal<void()>& ScreenReaderEnabledSignal()
502   {
503     return mScreenReaderEnabledSignal;
504   }
505
506   static Signal<void()>& ScreenReaderDisabledSignal()
507   {
508     return mScreenReaderDisabledSignal;
509   }
510
511 protected:
512   struct Data
513   {
514     std::unordered_set<const Accessible*> mKnownObjects;
515     std::string                           mBusName;
516     Bridge*                               mBridge = nullptr;
517     Actor                                 mHighlightActor;
518     Actor                                 mCurrentlyHighlightedActor;
519     std::pair<std::int32_t, std::int32_t> mExtentsOffset{0, 0};
520   };
521   std::shared_ptr<Data> mData;
522   friend class Accessible;
523
524   enum class AutoInitState
525   {
526     DISABLED,
527     ENABLED
528   };
529
530   inline static AutoInitState mAutoInitState = AutoInitState::ENABLED;
531
532   inline static Signal<void()> mEnabledSignal;
533   inline static Signal<void()> mDisabledSignal;
534   inline static Signal<void()> mScreenReaderEnabledSignal;
535   inline static Signal<void()> mScreenReaderDisabledSignal;
536
537   /**
538    * @brief Registers accessible object to be known in bridge object.
539    *
540    * Bridge must known about all currently alive accessible objects, as some requst
541    * might come and object will be identified by number id (it's memory address).
542    * To avoid memory corruption number id is checked against set of known objects.
543    *
544    * @param[in] object The accessible object
545    **/
546   void RegisterOnBridge(const Accessible* object);
547
548   /**
549    * @brief Tells bridge, that given object is considered root (doesn't have any parents).
550    *
551    * All root objects will have the same parent - application object. Application object
552    * is controlled by bridge and private.
553    *
554    * @param[in] owner The accessible object
555    **/
556   void SetIsOnRootLevel(Accessible* owner);
557 };
558
559 /**
560  * @brief Checks if ATSPI is activated or not.
561  * @return True if ATSPI is activated.
562  */
563 inline bool IsUp()
564 {
565   if(Bridge::GetCurrentBridge() == nullptr)
566   {
567     return false;
568   }
569
570   if(Bridge::GetCurrentBridge()->IsEnabled() == false)
571   {
572     return false;
573   }
574
575   return Bridge::GetCurrentBridge()->IsUp();
576 }
577
578 } // namespace Accessibility
579 } // namespace Dali
580
581 #endif // DALI_ADAPTOR_ACCESSIBILITY_BRIDGE_H