[NUI] Change all CallingConvention to `Cdecl`
[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 static class Accessibility
34     {
35         #region Constructor
36         [SuppressMessage("Microsoft.Performance", "CA1810: Initialize reference type static fields inline", Justification = "Need to call native code")]
37         static Accessibility()
38         {
39             enabledSignalHandler = () =>
40             {
41                 Enabled?.Invoke(typeof(Accessibility), EventArgs.Empty);
42             };
43
44             disabledSignalHandler = () =>
45             {
46                 Disabled?.Invoke(typeof(Accessibility), EventArgs.Empty);
47             };
48
49             screenReaderEnabledSignalHandler = () =>
50             {
51                 ScreenReaderEnabled?.Invoke(typeof(Accessibility), EventArgs.Empty);
52             };
53
54             screenReaderDisabledSignalHandler = () =>
55             {
56                 ScreenReaderDisabled?.Invoke(typeof(Accessibility), EventArgs.Empty);
57             };
58
59             Interop.Accessibility.RegisterEnabledDisabledSignalHandler(enabledSignalHandler, disabledSignalHandler);
60             Interop.Accessibility.RegisterScreenReaderEnabledDisabledSignalHandler(screenReaderEnabledSignalHandler, screenReaderDisabledSignalHandler);
61         }
62         #endregion Constructor
63
64         #region Property
65         /// <summary>
66         /// Flag to check whether the state of Accessibility is enabled or not.
67         /// </summary>
68         /// <remarks>
69         /// Getter returns true if Accessibility is enabled, false otherwise.
70         /// </remarks>
71         /// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
72         [EditorBrowsable(EditorBrowsableState.Never)]
73         public static bool IsEnabled
74         {
75             get
76             {
77                 return (bool)Interop.Accessibility.IsEnabled();
78             }
79         }
80
81         /// <summary>
82         /// Flag to check whether the state of Screen Reader is enabled or not.
83         /// </summary>
84         /// <remarks>
85         /// Getter returns true if Screen Reader is enabled, false otherwise.
86         /// </remarks>
87         /// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
88         [EditorBrowsable(EditorBrowsableState.Never)]
89         public static bool IsScreenReaderEnabled
90         {
91             get
92             {
93                 return (bool)Interop.Accessibility.IsScreenReaderEnabled();
94             }
95         }
96
97         #endregion Property
98
99         #region Method
100         /// <summary>
101         /// Start to speak
102         /// </summary>
103         /// <param name="sentence">Content to be spoken</param>
104         /// <param name="discardable">true to be stopped and discarded when other Say is triggered</param>
105         /// <returns></returns>
106         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
107         [EditorBrowsable(EditorBrowsableState.Never)]
108         public static bool Say(string sentence, bool discardable)
109         {
110             bool ret = Interop.Accessibility.Say(sentence, discardable, Marshal.GetFunctionPointerForDelegate<Delegate>(callback));
111
112             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
113             return ret;
114         }
115
116         /// <summary>
117         /// To make Say be paused or resumed
118         /// </summary>
119         /// <param name="pause">true to be paused, false to be resumed</param>
120         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
121         [EditorBrowsable(EditorBrowsableState.Never)]
122         public static void PauseResume(bool pause)
123         {
124             Interop.Accessibility.PauseResume(pause);
125             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
126         }
127
128         /// <summary>
129         /// Cancels anything screen-reader is reading / has queued to read
130         /// </summary>
131         /// <param name="alsoNonDiscardable">whether to cancel non-discardable readings as well</param>
132         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
133         [EditorBrowsable(EditorBrowsableState.Never)]
134         public static void StopReading(bool alsoNonDiscardable)
135         {
136             Interop.Accessibility.StopReading(alsoNonDiscardable);
137             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
138         }
139
140         /// <summary>
141         /// Suppress reading of screen-reader
142         /// </summary>
143         /// <param name="suppress">whether to suppress reading of screen-reader</param>
144         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
145         [EditorBrowsable(EditorBrowsableState.Never)]
146         public static bool SuppressScreenReader(bool suppress)
147         {
148             bool ret = Interop.Accessibility.SuppressScreenReader(suppress);
149             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
150             return ret;
151         }
152
153         /// <summary>
154         /// Re-enables auto-initialization of AT-SPI bridge
155         /// </summary>
156         /// <remarks>
157         /// Normal applications do not have to call this function. The AT-SPI bridge is initialized on demand.
158         /// </remarks>
159         [EditorBrowsable(EditorBrowsableState.Never)]
160         public static void BridgeEnableAutoInit()
161         {
162             Interop.Accessibility.BridgeEnableAutoInit();
163             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
164         }
165
166         /// <summary>
167         /// Blocks auto-initialization of AT-SPI bridge
168         /// </summary>
169         /// <remarks>
170         /// Use this only if your application starts before DBus does, and call it early in Main().
171         /// When DBus is ready, call BridgeEnableAutoInit().
172         /// </remarks>
173         [EditorBrowsable(EditorBrowsableState.Never)]
174         public static void BridgeDisableAutoInit()
175         {
176             Interop.Accessibility.BridgeDisableAutoInit();
177             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
178         }
179
180         /// <summary>
181         ///  Get View that is used to highlight widget.
182         /// </summary>
183         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
184         [EditorBrowsable(EditorBrowsableState.Never)]
185         public static View GetHighlightFrameView()
186         {
187             var ptr = Interop.ControlDevel.DaliAccessibilityAccessibleGetHighlightActor();
188             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
189             if (ptr == IntPtr.Zero)
190                 return null;
191             return new View(ptr, true);
192         }
193
194         /// <summary>
195         ///  Set view that will be used to highlight widget.
196         /// </summary>
197         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
198         [EditorBrowsable(EditorBrowsableState.Never)]
199         public static void SetHighlightFrameView(View view)
200         {
201             Interop.ControlDevel.DaliAccessibilityAccessibleSetHighlightActor(View.getCPtr(view));
202             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
203         }
204
205         /// <summary>
206         ///  Get highligted View.
207         /// </summary>
208         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
209         [EditorBrowsable(EditorBrowsableState.Never)]
210         public static View GetCurrentlyHighlightedView()
211         {
212             var ptr = Interop.ControlDevel.DaliAccessibilityAccessibleGetCurrentlyHighlightedActor();
213
214             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
215
216             return dummyHandle.GetInstanceSafely<View>(ptr);
217         }
218
219         /// <summary>
220         ///  Clear highlight.
221         /// </summary>
222         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
223         [EditorBrowsable(EditorBrowsableState.Never)]
224         public static bool ClearCurrentlyHighlightedView()
225         {
226             var view = GetCurrentlyHighlightedView();
227
228             return view?.ClearAccessibilityHighlight() ?? false;
229         }
230         #endregion Method
231
232
233         #region Event, Enum, Struct, ETC
234         /// <summary>
235         /// Enum of Say finished event argument status
236         /// </summary>
237         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
238         [EditorBrowsable(EditorBrowsableState.Never)]
239         public enum SayFinishedState
240         {
241             /// <summary>
242             /// Invalid
243             /// </summary>
244             // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
245             [EditorBrowsable(EditorBrowsableState.Never)]
246             Invalid = -1,
247             /// <summary>
248             /// Cancelled
249             /// </summary>
250             // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
251             [EditorBrowsable(EditorBrowsableState.Never)]
252             Cancelled = 1,
253             /// <summary>
254             /// Stopped
255             /// </summary>
256             // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
257             [EditorBrowsable(EditorBrowsableState.Never)]
258             Stopped = 2,
259             /// <summary>
260             /// Skipped
261             /// </summary>
262             // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
263             [EditorBrowsable(EditorBrowsableState.Never)]
264             Skipped = 3,
265             /// <summary>
266             /// Paused
267             /// </summary>
268             // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
269             [EditorBrowsable(EditorBrowsableState.Never)]
270             Paused = 4,
271             /// <summary>
272             /// Resumed
273             /// </summary>
274             // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
275             [EditorBrowsable(EditorBrowsableState.Never)]
276             Resumed = 5
277         }
278
279         /// <summary>
280         /// When Say is finished, this event is triggered
281         /// </summary>
282         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
283         [EditorBrowsable(EditorBrowsableState.Never)]
284         public static event EventHandler<SayFinishedEventArgs> SayFinished;
285
286         /// <summary>
287         /// Triggered whenever the value of IsEnabled would change from false to true
288         /// </summary>
289         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
290         [EditorBrowsable(EditorBrowsableState.Never)]
291         public static event EventHandler Enabled;
292
293         /// <summary>
294         /// Triggered whenever the value of IsEnabled would change from true to false
295         /// </summary>
296         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
297         [EditorBrowsable(EditorBrowsableState.Never)]
298         public static event EventHandler Disabled;
299
300         /// <summary>
301         /// Triggered whenever the value of IsScreenReaderEnabled would change from false to true
302         /// </summary>
303         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
304         [EditorBrowsable(EditorBrowsableState.Never)]
305         public static event EventHandler ScreenReaderEnabled;
306
307         /// <summary>
308         /// Triggered whenever the value of IsScreenReaderEnabled would change from true to false
309         /// </summary>
310         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
311         [EditorBrowsable(EditorBrowsableState.Never)]
312         public static event EventHandler ScreenReaderDisabled;
313
314         #endregion Event, Enum, Struct, ETC
315
316         #region Private
317
318         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
319         private delegate void SayFinishedEventCallbackType(int result);
320
321         private static SayFinishedEventCallbackType callback = SayFinishedEventCallback;
322
323         private static Interop.Accessibility.EnabledDisabledSignalHandler enabledSignalHandler = null;
324
325         private static Interop.Accessibility.EnabledDisabledSignalHandler disabledSignalHandler = null;
326
327         private static Interop.Accessibility.EnabledDisabledSignalHandler screenReaderEnabledSignalHandler = null;
328
329         private static Interop.Accessibility.EnabledDisabledSignalHandler screenReaderDisabledSignalHandler = null;
330
331         private static void SayFinishedEventCallback(int result)
332         {
333             NUILog.Debug($"sayFinishedEventCallback(res={result}) called!");
334             SayFinished?.Invoke(typeof(Accessibility), new SayFinishedEventArgs(result));
335         }
336
337         private static BaseHandle dummyHandle = new BaseHandle();
338
339         #endregion Private
340     }
341
342     /// <summary>
343     ///  Say Finished event arguments
344     /// </summary>
345     // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
346     [EditorBrowsable(EditorBrowsableState.Never)]
347     public class SayFinishedEventArgs : EventArgs
348     {
349         /// <summary>
350         /// The state of Say finished
351         /// </summary>
352         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
353         [EditorBrowsable(EditorBrowsableState.Never)]
354         public Accessibility.SayFinishedState State
355         {
356             private set;
357             get;
358         }
359
360         internal SayFinishedEventArgs(int result)
361         {
362             State = (Accessibility.SayFinishedState)(result);
363             NUILog.Debug($"SayFinishedEventArgs Constructor! State={State}");
364         }
365     }
366 }