Merge remote-tracking branch 'origin/master' into tizen
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / BaseComponents / ViewAccessibilityWrappers.cs
1 /*
2  * Copyright(c) 2022 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.Runtime.InteropServices;
20
21 namespace Tizen.NUI.BaseComponents
22 {
23     public partial class View
24     {
25         private static AccessibilityStates AccessibilityInitialStates = new AccessibilityStates();
26
27         // To be removed when native C# AT-SPI interfaces are implemented.
28         private uint? AtspiInterfaceFlags = null;
29
30         private static void RegisterAccessibilityDelegate()
31         {
32             InitializeAccessibilityDelegateAccessibleInterface();
33             InitializeAccessibilityDelegateActionInterface();
34             InitializeAccessibilityDelegateComponentInterface();
35             InitializeAccessibilityDelegateEditableTextInterface();
36             InitializeAccessibilityDelegateSelectionInterface();
37             InitializeAccessibilityDelegateTextInterface();
38             InitializeAccessibilityDelegateValueInterface();
39             InitializeAccessibilityDelegateTizenExtensions();
40
41             var ad   = Interop.ControlDevel.AccessibilityDelegate.Instance;
42             var size = Marshal.SizeOf<Interop.ControlDevel.AccessibilityDelegate>();
43             var ptr  = Marshal.AllocHGlobal(size);
44
45             Marshal.StructureToPtr(ad, ptr, false);
46             Interop.ControlDevel.DaliAccessibilitySetAccessibilityDelegate(ptr, size);
47         }
48
49         private static View GetViewFromRefObject(IntPtr refObjectPtr)
50         {
51             return Registry.GetManagedBaseHandleFromRefObject(refObjectPtr) as View;
52         }
53
54         private static IntPtr DuplicateString(string value)
55         {
56             return Interop.ControlDevel.DaliAccessibilityDuplicateString(value ?? "");
57         }
58
59         private static IntPtr DuplicateAccessibilityRange(AccessibilityRange range)
60         {
61             return Interop.ControlDevel.DaliAccessibilityNewRange(range.StartOffset, range.EndOffset, range.Content);
62         }
63
64         //
65         // Accessible interface
66         //
67
68         private static void InitializeAccessibilityDelegateAccessibleInterface()
69         {
70             var ad = Interop.ControlDevel.AccessibilityDelegate.Instance;
71
72             ad.CalculateStates = AccessibilityCalculateStatesWrapper;
73             ad.GetDescription  = AccessibilityGetDescriptionWrapper;
74             ad.GetInterfaces   = AccessibilityGetInterfaces; // Not a wrapper, entirely private implementation
75             ad.GetName         = AccessibilityGetNameWrapper;
76         }
77
78         private static ulong AccessibilityCalculateStatesWrapper(IntPtr self, ulong initialStates)
79         {
80             View view = GetViewFromRefObject(self);
81             ulong bitMask = 0UL;
82
83             lock (AccessibilityInitialStates)
84             {
85                 AccessibilityInitialStates.BitMask = initialStates;
86                 bitMask = view.AccessibilityCalculateStates().BitMask;
87                 AccessibilityInitialStates.BitMask = 0UL;
88             }
89
90             return bitMask;
91         }
92
93         private static IntPtr AccessibilityGetDescriptionWrapper(IntPtr self)
94         {
95             string description = GetViewFromRefObject(self).AccessibilityGetDescription();
96
97             return DuplicateString(description);
98         }
99
100         private static uint AccessibilityGetInterfaces(IntPtr self)
101         {
102             // Currently a maximum of one AccessibilityInterface per View is supported.
103             // This will change when we implement AT-SPI interfaces as native C# interfaces.
104             // Then, this method will look like:
105             //
106             // uint flags = 0U;
107             // if (view is IAtspiSelection) flags |= (1U << (int)AccessibilityInterface.Selection)
108             // if (view is IAtspiValue) flags |= (1U << (int)AccessibilityInterface.Value)
109             // ...
110             // return flags;
111
112             View view = GetViewFromRefObject(self);
113
114             if (!view.AtspiInterfaceFlags.HasValue)
115             {
116                 NUILog.Error("AtspiInterfaceFlags are not set!");
117                 return 0U;
118             }
119
120             return view.AtspiInterfaceFlags.Value;
121         }
122
123         private static IntPtr AccessibilityGetNameWrapper(IntPtr self)
124         {
125             string name = GetViewFromRefObject(self).AccessibilityGetName();
126
127             return DuplicateString(name);
128         }
129
130         //
131         // Action interface
132         //
133
134         private static void InitializeAccessibilityDelegateActionInterface()
135         {
136             var ad = Interop.ControlDevel.AccessibilityDelegate.Instance;
137
138             ad.DoAction       = AccessibilityDoActionWrapper;
139             ad.GetActionCount = AccessibilityGetActionCountWrapper;
140             ad.GetActionName  = AccessibilityGetActionNameWrapper;
141         }
142
143         private static bool AccessibilityDoActionWrapper(IntPtr self, IntPtr name)
144         {
145             return GetViewFromRefObject(self).AccessibilityDoAction(Marshal.PtrToStringAnsi(name));
146         }
147
148         private static int AccessibilityGetActionCountWrapper(IntPtr self)
149         {
150             return GetViewFromRefObject(self).AccessibilityGetActionCount();
151         }
152
153         private static IntPtr AccessibilityGetActionNameWrapper(IntPtr self, int index)
154         {
155             string name = GetViewFromRefObject(self).AccessibilityGetActionName(index);
156
157             return DuplicateString(name);
158         }
159
160         //
161         // Component interface
162         //
163
164         private static void InitializeAccessibilityDelegateComponentInterface()
165         {
166             var ad = Interop.ControlDevel.AccessibilityDelegate.Instance;
167
168             ad.IsScrollable = AccessibilityIsScrollableWrapper;
169         }
170
171         private static bool AccessibilityIsScrollableWrapper(IntPtr self)
172         {
173             return GetViewFromRefObject(self).AccessibilityIsScrollable();
174         }
175
176         //
177         // EditableText interface
178         //
179
180         private static void InitializeAccessibilityDelegateEditableTextInterface()
181         {
182             var ad = Interop.ControlDevel.AccessibilityDelegate.Instance;
183
184             ad.CopyText        = AccessibilityCopyTextWrapper;
185             ad.CutText         = AccessibilityCutTextWrapper;
186             ad.DeleteText      = AccessibilityDeleteTextWrapper;
187             ad.InsertText      = AccessibilityInsertTextWrapper;
188             ad.SetTextContents = AccessibilitySetTextContentsWrapper;
189         }
190
191         private static bool AccessibilityCopyTextWrapper(IntPtr self, int startPosition, int endPosition)
192         {
193             return GetViewFromRefObject(self).AccessibilityCopyText(startPosition, endPosition);
194         }
195
196         private static bool AccessibilityCutTextWrapper(IntPtr self, int startPosition, int endPosition)
197         {
198             return GetViewFromRefObject(self).AccessibilityCutText(startPosition, endPosition);
199         }
200
201         private static bool AccessibilityDeleteTextWrapper(IntPtr self, int startPosition, int endPosition)
202         {
203             return GetViewFromRefObject(self).AccessibilityDeleteText(startPosition, endPosition);
204         }
205
206         private static bool AccessibilityInsertTextWrapper(IntPtr self, int startPosition, IntPtr text)
207         {
208             return GetViewFromRefObject(self).AccessibilityInsertText(startPosition, Marshal.PtrToStringAnsi(text));
209         }
210
211         private static bool AccessibilitySetTextContentsWrapper(IntPtr self, IntPtr newContents)
212         {
213             return GetViewFromRefObject(self).AccessibilitySetTextContents(Marshal.PtrToStringAnsi(newContents));
214         }
215
216         //
217         // Selection interface
218         //
219
220         private static void InitializeAccessibilityDelegateSelectionInterface()
221         {
222             var ad = Interop.ControlDevel.AccessibilityDelegate.Instance;
223
224             ad.ClearSelection           = AccessibilityClearSelectionWrapper;
225             ad.DeselectChild            = AccessibilityDeselectChildWrapper;
226             ad.DeselectSelectedChild    = AccessibilityDeselectSelectedChildWrapper;
227             ad.GetSelectedChild         = AccessibilityGetSelectedChildWrapper;
228             ad.GetSelectedChildrenCount = AccessibilityGetSelectedChildrenCountWrapper;
229             ad.IsChildSelected          = AccessibilityIsChildSelectedWrapper;
230             ad.SelectAll                = AccessibilitySelectAllWrapper;
231             ad.SelectChild              = AccessibilitySelectChildWrapper;
232         }
233
234         private static bool AccessibilityClearSelectionWrapper(IntPtr self)
235         {
236             return GetViewFromRefObject(self).AccessibilityClearSelection();
237         }
238
239         private static bool AccessibilityDeselectChildWrapper(IntPtr self, int childIndex)
240         {
241             return GetViewFromRefObject(self).AccessibilityDeselectChild(childIndex);
242         }
243
244         private static bool AccessibilityDeselectSelectedChildWrapper(IntPtr self, int selectedChildIndex)
245         {
246             return GetViewFromRefObject(self).AccessibilityDeselectSelectedChild(selectedChildIndex);
247         }
248
249         private static IntPtr AccessibilityGetSelectedChildWrapper(IntPtr self, int selectedChildIndex)
250         {
251             View child = GetViewFromRefObject(self).AccessibilityGetSelectedChild(selectedChildIndex);
252
253             return View.getCPtr(child).Handle;
254         }
255
256         private static int AccessibilityGetSelectedChildrenCountWrapper(IntPtr self)
257         {
258             return GetViewFromRefObject(self).AccessibilityGetSelectedChildrenCount();
259         }
260
261         private static bool AccessibilityIsChildSelectedWrapper(IntPtr self, int childIndex)
262         {
263             return GetViewFromRefObject(self).AccessibilityIsChildSelected(childIndex);
264         }
265
266         private static bool AccessibilitySelectAllWrapper(IntPtr self)
267         {
268             return GetViewFromRefObject(self).AccessibilitySelectAll();
269         }
270
271         private static bool AccessibilitySelectChildWrapper(IntPtr self, int childIndex)
272         {
273             return GetViewFromRefObject(self).AccessibilitySelectChild(childIndex);
274         }
275
276         //
277         // Text interface
278         //
279
280         private static void InitializeAccessibilityDelegateTextInterface()
281         {
282             var ad = Interop.ControlDevel.AccessibilityDelegate.Instance;
283
284             ad.GetCharacterCount = AccessibilityGetCharacterCountWrapper;
285             ad.GetCursorOffset   = AccessibilityGetCursorOffsetWrapper;
286             ad.GetSelection      = AccessibilityGetSelectionWrapper;
287             ad.GetText           = AccessibilityGetTextWrapper;
288             ad.GetTextAtOffset   = AccessibilityGetTextAtOffsetWrapper;
289             ad.RemoveSelection   = AccessibilityRemoveSelectionWrapper;
290             ad.SetCursorOffset   = AccessibilitySetCursorOffsetWrapper;
291             ad.SetSelection      = AccessibilitySetSelectionWrapper;
292         }
293
294         private static int AccessibilityGetCharacterCountWrapper(IntPtr self)
295         {
296             return GetViewFromRefObject(self).AccessibilityGetCharacterCount();
297         }
298
299         private static int AccessibilityGetCursorOffsetWrapper(IntPtr self)
300         {
301             return GetViewFromRefObject(self).AccessibilityGetCursorOffset();
302         }
303
304         private static IntPtr AccessibilityGetSelectionWrapper(IntPtr self, int selectionNumber)
305         {
306             AccessibilityRange range = GetViewFromRefObject(self).AccessibilityGetSelection(selectionNumber);
307
308             return DuplicateAccessibilityRange(range);
309         }
310
311         private static IntPtr AccessibilityGetTextWrapper(IntPtr self, int startOffset, int endOffset)
312         {
313             string text = GetViewFromRefObject(self).AccessibilityGetText(startOffset, endOffset);
314
315             return DuplicateString(text);
316         }
317
318         private static IntPtr AccessibilityGetTextAtOffsetWrapper(IntPtr self, int offset, int boundary)
319         {
320             AccessibilityRange range = GetViewFromRefObject(self).AccessibilityGetTextAtOffset(offset, (AccessibilityTextBoundary)boundary);
321
322             return DuplicateAccessibilityRange(range);
323         }
324
325         private static bool AccessibilityRemoveSelectionWrapper(IntPtr self, int selectionNumber)
326         {
327             return GetViewFromRefObject(self).AccessibilityRemoveSelection(selectionNumber);
328         }
329
330         private static bool AccessibilitySetCursorOffsetWrapper(IntPtr self, int offset)
331         {
332             return GetViewFromRefObject(self).AccessibilitySetCursorOffset(offset);
333         }
334
335         private static bool AccessibilitySetSelectionWrapper(IntPtr self, int selectionNumber, int startOffset, int endOffset)
336         {
337             return GetViewFromRefObject(self).AccessibilitySetSelection(selectionNumber, startOffset, endOffset);
338         }
339
340         //
341         // Value interface
342         //
343
344         private static void InitializeAccessibilityDelegateValueInterface()
345         {
346             var ad = Interop.ControlDevel.AccessibilityDelegate.Instance;
347
348             ad.GetCurrent          = AccessibilityGetCurrentWrapper;
349             ad.GetMaximum          = AccessibilityGetMaximumWrapper;
350             ad.GetMinimum          = AccessibilityGetMinimumWrapper;
351             ad.GetMinimumIncrement = AccessibilityGetMinimumIncrementWrapper;
352             ad.SetCurrent          = AccessibilitySetCurrentWrapper;
353         }
354
355         private static double AccessibilityGetCurrentWrapper(IntPtr self)
356         {
357             return GetViewFromRefObject(self).AccessibilityGetCurrent();
358         }
359
360         private static double AccessibilityGetMaximumWrapper(IntPtr self)
361         {
362             return GetViewFromRefObject(self).AccessibilityGetMaximum();
363         }
364
365         private static double AccessibilityGetMinimumWrapper(IntPtr self)
366         {
367             return GetViewFromRefObject(self).AccessibilityGetMinimum();
368         }
369
370         private static double AccessibilityGetMinimumIncrementWrapper(IntPtr self)
371         {
372             return GetViewFromRefObject(self).AccessibilityGetMinimumIncrement();
373         }
374
375         private static bool AccessibilitySetCurrentWrapper(IntPtr self, double value)
376         {
377             return GetViewFromRefObject(self).AccessibilitySetCurrent(value);
378         }
379
380         //
381         // Tizen extensions
382         //
383
384         private static void InitializeAccessibilityDelegateTizenExtensions()
385         {
386             var ad = Interop.ControlDevel.AccessibilityDelegate.Instance;
387
388             ad.ScrollToChild            = AccessibilityScrollToChildWrapper;
389             ad.ShouldReportZeroChildren = AccessibilityShouldReportZeroChildrenWrapper;
390         }
391
392         private static bool AccessibilityScrollToChildWrapper(IntPtr self, IntPtr child)
393         {
394             View view = GetViewFromRefObject(self);
395
396             return view.AccessibilityScrollToChild(view.GetInstanceSafely<View>(child));
397         }
398
399         private static bool AccessibilityShouldReportZeroChildrenWrapper(IntPtr self)
400         {
401             return GetViewFromRefObject(self).AccessibilityShouldReportZeroChildren();
402         }
403     }
404 }