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