2 * Copyright(c) 2021 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 using System.ComponentModel;
20 using System.Runtime.InteropServices;
21 using Tizen.NUI.BaseComponents;
22 using System.Diagnostics.CodeAnalysis;
24 namespace Tizen.NUI.Accessibility
27 /// Accessibility provides Dali-ATSPI interface which has functionality of Screen-Reader and general accessibility
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
36 [SuppressMessage("Microsoft.Performance", "CA1810: Initialize reference type static fields inline", Justification = "Need to call native code")]
37 static Accessibility()
39 enabledSignalHandler = () =>
41 Enabled?.Invoke(typeof(Accessibility), EventArgs.Empty);
44 disabledSignalHandler = () =>
46 Disabled?.Invoke(typeof(Accessibility), EventArgs.Empty);
49 screenReaderEnabledSignalHandler = () =>
51 ScreenReaderEnabled?.Invoke(typeof(Accessibility), EventArgs.Empty);
54 screenReaderDisabledSignalHandler = () =>
56 ScreenReaderDisabled?.Invoke(typeof(Accessibility), EventArgs.Empty);
59 Interop.Accessibility.RegisterEnabledDisabledSignalHandler(enabledSignalHandler, disabledSignalHandler);
60 Interop.Accessibility.RegisterScreenReaderEnabledDisabledSignalHandler(screenReaderEnabledSignalHandler, screenReaderDisabledSignalHandler);
62 #endregion Constructor
66 /// Flag to check whether the state of Accessibility is enabled or not.
69 /// Getter returns true if Accessibility is enabled, false otherwise.
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
77 return (bool)Interop.Accessibility.IsEnabled();
82 /// Flag to check whether the state of Screen Reader is enabled or not.
85 /// Getter returns true if Screen Reader is enabled, false otherwise.
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
93 return (bool)Interop.Accessibility.IsScreenReaderEnabled();
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)
110 bool ret = Interop.Accessibility.Say(sentence, discardable, Marshal.GetFunctionPointerForDelegate<Delegate>(callback));
112 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
117 /// To make Say be paused or resumed
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)
124 Interop.Accessibility.PauseResume(pause);
125 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
129 /// Cancels anything screen-reader is reading / has queued to read
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)
136 Interop.Accessibility.StopReading(alsoNonDiscardable);
137 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
141 /// Suppress reading of screen-reader
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)
148 bool ret = Interop.Accessibility.SuppressScreenReader(suppress);
149 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
154 /// Re-enables auto-initialization of AT-SPI bridge
157 /// Normal applications do not have to call this function. The AT-SPI bridge is initialized on demand.
159 [EditorBrowsable(EditorBrowsableState.Never)]
160 public static void BridgeEnableAutoInit()
162 Interop.Accessibility.BridgeEnableAutoInit();
163 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
167 /// Blocks auto-initialization of AT-SPI bridge
170 /// Use this only if your application starts before DBus does, and call it early in Main().
171 /// When DBus is ready, call BridgeEnableAutoInit().
173 [EditorBrowsable(EditorBrowsableState.Never)]
174 public static void BridgeDisableAutoInit()
176 Interop.Accessibility.BridgeDisableAutoInit();
177 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
181 /// Get View that is used to highlight widget.
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()
187 var ptr = Interop.ControlDevel.DaliAccessibilityAccessibleGetHighlightActor();
188 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
189 if (ptr == IntPtr.Zero)
191 return new View(ptr, true);
195 /// Set view that will be used to highlight widget.
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)
201 Interop.ControlDevel.DaliAccessibilityAccessibleSetHighlightActor(View.getCPtr(view));
202 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
206 /// Get highligted View.
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()
212 var ptr = Interop.ControlDevel.DaliAccessibilityAccessibleGetCurrentlyHighlightedActor();
214 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
216 return dummyHandle.GetInstanceSafely<View>(ptr);
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()
226 var view = GetCurrentlyHighlightedView();
228 return view?.ClearAccessibilityHighlight() ?? false;
233 #region Event, Enum, Struct, ETC
235 /// Enum of Say finished event argument status
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
244 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
245 [EditorBrowsable(EditorBrowsableState.Never)]
250 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
251 [EditorBrowsable(EditorBrowsableState.Never)]
256 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
257 [EditorBrowsable(EditorBrowsableState.Never)]
262 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
263 [EditorBrowsable(EditorBrowsableState.Never)]
268 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
269 [EditorBrowsable(EditorBrowsableState.Never)]
274 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
275 [EditorBrowsable(EditorBrowsableState.Never)]
280 /// When Say is finished, this event is triggered
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;
287 /// Triggered whenever the value of IsEnabled would change from false to true
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;
294 /// Triggered whenever the value of IsEnabled would change from true to false
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;
301 /// Triggered whenever the value of IsScreenReaderEnabled would change from false to true
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;
308 /// Triggered whenever the value of IsScreenReaderEnabled would change from true to false
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;
314 #endregion Event, Enum, Struct, ETC
318 [UnmanagedFunctionPointer(CallingConvention.StdCall)]
319 private delegate void SayFinishedEventCallbackType(int result);
321 private static SayFinishedEventCallbackType callback = SayFinishedEventCallback;
323 private static Interop.Accessibility.EnabledDisabledSignalHandler enabledSignalHandler = null;
325 private static Interop.Accessibility.EnabledDisabledSignalHandler disabledSignalHandler = null;
327 private static Interop.Accessibility.EnabledDisabledSignalHandler screenReaderEnabledSignalHandler = null;
329 private static Interop.Accessibility.EnabledDisabledSignalHandler screenReaderDisabledSignalHandler = null;
331 private static void SayFinishedEventCallback(int result)
333 NUILog.Debug($"sayFinishedEventCallback(res={result}) called!");
334 SayFinished?.Invoke(typeof(Accessibility), new SayFinishedEventArgs(result));
337 private static BaseHandle dummyHandle = new BaseHandle();
343 /// Say Finished event arguments
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
350 /// The state of Say finished
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
360 internal SayFinishedEventArgs(int result)
362 State = (Accessibility.SayFinishedState)(result);
363 NUILog.Debug($"SayFinishedEventArgs Constructor! State={State}");