/*
* Copyright(c) 2021 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using Tizen.NUI.BaseComponents;
using System.Diagnostics.CodeAnalysis;
namespace Tizen.NUI.Accessibility
{
///
/// Accessibility provides Dali-ATSPI interface which has functionality of Screen-Reader and general accessibility
///
// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
[SuppressMessage("Microsoft.Design", "CA1724: Type names should not match namespaces")]
[SuppressMessage("Microsoft.Design", "CA1001:Types that own disposable fields should be disposable", Justification = "This is a singleton class and is not disposed")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static class Accessibility
{
#region Constructor
[SuppressMessage("Microsoft.Performance", "CA1810: Initialize reference type static fields inline", Justification = "Need to call native code")]
static Accessibility()
{
enabledSignalHandler = () =>
{
Enabled?.Invoke(typeof(Accessibility), EventArgs.Empty);
};
disabledSignalHandler = () =>
{
Disabled?.Invoke(typeof(Accessibility), EventArgs.Empty);
};
screenReaderEnabledSignalHandler = () =>
{
ScreenReaderEnabled?.Invoke(typeof(Accessibility), EventArgs.Empty);
};
screenReaderDisabledSignalHandler = () =>
{
ScreenReaderDisabled?.Invoke(typeof(Accessibility), EventArgs.Empty);
};
Interop.Accessibility.RegisterEnabledDisabledSignalHandler(enabledSignalHandler, disabledSignalHandler);
Interop.Accessibility.RegisterScreenReaderEnabledDisabledSignalHandler(screenReaderEnabledSignalHandler, screenReaderDisabledSignalHandler);
}
#endregion Constructor
#region Property
///
/// Flag to check whether the state of Accessibility is enabled or not.
///
///
/// Getter returns true if Accessibility is enabled, false otherwise.
///
/// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
[EditorBrowsable(EditorBrowsableState.Never)]
public static bool IsEnabled
{
get
{
return (bool)Interop.Accessibility.IsEnabled();
}
}
///
/// Flag to check whether the state of Screen Reader is enabled or not.
///
///
/// Getter returns true if Screen Reader is enabled, false otherwise.
///
/// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
[EditorBrowsable(EditorBrowsableState.Never)]
public static bool IsScreenReaderEnabled
{
get
{
return (bool)Interop.Accessibility.IsScreenReaderEnabled();
}
}
#endregion Property
#region Method
///
/// Start to speak
///
/// Content to be spoken
/// true to be stopped and discarded when other Say is triggered
///
// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
[EditorBrowsable(EditorBrowsableState.Never)]
public static bool Say(string sentence, bool discardable)
{
bool ret = Interop.Accessibility.Say(sentence, discardable, Marshal.GetFunctionPointerForDelegate(callback));
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
return ret;
}
///
/// To make Say be paused or resumed
///
/// true to be paused, false to be resumed
// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
[EditorBrowsable(EditorBrowsableState.Never)]
public static void PauseResume(bool pause)
{
Interop.Accessibility.PauseResume(pause);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Cancels anything screen-reader is reading / has queued to read
///
/// whether to cancel non-discardable readings as well
// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
[EditorBrowsable(EditorBrowsableState.Never)]
public static void StopReading(bool alsoNonDiscardable)
{
Interop.Accessibility.StopReading(alsoNonDiscardable);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Suppress reading of screen-reader
///
/// whether to suppress reading of screen-reader
// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
[EditorBrowsable(EditorBrowsableState.Never)]
public static bool SuppressScreenReader(bool suppress)
{
bool ret = Interop.Accessibility.SuppressScreenReader(suppress);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
return ret;
}
///
/// Re-enables auto-initialization of AT-SPI bridge
///
///
/// Normal applications do not have to call this function. The AT-SPI bridge is initialized on demand.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public static void BridgeEnableAutoInit()
{
Interop.Accessibility.BridgeEnableAutoInit();
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Blocks auto-initialization of AT-SPI bridge
///
///
/// Use this only if your application starts before DBus does, and call it early in Main().
/// When DBus is ready, call BridgeEnableAutoInit().
///
[EditorBrowsable(EditorBrowsableState.Never)]
public static void BridgeDisableAutoInit()
{
Interop.Accessibility.BridgeDisableAutoInit();
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Get View that is used to highlight widget.
///
// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
[EditorBrowsable(EditorBrowsableState.Never)]
public static View GetHighlightFrameView()
{
var ptr = Interop.ControlDevel.DaliAccessibilityAccessibleGetHighlightActor();
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
if (ptr == IntPtr.Zero)
return null;
return new View(ptr, true);
}
///
/// Set view that will be used to highlight widget.
///
// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
[EditorBrowsable(EditorBrowsableState.Never)]
public static void SetHighlightFrameView(View view)
{
Interop.ControlDevel.DaliAccessibilityAccessibleSetHighlightActor(View.getCPtr(view));
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Get highligted View.
///
// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
[EditorBrowsable(EditorBrowsableState.Never)]
public static View GetCurrentlyHighlightedView()
{
var ptr = Interop.ControlDevel.DaliAccessibilityAccessibleGetCurrentlyHighlightedActor();
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
return dummyHandle.GetInstanceSafely(ptr);
}
///
/// Clear highlight.
///
// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
[EditorBrowsable(EditorBrowsableState.Never)]
public static bool ClearCurrentlyHighlightedView()
{
var view = GetCurrentlyHighlightedView();
return view?.ClearAccessibilityHighlight() ?? false;
}
#endregion Method
#region Event, Enum, Struct, ETC
///
/// Enum of Say finished event argument status
///
// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
[EditorBrowsable(EditorBrowsableState.Never)]
public enum SayFinishedState
{
///
/// Invalid
///
// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
[EditorBrowsable(EditorBrowsableState.Never)]
Invalid = -1,
///
/// Cancelled
///
// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
[EditorBrowsable(EditorBrowsableState.Never)]
Cancelled = 1,
///
/// Stopped
///
// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
[EditorBrowsable(EditorBrowsableState.Never)]
Stopped = 2,
///
/// Skipped
///
// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
[EditorBrowsable(EditorBrowsableState.Never)]
Skipped = 3,
///
/// Paused
///
// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
[EditorBrowsable(EditorBrowsableState.Never)]
Paused = 4,
///
/// Resumed
///
// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
[EditorBrowsable(EditorBrowsableState.Never)]
Resumed = 5
}
///
/// When Say is finished, this event is triggered
///
// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
[EditorBrowsable(EditorBrowsableState.Never)]
public static event EventHandler SayFinished;
///
/// Triggered whenever the value of IsEnabled would change from false to true
///
// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
[EditorBrowsable(EditorBrowsableState.Never)]
public static event EventHandler Enabled;
///
/// Triggered whenever the value of IsEnabled would change from true to false
///
// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
[EditorBrowsable(EditorBrowsableState.Never)]
public static event EventHandler Disabled;
///
/// Triggered whenever the value of IsScreenReaderEnabled would change from false to true
///
// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
[EditorBrowsable(EditorBrowsableState.Never)]
public static event EventHandler ScreenReaderEnabled;
///
/// Triggered whenever the value of IsScreenReaderEnabled would change from true to false
///
// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
[EditorBrowsable(EditorBrowsableState.Never)]
public static event EventHandler ScreenReaderDisabled;
#endregion Event, Enum, Struct, ETC
#region Private
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void SayFinishedEventCallbackType(int result);
private static SayFinishedEventCallbackType callback = SayFinishedEventCallback;
private static Interop.Accessibility.EnabledDisabledSignalHandler enabledSignalHandler = null;
private static Interop.Accessibility.EnabledDisabledSignalHandler disabledSignalHandler = null;
private static Interop.Accessibility.EnabledDisabledSignalHandler screenReaderEnabledSignalHandler = null;
private static Interop.Accessibility.EnabledDisabledSignalHandler screenReaderDisabledSignalHandler = null;
private static void SayFinishedEventCallback(int result)
{
NUILog.Debug($"sayFinishedEventCallback(res={result}) called!");
SayFinished?.Invoke(typeof(Accessibility), new SayFinishedEventArgs(result));
}
private static BaseHandle dummyHandle = new BaseHandle();
#endregion Private
}
///
/// Say Finished event arguments
///
// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
[EditorBrowsable(EditorBrowsableState.Never)]
public class SayFinishedEventArgs : EventArgs
{
///
/// The state of Say finished
///
// This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
[EditorBrowsable(EditorBrowsableState.Never)]
public Accessibility.SayFinishedState State
{
private set;
get;
}
internal SayFinishedEventArgs(int result)
{
State = (Accessibility.SayFinishedState)(result);
NUILog.Debug($"SayFinishedEventArgs Constructor! State={State}");
}
}
}