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.
17 #include "control-devel_wrap.h"
19 #include <dali/devel-api/adaptor-framework/accessibility.h>
20 #include <dali/devel-api/adaptor-framework/accessibility-impl.h>
23 using namespace Dali::Toolkit::DevelControl;
27 // Keep this structure layout binary compatible with the respective C# structure!
28 struct AccessibilityDelegate
30 char *(*getName)(); // 1
31 char *(*getDescription)(); // 2
32 bool (*doAction)(const char *); // 3
33 Dali::Accessibility::States *(*calculateStates)(); // 4
34 int (*getActionCount)(); // 5
35 char *(*getActionName)(int); // 6
36 bool (*shouldReportZeroChildren)(); // 7
37 double (*getMinimum)(); // 8
38 double (*getCurrent)(); // 9
39 double (*getMaximum)(); // 10
40 bool (*setCurrent)(double); // 11
41 double (*getMinimumIncrement)(); // 12
42 bool (*isScrollable)(); // 13
43 char *(*getText)(int, int); // 14
44 int (*getCharacterCount)(); // 15
45 int (*getCaretOffset)(); // 16
46 bool (*setCaretOffset)(int); // 17
47 Dali::Accessibility::Range *(*getTextAtOffset)(int, int); // 18
48 Dali::Accessibility::Range *(*getSelection)(int); // 19
49 bool (*removeSelection)(int); // 20
50 bool (*setSelection)(int, int, int); // 21
51 bool (*copyText)(int, int); // 22
52 bool (*cutText)(int, int); // 23
55 inline std::string stealString(char *str)
69 inline T stealObject(T *obj)
82 struct AccessibleImpl_NUI : public AccessibleImpl
84 // Points to memory managed from the C# side
85 const AccessibilityDelegate *v;
87 AccessibleImpl_NUI() = delete;
88 AccessibleImpl_NUI(const AccessibleImpl_NUI &) = delete;
89 AccessibleImpl_NUI(AccessibleImpl_NUI &&) = delete;
91 AccessibleImpl_NUI& operator=(const AccessibleImpl_NUI &) = delete;
92 AccessibleImpl_NUI& operator=(AccessibleImpl_NUI &&) = delete;
94 AccessibleImpl_NUI(Dali::Actor actor, Dali::Accessibility::Role role, const AccessibilityDelegate *vtable)
95 : AccessibleImpl(actor, role, false), v{vtable} {}
97 std::string GetNameRaw() override
103 ret = stealString(v->getName());
109 std::string GetDescriptionRaw() override
113 if (v->getDescription)
115 ret = stealString(v->getDescription());
121 std::string GetActionName(std::size_t index) override
125 if (v->getActionName)
127 ret = stealString(v->getActionName(static_cast<int>(index)));
133 std::size_t GetActionCount() override
137 if (v->getActionCount)
139 ret = static_cast<std::size_t>(v->getActionCount());
145 bool DoAction(std::size_t index) override
147 return DoAction(GetActionName(index));
150 bool DoAction(const std::string &name) override
156 ret = v->doAction(name.data());
162 Dali::Accessibility::States CalculateStates() override
164 Dali::Accessibility::States ret{};
166 if (v->calculateStates)
168 ret = stealObject(v->calculateStates());
174 Dali::Property::Index GetNamePropertyIndex() override
176 return Dali::Property::INVALID_INDEX;
179 Dali::Property::Index GetDescriptionPropertyIndex() override
181 return Dali::Property::INVALID_INDEX;
184 virtual bool ShouldReportZeroChildren()
188 if (v->shouldReportZeroChildren)
190 ret = v->shouldReportZeroChildren();
196 std::size_t GetChildCount() override
198 bool highlighted = (self == Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor());
200 if (ShouldReportZeroChildren())
204 // We still allow the highlight frame to be reported as a child of this actor
205 // even though its ShouldReportZeroChildren() method returned true.
206 ret += static_cast<std::size_t>(highlighted);
212 return AccessibleImpl::GetChildCount();
216 Dali::Accessibility::Accessible *GetChildAtIndex(std::size_t index) override
218 bool highlighted = (self == Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor());
220 if (ShouldReportZeroChildren())
222 if (highlighted && index == 0)
224 return Dali::Accessibility::Accessible::Get(currentHighlightActor.GetHandle());
228 // We should not end up here. When ShouldReportZeroChildren() returns true,
229 // there are two possible cases:
230 // (1) The actor is not highlighted, so GetChildCount() returns zero, and so
231 // GetChildAtIndex() is not called.
232 // (2) The actor is highlighted, so GetChildCount() returns one. The only valid
233 // argument for GetChildAtIndex() is zero.
234 throw std::domain_error{"Invalid index"};
239 return AccessibleImpl::GetChildAtIndex(index);
243 bool IsScrollable() override
249 ret = v->isScrollable();
256 void EnsureChildVisible(Dali::Actor child) override;
257 void EnsureSelfVisible() override;
261 struct AccessibleImpl_NUI_Value : public AccessibleImpl_NUI,
262 public virtual Dali::Accessibility::Value
264 using AccessibleImpl_NUI::AccessibleImpl_NUI;
266 double GetMinimum() override
272 ret = v->getMinimum();
278 double GetCurrent() override
284 ret = v->getCurrent();
290 double GetMaximum() override
296 ret = v->getMaximum();
302 bool SetCurrent(double val) override
308 ret = v->setCurrent(val);
314 double GetMinimumIncrement() override
318 if (v->getMinimumIncrement)
320 ret = v->getMinimumIncrement();
327 struct AccessibleImpl_NUI_EditableText : public AccessibleImpl_NUI,
328 public virtual Dali::Accessibility::Text,
329 public virtual Dali::Accessibility::EditableText
331 using AccessibleImpl_NUI::AccessibleImpl_NUI;
333 std::string GetText(std::size_t startOffset, std::size_t endOffset) override
339 ret = stealString(v->getText(static_cast<int>(startOffset), static_cast<int>(endOffset)));
345 std::size_t GetCharacterCount() override
349 if (v->getCharacterCount)
351 ret = static_cast<std::size_t>(v->getCharacterCount());
357 std::size_t GetCaretOffset() override
361 if (v->getCaretOffset)
363 ret = static_cast<std::size_t>(v->getCaretOffset());
369 bool SetCaretOffset(std::size_t offset) override
373 if (v->setCaretOffset)
375 ret = v->setCaretOffset(static_cast<int>(offset));
381 Dali::Accessibility::Range GetTextAtOffset(std::size_t offset, Dali::Accessibility::TextBoundary boundary) override
383 Dali::Accessibility::Range ret{};
385 if (v->getTextAtOffset)
387 ret = stealObject(v->getTextAtOffset(static_cast<int>(offset), static_cast<int>(boundary)));
393 Dali::Accessibility::Range GetSelection(std::size_t selectionNum) override
395 Dali::Accessibility::Range ret{};
399 ret = stealObject(v->getSelection(static_cast<int>(selectionNum)));
405 bool RemoveSelection(std::size_t selectionNum) override
409 if (v->removeSelection)
411 ret = v->removeSelection(static_cast<int>(selectionNum));
417 bool SetSelection(std::size_t selectionNum, std::size_t startOffset, std::size_t endOffset) override
423 ret = v->setSelection(static_cast<int>(selectionNum), static_cast<int>(startOffset), static_cast<int>(endOffset));
429 bool CopyText(std::size_t startPosition, std::size_t endPosition) override
435 ret = v->copyText(static_cast<int>(startPosition), static_cast<int>(endPosition));
441 bool CutText(std::size_t startPosition, std::size_t endPosition) override
447 ret = v->cutText(static_cast<int>(startPosition), static_cast<int>(endPosition));
457 IFACE_EDITABLE_TEXT = 2,
460 } // anonymous namespace
464 SWIGEXPORT void SWIGSTDCALL CSharp_Dali_Toolkit_DevelControl_SetAccessibilityConstructor_NUI
465 (void *arg1_self, int arg2_role, int arg3_iface, const void *arg4_vtable, int arg5_vtableSize)
467 GUARD_ON_NULL_RET(arg1_self);
468 GUARD_ON_NULL_RET(arg4_vtable);
471 Dali::Actor self = *(Dali::Actor *)arg1_self;
472 auto role = static_cast<Dali::Accessibility::Role>(arg2_role);
473 int iface = arg3_iface;
474 const auto *vtable = static_cast<const AccessibilityDelegate *>(arg4_vtable);
475 auto vtableSize = static_cast<std::size_t>(arg5_vtableSize);
477 if (vtableSize != sizeof(*vtable))
479 throw std::runtime_error("SetAccessibilityConstructor_NUI interop error: Marshal.SizeOf<AccessibilityDelegate>() != sizeof(AccessibilityDelegate)");
482 SetAccessibilityConstructor(self, [=](Dali::Actor actor)
484 Dali::Accessibility::Accessible *accessible{};
489 DALI_LOG_ERROR("SetAccessibilityConstructor_NUI error: unknown interface %d", iface);
492 accessible = new AccessibleImpl_NUI(actor, role, vtable);
495 accessible = new AccessibleImpl_NUI_Value(actor, role, vtable);
497 case IFACE_EDITABLE_TEXT:
498 accessible = new AccessibleImpl_NUI_EditableText(actor, role, vtable);
502 return std::unique_ptr<Dali::Accessibility::Accessible>(accessible);
507 SWIGEXPORT char *SWIGSTDCALL CSharp_Dali_Toolkit_DevelControl_AccessibleImpl_NUI_DuplicateString(const char *arg)