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 class Accessibility
35 #region Constructor, Destructor, Dispose
36 private Accessibility()
39 dummy.Name = "dali-atspi-singleton";
42 static Accessibility()
44 enabledSignalHandler = () =>
46 Enabled?.Invoke(typeof(Accessibility), EventArgs.Empty);
49 disabledSignalHandler = () =>
51 Disabled?.Invoke(typeof(Accessibility), EventArgs.Empty);
54 Interop.Accessibility.RegisterEnabledDisabledSignalHandler(enabledSignalHandler, disabledSignalHandler);
58 /// destructor. This is HiddenAPI. recommended not to use in public.
62 Interop.Accessibility.RegisterEnabledDisabledSignalHandler(null, null);
64 Tizen.Log.Debug("NUI", $"Accessibility is destroyed\n");
66 #endregion Constructor, Destructor, Dispose
71 /// Instance for singleton
73 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
74 [EditorBrowsable(EditorBrowsableState.Never)]
75 public static Accessibility Instance
81 /// Flag to check whether the state of Accessibility is enabled or not.
84 /// Getter returns true if Accessibility is enabled, false otherwise.
86 /// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
87 [EditorBrowsable(EditorBrowsableState.Never)]
88 public static bool IsEnabled
92 return (bool)Interop.Accessibility.IsEnabled();
101 /// Get the current status
103 /// <returns>Current enabled status</returns>
104 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
105 [EditorBrowsable(EditorBrowsableState.Never)]
106 static public bool GetStatus()
114 /// <param name="sentence">Content to be spoken</param>
115 /// <param name="discardable">true to be stopped and discarded when other Say is triggered</param>
116 /// <returns></returns>
117 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
118 [EditorBrowsable(EditorBrowsableState.Never)]
119 public bool Say(string sentence, bool discardable)
121 IntPtr callbackIntPtr = IntPtr.Zero;
122 if (sayFinishedEventHandler != null)
124 callback = SayFinishedEventCallback;
125 callbackIntPtr = Marshal.GetFunctionPointerForDelegate<Delegate>(callback);
127 bool ret = Interop.Accessibility.Say(View.getCPtr(dummy), sentence, discardable, callbackIntPtr);
128 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
133 /// To make Say be paused or resumed
135 /// <param name="pause">true to be paused, false to be resumed</param>
136 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
137 [EditorBrowsable(EditorBrowsableState.Never)]
138 public void PauseResume(bool pause)
140 Interop.Accessibility.PauseResume(View.getCPtr(dummy), pause);
141 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
145 /// Cancels anything screen-reader is reading / has queued to read
147 /// <param name="alsoNonDiscardable">whether to cancel non-discardable readings as well</param>
148 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
149 [EditorBrowsable(EditorBrowsableState.Never)]
150 public void StopReading(bool alsoNonDiscardable)
152 Interop.Accessibility.StopReading(View.getCPtr(dummy), alsoNonDiscardable);
153 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
157 /// Suppress reading of screen-reader
159 /// <param name="suppress">whether to suppress reading of screen-reader</param>
160 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
161 [EditorBrowsable(EditorBrowsableState.Never)]
162 public bool SuppressScreenReader(bool suppress)
164 bool ret = Interop.Accessibility.SuppressScreenReader(View.getCPtr(dummy), suppress);
165 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
170 /// Re-enables auto-initialization of AT-SPI bridge
173 /// Normal applications do not have to call this function. The AT-SPI bridge is initialized on demand.
175 [EditorBrowsable(EditorBrowsableState.Never)]
176 public static void BridgeEnableAutoInit()
178 Interop.Accessibility.BridgeEnableAutoInit();
179 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
183 /// Blocks auto-initialization of AT-SPI bridge
186 /// Use this only if your application starts before DBus does, and call it early in Main().
187 /// When DBus is ready, call BridgeEnableAutoInit().
189 [EditorBrowsable(EditorBrowsableState.Never)]
190 public static void BridgeDisableAutoInit()
192 Interop.Accessibility.BridgeDisableAutoInit();
193 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
197 /// Get View that is used to highlight widget.
199 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
200 [EditorBrowsable(EditorBrowsableState.Never)]
201 public View GetHighlightFrameView()
203 var ptr = Interop.ControlDevel.DaliAccessibilityAccessibleGetHighlightActor();
204 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
205 if (ptr == IntPtr.Zero)
207 return new View(ptr, true);
211 /// Set view that will be used to highlight widget.
213 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
214 [EditorBrowsable(EditorBrowsableState.Never)]
215 public void SetHighlightFrameView(View view)
217 Interop.ControlDevel.DaliAccessibilityAccessibleSetHighlightActor(View.getCPtr(view));
218 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
222 /// Get highligted View.
224 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
225 [EditorBrowsable(EditorBrowsableState.Never)]
226 public View GetCurrentlyHighlightedView()
228 var ptr = Interop.ControlDevel.DaliAccessibilityAccessibleGetCurrentlyHighlightedActor();
229 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
230 if (ptr == IntPtr.Zero)
232 return new View(ptr, true);
238 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
239 [EditorBrowsable(EditorBrowsableState.Never)]
240 public bool ClearCurrentlyHighlightedView()
242 using (View view = GetCurrentlyHighlightedView())
244 return view?.ClearAccessibilityHighlight() ?? false;
250 #region Event, Enum, Struct, ETC
252 /// Enum of Say finished event argument status
254 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
255 [EditorBrowsable(EditorBrowsableState.Never)]
256 public enum SayFinishedState
261 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
262 [EditorBrowsable(EditorBrowsableState.Never)]
267 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
268 [EditorBrowsable(EditorBrowsableState.Never)]
273 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
274 [EditorBrowsable(EditorBrowsableState.Never)]
279 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
280 [EditorBrowsable(EditorBrowsableState.Never)]
285 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
286 [EditorBrowsable(EditorBrowsableState.Never)]
291 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
292 [EditorBrowsable(EditorBrowsableState.Never)]
297 /// When Say is finished, this event is triggered
299 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
300 [EditorBrowsable(EditorBrowsableState.Never)]
301 public event EventHandler<SayFinishedEventArgs> SayFinished
303 add => sayFinishedEventHandler += value;
304 remove => sayFinishedEventHandler -= value;
308 /// Triggered whenever the value of IsEnabled would change from false to true
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 Enabled;
315 /// Triggered whenever the value of IsEnabled would change from true to false
317 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
318 [EditorBrowsable(EditorBrowsableState.Never)]
319 public static event EventHandler Disabled;
321 #endregion Event, Enum, Struct, ETC
325 internal void PauseResume(View target, bool pause)
327 Interop.Accessibility.PauseResume(View.getCPtr(target), pause);
328 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
331 internal bool Say(View target, string sentence, bool discardable)
333 IntPtr callbackIntPtr = IntPtr.Zero;
334 if (sayFinishedEventHandler != null)
336 callback = SayFinishedEventCallback;
337 callbackIntPtr = Marshal.GetFunctionPointerForDelegate<Delegate>(callback);
339 bool ret = Interop.Accessibility.Say(View.getCPtr(target), sentence, discardable, callbackIntPtr);
340 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
347 private static readonly Accessibility accessibility = new Accessibility();
349 private event EventHandler<SayFinishedEventArgs> sayFinishedEventHandler;
351 [UnmanagedFunctionPointer(CallingConvention.StdCall)]
352 private delegate void SayFinishedEventCallbackType(int result);
354 private SayFinishedEventCallbackType callback = null;
356 private static Interop.Accessibility.EnabledDisabledSignalHandler enabledSignalHandler = null;
358 private static Interop.Accessibility.EnabledDisabledSignalHandler disabledSignalHandler = null;
360 private void SayFinishedEventCallback(int result)
362 NUILog.Debug($"sayFinishedEventCallback(res={result}) called!");
363 sayFinishedEventHandler?.Invoke(this, new SayFinishedEventArgs(result));
372 /// Say Finished event arguments
374 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
375 [EditorBrowsable(EditorBrowsableState.Never)]
376 public class SayFinishedEventArgs : EventArgs
379 /// The state of Say finished
381 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
382 [EditorBrowsable(EditorBrowsableState.Never)]
383 public Accessibility.SayFinishedState State
389 internal SayFinishedEventArgs(int result)
391 State = (Accessibility.SayFinishedState)(result);
392 NUILog.Debug($"SayFinishedEventArgs Constructor! State={State}");