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