32db1406561542b52f4368dadfd10eaaf915e9e1
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / Accessibility / Accessibility.cs
1 /*
2  * Copyright(c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 using System;
19 using System.ComponentModel;
20 using System.Runtime.InteropServices;
21 using Tizen.NUI.BaseComponents;
22 using System.Diagnostics.CodeAnalysis;
23
24 namespace Tizen.NUI.Accessibility
25 {
26     /// <summary>
27     /// Accessibility provides Dali-ATSPI interface which has functionality of Screen-Reader and general accessibility
28     /// </summary>
29     // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
30     [SuppressMessage("Microsoft.Design", "CA1724: Type names should not match namespaces")]
31     [SuppressMessage("Microsoft.Design", "CA1001:Types that own disposable fields should be disposable", Justification = "This is a singleton class and is not disposed")]
32     [EditorBrowsable(EditorBrowsableState.Never)]
33     public class Accessibility
34     {
35         #region Constructor, Destructor, Dispose
36         private Accessibility()
37         {
38             dummy = new View();
39             dummy.Name = "dali-atspi-singleton";
40         }
41         /// <summary>
42         /// destructor. This is HiddenAPI. recommended not to use in public.
43         /// </summary>
44         ~Accessibility()
45         {
46             Tizen.Log.Debug("NUI", $"Accessibility is destroyed\n");
47         }
48         #endregion Constructor, Destructor, Dispose
49
50
51         #region Property
52         /// <summary>
53         /// Instance for singleton
54         /// </summary>
55         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
56         [EditorBrowsable(EditorBrowsableState.Never)]
57         public static Accessibility Instance
58         {
59             get => accessibility;
60         }
61
62         /// <summary>
63         /// Flag to check whether the state of Accessibility is enabled or not.
64         /// </summary>
65         /// <remarks>
66         /// Getter returns true if Accessibility is enabled, false otherwise.
67         /// </remarks>
68         /// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
69         [EditorBrowsable(EditorBrowsableState.Never)]
70         public static bool IsEnabled
71         {
72             get
73             {
74                 return (bool)Interop.Accessibility.IsEnabled();
75             }
76         }
77
78         #endregion Property
79
80
81         #region Method
82         /// <summary>
83         /// Get the current status
84         /// </summary>
85         /// <returns>Current enabled status</returns>
86         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
87         [EditorBrowsable(EditorBrowsableState.Never)]
88         static public bool GetStatus()
89         {
90             return true;
91         }
92
93         /// <summary>
94         /// Start to speak
95         /// </summary>
96         /// <param name="sentence">Content to be spoken</param>
97         /// <param name="discardable">true to be stopped and discarded when other Say is triggered</param>
98         /// <returns></returns>
99         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
100         [EditorBrowsable(EditorBrowsableState.Never)]
101         public bool Say(string sentence, bool discardable)
102         {
103             IntPtr callbackIntPtr = IntPtr.Zero;
104             if (sayFinishedEventHandler != null)
105             {
106                 callback = SayFinishedEventCallback;
107                 callbackIntPtr = Marshal.GetFunctionPointerForDelegate<Delegate>(callback);
108             }
109             bool ret = Interop.Accessibility.Say(View.getCPtr(dummy), sentence, discardable, callbackIntPtr);
110             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
111             return ret;
112         }
113
114         /// <summary>
115         /// To make Say be paused or resumed
116         /// </summary>
117         /// <param name="pause">true to be paused, false to be resumed</param>
118         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
119         [EditorBrowsable(EditorBrowsableState.Never)]
120         public void PauseResume(bool pause)
121         {
122             Interop.Accessibility.PauseResume(View.getCPtr(dummy), pause);
123             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
124         }
125
126         /// <summary>
127         /// Cancels anything screen-reader is reading / has queued to read
128         /// </summary>
129         /// <param name="alsoNonDiscardable">whether to cancel non-discardable readings as well</param>
130         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
131         [EditorBrowsable(EditorBrowsableState.Never)]
132         public void StopReading(bool alsoNonDiscardable)
133         {
134             Interop.Accessibility.StopReading(View.getCPtr(dummy), alsoNonDiscardable);
135             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
136         }
137
138         /// <summary>
139         /// Suppress reading of screen-reader
140         /// </summary>
141         /// <param name="suppress">whether to suppress reading of screen-reader</param>
142         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
143         [EditorBrowsable(EditorBrowsableState.Never)]
144         public bool SuppressScreenReader(bool suppress)
145         {
146             bool ret = Interop.Accessibility.SuppressScreenReader(View.getCPtr(dummy), suppress);
147             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
148             return ret;
149         }
150
151         /// <summary>
152         /// Re-enables auto-initialization of AT-SPI bridge
153         /// </summary>
154         /// <remarks>
155         /// Normal applications do not have to call this function. The AT-SPI bridge is initialized on demand.
156         /// </remarks>
157         [EditorBrowsable(EditorBrowsableState.Never)]
158         public static void BridgeEnableAutoInit()
159         {
160             Interop.Accessibility.BridgeEnableAutoInit();
161             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
162         }
163
164         /// <summary>
165         /// Blocks auto-initialization of AT-SPI bridge
166         /// </summary>
167         /// <remarks>
168         /// Use this only if your application starts before DBus does, and call it early in Main().
169         /// When DBus is ready, call BridgeEnableAutoInit().
170         /// </remarks>
171         [EditorBrowsable(EditorBrowsableState.Never)]
172         public static void BridgeDisableAutoInit()
173         {
174             Interop.Accessibility.BridgeDisableAutoInit();
175             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
176         }
177
178         /// <summary>
179         ///  Get View that is used to highlight widget.
180         /// </summary>
181         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
182         [EditorBrowsable(EditorBrowsableState.Never)]
183         public View GetHighlightFrameView()
184         {
185             var ptr = Interop.ControlDevel.DaliAccessibilityAccessibleGetHighlightActor();
186             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
187             if (ptr == IntPtr.Zero)
188                 return null;
189             return new View(ptr, true);
190         }
191
192         /// <summary>
193         ///  Set view that will be used to highlight widget.
194         /// </summary>
195         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
196         [EditorBrowsable(EditorBrowsableState.Never)]
197         public void SetHighlightFrameView(View view)
198         {
199             Interop.ControlDevel.DaliAccessibilityAccessibleSetHighlightActor(View.getCPtr(view));
200             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
201         }
202
203         /// <summary>
204         ///  Get highligted View.
205         /// </summary>
206         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
207         [EditorBrowsable(EditorBrowsableState.Never)]
208         public View GetCurrentlyHighlightedView()
209         {
210             var ptr = Interop.ControlDevel.DaliAccessibilityAccessibleGetCurrentlyHighlightedActor();
211             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
212             if (ptr == IntPtr.Zero)
213                 return null;
214             return new View(ptr, true);
215         }
216
217         /// <summary>
218         ///  Clear highlight.
219         /// </summary>
220         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
221         [EditorBrowsable(EditorBrowsableState.Never)]
222         public bool ClearCurrentlyHighlightedView()
223         {
224             using (View view = GetCurrentlyHighlightedView())
225             {
226                 return view?.ClearAccessibilityHighlight() ?? false;
227             }
228         }
229         #endregion Method
230
231
232         #region Event, Enum, Struct, ETC
233         /// <summary>
234         /// Enum of Say finished event argument status
235         /// </summary>
236         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
237         [EditorBrowsable(EditorBrowsableState.Never)]
238         public enum SayFinishedState
239         {
240             /// <summary>
241             /// Invalid
242             /// </summary>
243             // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
244             [EditorBrowsable(EditorBrowsableState.Never)]
245             Invalid = -1,
246             /// <summary>
247             /// Cancelled
248             /// </summary>
249             // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
250             [EditorBrowsable(EditorBrowsableState.Never)]
251             Cancelled = 1,
252             /// <summary>
253             /// Stopped
254             /// </summary>
255             // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
256             [EditorBrowsable(EditorBrowsableState.Never)]
257             Stopped = 2,
258             /// <summary>
259             /// Skipped
260             /// </summary>
261             // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
262             [EditorBrowsable(EditorBrowsableState.Never)]
263             Skipped = 3,
264             /// <summary>
265             /// Paused
266             /// </summary>
267             // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
268             [EditorBrowsable(EditorBrowsableState.Never)]
269             Paused = 4,
270             /// <summary>
271             /// Resumed
272             /// </summary>
273             // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
274             [EditorBrowsable(EditorBrowsableState.Never)]
275             Resumed = 5
276         }
277
278         /// <summary>
279         /// When Say is finished, this event is triggered
280         /// </summary>
281         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
282         [EditorBrowsable(EditorBrowsableState.Never)]
283         public event EventHandler<SayFinishedEventArgs> SayFinished
284         {
285             add => sayFinishedEventHandler += value;
286             remove => sayFinishedEventHandler -= value;
287         }
288         #endregion Event, Enum, Struct, ETC
289
290
291         #region Internal
292         internal void PauseResume(View target, bool pause)
293         {
294             Interop.Accessibility.PauseResume(View.getCPtr(target), pause);
295             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
296         }
297
298         internal bool Say(View target, string sentence, bool discardable)
299         {
300             IntPtr callbackIntPtr = IntPtr.Zero;
301             if (sayFinishedEventHandler != null)
302             {
303                 callback = SayFinishedEventCallback;
304                 callbackIntPtr = Marshal.GetFunctionPointerForDelegate<Delegate>(callback);
305             }
306             bool ret = Interop.Accessibility.Say(View.getCPtr(target), sentence, discardable, callbackIntPtr);
307             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
308             return ret;
309         }
310         #endregion Internal
311
312
313         #region Private
314         private static readonly Accessibility accessibility = new Accessibility();
315
316         private event EventHandler<SayFinishedEventArgs> sayFinishedEventHandler;
317
318         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
319         private delegate void SayFinishedEventCallbackType(int result);
320
321         private SayFinishedEventCallbackType callback = null;
322
323         private void SayFinishedEventCallback(int result)
324         {
325             NUILog.Debug($"sayFinishedEventCallback(res={result}) called!");
326             sayFinishedEventHandler?.Invoke(this, new SayFinishedEventArgs(result));
327         }
328
329         private View dummy;
330
331         #endregion Private
332     }
333
334     /// <summary>
335     ///  Say Finished event arguments
336     /// </summary>
337     // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
338     [EditorBrowsable(EditorBrowsableState.Never)]
339     public class SayFinishedEventArgs : EventArgs
340     {
341         /// <summary>
342         /// The state of Say finished
343         /// </summary>
344         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
345         [EditorBrowsable(EditorBrowsableState.Never)]
346         public Accessibility.SayFinishedState State
347         {
348             private set;
349             get;
350         }
351
352         internal SayFinishedEventArgs(int result)
353         {
354             State = (Accessibility.SayFinishedState)(result);
355             NUILog.Debug($"SayFinishedEventArgs Constructor! State={State}");
356         }
357     }
358 }