2 * Copyright (c) 2022 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 #include "nui-view-accessible.h"
22 #include <dali/integration-api/debug.h>
25 #include "control-devel-wrap.h"
28 using namespace Dali::Toolkit;
30 using Interface = Accessibility::AtspiInterface;
34 void GetAttributesCallback(const char* key, const char* value, Accessibility::Attributes* attributes)
36 attributes->insert_or_assign(key, value);
39 using GetAttributesCallbackType = decltype(&GetAttributesCallback);
41 } // unnamed namespace
43 // Keep this structure layout binary compatible with the respective C# structure!
44 struct NUIViewAccessible::AccessibilityDelegate
46 AccessibilityDelegate() = delete;
49 char* (*getName) (RefObject*); // 1
50 char* (*getDescription) (RefObject*); // 2
51 bool (*doAction) (RefObject*, const char*); // 3
52 std::uint64_t (*calculateStates) (RefObject*, std::uint64_t); // 4
53 int (*getActionCount) (RefObject*); // 5
54 char* (*getActionName) (RefObject*, int); // 6
55 std::uint32_t (*getInterfaces) (RefObject*); // 7
56 double (*getMinimum) (RefObject*); // 8
57 double (*getCurrent) (RefObject*); // 9
58 double (*getMaximum) (RefObject*); // 10
59 bool (*setCurrent) (RefObject*, double); // 11
60 double (*getMinimumIncrement) (RefObject*); // 12
61 bool (*isScrollable) (RefObject*); // 13
62 char* (*getText) (RefObject*, int, int); // 14
63 int (*getCharacterCount) (RefObject*); // 15
64 int (*getCursorOffset) (RefObject*); // 16
65 bool (*setCursorOffset) (RefObject*, int); // 17
66 Accessibility::Range* (*getTextAtOffset) (RefObject*, int, int); // 18
67 Accessibility::Range* (*getRangeOfSelection) (RefObject*, int); // 19
68 bool (*removeSelection) (RefObject*, int); // 20
69 bool (*setRangeOfSelection) (RefObject*, int, int, int); // 21
70 bool (*copyText) (RefObject*, int, int); // 22
71 bool (*cutText) (RefObject*, int, int); // 23
72 bool (*insertText) (RefObject*, int, const char*); // 24
73 bool (*setTextContents) (RefObject*, const char*); // 25
74 bool (*deleteText) (RefObject*, int, int); // 26
75 bool (*scrollToChild) (RefObject*, Actor*); // 27
76 int (*getSelectedChildrenCount)(RefObject*); // 28
77 Actor* (*getSelectedChild) (RefObject*, int); // 29
78 bool (*selectChild) (RefObject*, int); // 30
79 bool (*deselectSelectedChild) (RefObject*, int); // 31
80 bool (*isChildSelected) (RefObject*, int); // 32
81 bool (*selectAll) (RefObject*); // 33
82 bool (*clearSelection) (RefObject*); // 34
83 bool (*deselectChild) (RefObject*, int); // 35
84 Rect<int>* (*getRangeExtents) (RefObject*, int, int, int); // 36
85 void (*getAttributes) (RefObject*, GetAttributesCallbackType, Accessibility::Attributes*); // 37
89 NUIViewAccessible::NUIViewAccessible(Actor actor)
90 : ControlAccessible(actor)
92 DALI_ASSERT_DEBUG(mTable);
95 void NUIViewAccessible::SetAccessibilityDelegate(const AccessibilityDelegate* accessibilityDelegate)
99 DALI_LOG_ERROR("Overwriting global AccessibilityDelegate");
102 mTable = accessibilityDelegate;
105 std::string NUIViewAccessible::StealString(char* str)
119 T NUIViewAccessible::StealObject(T* obj)
125 ret = std::move(*obj);
132 template<Interface I, typename R, typename... Args>
133 R NUIViewAccessible::CallMethod(R (*method)(RefObject*, Args...), Args... args) const
135 DALI_ASSERT_DEBUG(method);
136 DALI_ASSERT_ALWAYS(GetInterfaces()[I]);
138 return method(Self().GetObjectPtr(), args...);
142 // Standard interfaces (Accessible, Action, Component)
145 std::string NUIViewAccessible::GetNameRaw() const
147 char* name = CallMethod<Interface::ACCESSIBLE>(mTable->getName);
149 return StealString(name);
152 std::string NUIViewAccessible::GetDescriptionRaw() const
154 char* description = CallMethod<Interface::ACCESSIBLE>(mTable->getDescription);
156 return StealString(description);
159 bool NUIViewAccessible::GrabHighlight()
161 bool ret = ControlAccessible::GrabHighlight();
165 // Note: Currently (2021-03-26), size negotiation between the default highlight frame
166 // and NUI Components is known to be broken (and possibly in other cases, too). Please
167 // remove this for GrabHighlight() when it is fixed.
168 auto size = Self().GetProperty<Vector2>(Actor::Property::SIZE);
169 mCurrentHighlightActor.GetHandle().SetProperty(Actor::Property::SIZE, size);
175 std::string NUIViewAccessible::GetActionName(std::size_t index) const
177 char* name = CallMethod<Interface::ACTION>(mTable->getActionName, static_cast<int>(index));
179 return StealString(name);
182 std::size_t NUIViewAccessible::GetActionCount() const
184 int count = CallMethod<Interface::ACTION>(mTable->getActionCount);
186 return static_cast<std::size_t>(count);
189 bool NUIViewAccessible::DoAction(std::size_t index)
191 return DoAction(GetActionName(index));
194 bool NUIViewAccessible::DoAction(const std::string& name)
196 return CallMethod<Interface::ACTION>(mTable->doAction, name.c_str());
199 Accessibility::States NUIViewAccessible::CalculateStates()
201 std::uint64_t states = ControlAccessible::CalculateStates().GetRawData64();
203 states = CallMethod<Interface::ACCESSIBLE>(mTable->calculateStates, states);
205 return Accessibility::States{states};
208 Accessibility::Attributes NUIViewAccessible::GetAttributes() const
210 auto attributes = ControlAccessible::GetAttributes();
212 CallMethod<Interface::ACCESSIBLE>(mTable->getAttributes, &GetAttributesCallback, &attributes);
217 Property::Index NUIViewAccessible::GetNamePropertyIndex()
219 return Property::INVALID_INDEX;
222 Property::Index NUIViewAccessible::GetDescriptionPropertyIndex()
224 return Property::INVALID_INDEX;
227 bool NUIViewAccessible::IsScrollable() const
229 return CallMethod<Interface::COMPONENT>(mTable->isScrollable);
232 bool NUIViewAccessible::ScrollToChild(Actor child)
234 return CallMethod<Interface::ACCESSIBLE>(mTable->scrollToChild, new Actor(child));
237 Accessibility::AtspiInterfaces NUIViewAccessible::DoGetInterfaces() const
239 using Interfaces = Accessibility::AtspiInterfaces;
241 Interfaces baseInterfaces;
242 Interfaces extraInterfaces;
244 // These are always implemented
245 baseInterfaces[Interface::ACCESSIBLE] = true;
246 baseInterfaces[Interface::ACTION] = true;
247 baseInterfaces[Interface::COLLECTION] = true;
248 baseInterfaces[Interface::COMPONENT] = true;
250 // We cannot use CallMethod() here as that would cause recursion.
251 // Note that the result will be cached and subsequent calls to GetInterfaces()
252 // will not involve calling this virtual method or jumping into C# code.
253 extraInterfaces = Interfaces{mTable->getInterfaces(Self().GetObjectPtr())};
255 return baseInterfaces | extraInterfaces;
262 double NUIViewAccessible::GetMinimum() const
264 return CallMethod<Interface::VALUE>(mTable->getMinimum);
267 double NUIViewAccessible::GetCurrent() const
269 return CallMethod<Interface::VALUE>(mTable->getCurrent);
272 double NUIViewAccessible::GetMaximum() const
274 return CallMethod<Interface::VALUE>(mTable->getMaximum);
277 bool NUIViewAccessible::SetCurrent(double value)
279 return CallMethod<Interface::VALUE>(mTable->setCurrent, value);
282 double NUIViewAccessible::GetMinimumIncrement() const
284 return CallMethod<Interface::VALUE>(mTable->getMinimumIncrement);
291 std::string NUIViewAccessible::GetText(std::size_t startOffset, std::size_t endOffset) const
293 char* text = CallMethod<Interface::TEXT>(mTable->getText, static_cast<int>(startOffset), static_cast<int>(endOffset));
295 return StealString(text);
298 std::size_t NUIViewAccessible::GetCharacterCount() const
300 int count = CallMethod<Interface::TEXT>(mTable->getCharacterCount);
302 return static_cast<std::size_t>(count);
305 std::size_t NUIViewAccessible::GetCursorOffset() const
307 int offset = CallMethod<Interface::TEXT>(mTable->getCursorOffset);
309 return static_cast<std::size_t>(offset);
312 bool NUIViewAccessible::SetCursorOffset(std::size_t offset)
314 return CallMethod<Interface::TEXT>(mTable->setCursorOffset, static_cast<int>(offset));
317 Accessibility::Range NUIViewAccessible::GetTextAtOffset(std::size_t offset, Accessibility::TextBoundary boundary) const
319 Accessibility::Range* range = CallMethod<Interface::TEXT>(mTable->getTextAtOffset, static_cast<int>(offset), static_cast<int>(boundary));
321 return StealObject(range);
324 Accessibility::Range NUIViewAccessible::GetRangeOfSelection(std::size_t selectionIndex) const
326 Accessibility::Range* range = CallMethod<Interface::TEXT>(mTable->getRangeOfSelection, static_cast<int>(selectionIndex));
328 return StealObject(range);
331 bool NUIViewAccessible::RemoveSelection(std::size_t selectionIndex)
333 return CallMethod<Interface::TEXT>(mTable->removeSelection, static_cast<int>(selectionIndex));
336 bool NUIViewAccessible::SetRangeOfSelection(std::size_t selectionIndex, std::size_t startOffset, std::size_t endOffset)
338 return CallMethod<Interface::TEXT>(mTable->setRangeOfSelection, static_cast<int>(selectionIndex), static_cast<int>(startOffset), static_cast<int>(endOffset));
341 Rect<> NUIViewAccessible::GetRangeExtents(std::size_t startOffset, std::size_t endOffset, Accessibility::CoordinateType type)
343 auto rectPtr = CallMethod<Interface::TEXT>(mTable->getRangeExtents, static_cast<int>(startOffset), static_cast<int>(endOffset), static_cast<int>(type));
344 Rect<int> rect = StealObject(rectPtr);
346 return {(float)rect.x, (float)rect.y, (float)rect.width, (float)rect.height};
350 // EditableText interface
353 bool NUIViewAccessible::CopyText(std::size_t startPosition, std::size_t endPosition)
355 return CallMethod<Interface::EDITABLE_TEXT>(mTable->copyText, static_cast<int>(startPosition), static_cast<int>(endPosition));
358 bool NUIViewAccessible::CutText(std::size_t startPosition, std::size_t endPosition)
360 return CallMethod<Interface::EDITABLE_TEXT>(mTable->cutText, static_cast<int>(startPosition), static_cast<int>(endPosition));
363 bool NUIViewAccessible::InsertText(std::size_t startPosition, std::string text)
365 return CallMethod<Interface::EDITABLE_TEXT>(mTable->insertText, static_cast<int>(startPosition), text.c_str());
368 bool NUIViewAccessible::SetTextContents(std::string newContents)
370 return CallMethod<Interface::EDITABLE_TEXT>(mTable->setTextContents, newContents.c_str());
373 bool NUIViewAccessible::DeleteText(std::size_t startPosition, std::size_t endPosition)
375 return CallMethod<Interface::EDITABLE_TEXT>(mTable->deleteText, static_cast<int>(startPosition), static_cast<int>(endPosition));
379 // Selection interface
382 int NUIViewAccessible::GetSelectedChildrenCount() const
384 return CallMethod<Interface::SELECTION>(mTable->getSelectedChildrenCount);
387 Accessibility::Accessible* NUIViewAccessible::GetSelectedChild(int selectedChildIndex)
389 Actor* actor = CallMethod<Interface::SELECTION>(mTable->getSelectedChild, selectedChildIndex);
391 return actor ? Accessibility::Accessible::Get(*actor) : nullptr;
394 bool NUIViewAccessible::SelectChild(int childIndex)
396 return CallMethod<Interface::SELECTION>(mTable->selectChild, childIndex);
399 bool NUIViewAccessible::DeselectSelectedChild(int selectedChildIndex)
401 return CallMethod<Interface::SELECTION>(mTable->deselectSelectedChild, selectedChildIndex);
404 bool NUIViewAccessible::IsChildSelected(int childIndex) const
406 return CallMethod<Interface::SELECTION>(mTable->isChildSelected, childIndex);
409 bool NUIViewAccessible::SelectAll()
411 return CallMethod<Interface::SELECTION>(mTable->selectAll);
414 bool NUIViewAccessible::ClearSelection()
416 return CallMethod<Interface::SELECTION>(mTable->clearSelection);
419 bool NUIViewAccessible::DeselectChild(int childIndex)
421 return CallMethod<Interface::SELECTION>(mTable->deselectChild, childIndex);
428 SWIGEXPORT char* SWIGSTDCALL CSharp_Dali_Accessibility_DuplicateString(const char* arg)
433 SWIGEXPORT void SWIGSTDCALL CSharp_Dali_Accessibility_SetAccessibilityDelegate(const void* arg1_accessibilityDelegate, uint32_t arg2_accessibilityDelegateSize)
435 GUARD_ON_NULL_RET(arg1_accessibilityDelegate);
437 const auto* accessibilityDelegate = static_cast<const NUIViewAccessible::AccessibilityDelegate*>(arg1_accessibilityDelegate);
438 auto accessibilityDelegateSize = static_cast<std::size_t>(arg2_accessibilityDelegateSize);
441 if(accessibilityDelegateSize != sizeof(*accessibilityDelegate))
443 DALI_LOG_ERROR("SetAccessibilityDelegate error: Marshal.SizeOf<AccessibilityDelegate>()[%zu] != sizeof(AccessibilityDelegate)[%zu]\n", accessibilityDelegateSize, sizeof(*accessibilityDelegate));
444 throw std::runtime_error("SetAccessibilityDelegate error: Marshal.SizeOf<AccessibilityDelegate>() != sizeof(AccessibilityDelegate)");
447 NUIViewAccessible::SetAccessibilityDelegate(accessibilityDelegate);
448 Accessibility::Bridge::GetCurrentBridge()->SetToolkitName("nui(dali)");