2 * Copyright 2020 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.
20 #include <dali/integration-api/debug.h>
21 #include <dali/public-api/actors/actor.h>
22 #include <dali/public-api/actors/layer.h>
23 #include <dali/public-api/object/base-object.h>
24 #include <dali/public-api/object/object-registry.h>
25 #include <dali/public-api/object/type-info.h>
26 #include <dali/public-api/object/type-registry-helper.h>
27 #include <dali/public-api/object/weak-handle.h>
30 #include <dali/devel-api/adaptor-framework/accessibility-impl.h>
31 #include <dali/devel-api/adaptor-framework/window-devel.h>
32 #include <dali/internal/adaptor/common/adaptor-impl.h>
33 #include <dali/public-api/dali-adaptor-common.h>
35 using namespace Dali::Accessibility;
38 const std::string& Dali::Accessibility::Address::GetBus() const
40 return mBus.empty() && Bridge::GetCurrentBridge() ? Bridge::GetCurrentBridge()->GetBusName() : mBus;
43 std::string EmptyAccessibleWithAddress::GetRoleName()
48 std::string Accessible::GetLocalizedRoleName()
53 std::string Accessible::GetRoleName()
61 case Role::ACCELERATOR_LABEL:
63 return "accelerator label";
89 case Role::CHECK_MENU_ITEM:
91 return "check menu item";
93 case Role::COLOR_CHOOSER:
95 return "color chooser";
97 case Role::COLUMN_HEADER:
99 return "column header";
101 case Role::COMBO_BOX:
105 case Role::DATE_EDITOR:
107 return "date editor";
109 case Role::DESKTOP_ICON:
111 return "desktop icon";
113 case Role::DESKTOP_FRAME:
115 return "desktop frame";
125 case Role::DIRECTORY_PANE:
127 return "directory pane";
129 case Role::DRAWING_AREA:
131 return "drawing area";
133 case Role::FILE_CHOOSER:
135 return "file chooser";
141 case Role::FOCUS_TRAVERSABLE:
143 return "focus traversable";
145 case Role::FONT_CHOOSER:
147 return "font chooser";
153 case Role::GLASS_PANE:
157 case Role::HTML_CONTAINER:
159 return "html container";
169 case Role::INTERNAL_FRAME:
171 return "internal frame";
177 case Role::LAYERED_PANE:
179 return "layered pane";
185 case Role::LIST_ITEM:
197 case Role::MENU_ITEM:
201 case Role::OPTION_PANE:
203 return "option pane";
209 case Role::PAGE_TAB_LIST:
211 return "page tab list";
217 case Role::PASSWORD_TEXT:
219 return "password text";
221 case Role::POPUP_MENU:
225 case Role::PROGRESS_BAR:
227 return "progress bar";
229 case Role::PUSH_BUTTON:
231 return "push button";
233 case Role::RADIO_BUTTON:
235 return "radio button";
237 case Role::RADIO_MENU_ITEM:
239 return "radio menu item";
241 case Role::ROOT_PANE:
245 case Role::ROW_HEADER:
249 case Role::SCROLL_BAR:
253 case Role::SCROLL_PANE:
255 return "scroll pane";
257 case Role::SEPARATOR:
265 case Role::SPIN_BUTTON:
267 return "spin button";
269 case Role::SPLIT_PANE:
273 case Role::STATUS_BAR:
281 case Role::TABLE_CELL:
285 case Role::TABLE_COLUMN_HEADER:
287 return "table column header";
289 case Role::TABLE_ROW_HEADER:
291 return "table row header";
293 case Role::TEAROFF_MENU_ITEM:
295 return "tearoff menu item";
305 case Role::TOGGLE_BUTTON:
307 return "toggle button";
321 case Role::TREE_TABLE:
349 case Role::PARAGRAPH:
357 case Role::APPLICATION:
359 return "application";
361 case Role::AUTOCOMPLETE:
363 return "autocomplete";
385 case Role::DOCUMENT_FRAME:
387 return "document frame";
401 case Role::REDUNDANT_OBJECT:
403 return "redundant object";
413 case Role::INPUT_METHOD_WINDOW:
415 return "input method window";
417 case Role::TABLE_ROW:
421 case Role::TREE_ITEM:
425 case Role::DOCUMENT_SPREADSHEET:
427 return "document spreadsheet";
429 case Role::DOCUMENT_PRESENTATION:
431 return "document presentation";
433 case Role::DOCUMENT_TEXT:
435 return "document text";
437 case Role::DOCUMENT_WEB:
439 return "document web";
441 case Role::DOCUMENT_EMAIL:
443 return "document email";
457 case Role::IMAGE_MAP:
461 case Role::NOTIFICATION:
463 return "notification";
469 case Role::LEVEL_BAR:
473 case Role::TITLE_BAR:
477 case Role::BLOCK_QUOTE:
479 return "block quote";
489 case Role::DEFINITION:
525 case Role::MATH_FRACTION:
527 return "math fraction";
529 case Role::MATH_ROOT:
533 case Role::SUBSCRIPT:
537 case Role::SUPERSCRIPT:
539 return "superscript";
541 case Role::MAX_COUNT:
549 Dali::Actor Accessible::GetCurrentlyHighlightedActor()
551 return IsUp() ? Bridge::GetCurrentBridge()->mData->mCurrentlyHighlightedActor : Dali::Actor{};
554 void Accessible::SetCurrentlyHighlightedActor(Dali::Actor actor)
558 Bridge::GetCurrentBridge()->mData->mCurrentlyHighlightedActor = actor;
562 Dali::Actor Accessible::GetHighlightActor()
564 return IsUp() ? Bridge::GetCurrentBridge()->mData->mHighlightActor : Dali::Actor{};
567 void Accessible::SetHighlightActor(Dali::Actor actor)
571 Bridge::GetCurrentBridge()->mData->mHighlightActor = actor;
575 void Bridge::ForceDown()
577 auto highlighted = Accessible::GetCurrentlyHighlightedActor();
580 auto component = dynamic_cast<Component*>(Accessible::Get(highlighted));
583 component->ClearHighlight();
589 void Bridge::SetIsOnRootLevel(Accessible* owner)
591 owner->mIsOnRootLevel = true;
596 class NonControlAccessible : public virtual Accessible, public virtual Collection, public virtual Component
599 Dali::WeakHandle<Dali::Actor> mSelf;
604 auto handle = mSelf.GetHandle();
606 // NonControlAccessible is deleted on ObjectDestroyedSignal
607 // for the respective actor (see `nonControlAccessibles`).
608 DALI_ASSERT_ALWAYS(handle);
614 NonControlAccessible(Dali::Actor actor, bool isRoot)
620 Dali::Rect<> GetExtents(Dali::Accessibility::CoordinateType type) override
622 Dali::Actor actor = Self();
623 Vector2 screenPosition = actor.GetProperty(Actor::Property::SCREEN_POSITION).Get<Vector2>();
624 Vector3 size = actor.GetCurrentProperty<Vector3>(Actor::Property::SIZE) * actor.GetCurrentProperty<Vector3>(Actor::Property::WORLD_SCALE);
625 bool positionUsesAnchorPoint = actor.GetProperty(Actor::Property::POSITION_USES_ANCHOR_POINT).Get<bool>();
626 Vector3 anchorPointOffSet = size * (positionUsesAnchorPoint ? actor.GetCurrentProperty<Vector3>(Actor::Property::ANCHOR_POINT) : AnchorPoint::TOP_LEFT);
627 Vector2 position = Vector2(screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y);
629 if(type == Dali::Accessibility::CoordinateType::WINDOW)
631 return {position.x, position.y, size.x, size.y};
633 else // Dali::Accessibility::CoordinateType::SCREEN
635 auto window = Dali::DevelWindow::Get(actor);
636 auto windowPosition = window.GetPosition();
637 return {position.x + windowPosition.GetX(), position.y + windowPosition.GetY(), size.x, size.y};
641 Dali::Accessibility::ComponentLayer GetLayer() override
643 return Dali::Accessibility::ComponentLayer::WINDOW;
646 int16_t GetMdiZOrder() override
651 double GetAlpha() override
656 bool GrabFocus() override
661 bool GrabHighlight() override
666 bool ClearHighlight() override
671 bool IsScrollable() override
676 std::string GetName() override
678 return Self().GetProperty<std::string>(Dali::Actor::Property::NAME);
681 std::string GetDescription() override
686 Accessible* GetParent() override
690 auto data = GetBridgeData();
691 return data->mBridge->GetApplication();
693 return Get(Self().GetParent());
696 size_t GetChildCount() override
698 return static_cast<size_t>(Self().GetChildCount());
701 Accessible* GetChildAtIndex(size_t index) override
703 auto numberOfChildren = static_cast<size_t>(Self().GetChildCount());
704 if(index >= numberOfChildren)
706 throw std::domain_error{"invalid index " + std::to_string(index) + " for object with " + std::to_string(numberOfChildren) + " children"};
708 return Get(Self().GetChildAt(static_cast<unsigned int>(index)));
711 size_t GetIndexInParent() override
713 auto parent = Self().GetParent();
718 auto size = static_cast<size_t>(parent.GetChildCount());
719 for(auto i = 0u; i < size; ++i)
721 if(parent.GetChildAt(i) == Self())
726 throw std::domain_error{"actor is not a child of it's parent"};
729 Role GetRole() override
731 return mRoot ? Role::WINDOW : Role::REDUNDANT_OBJECT;
734 States GetStates() override
739 auto window = Dali::DevelWindow::Get(Self());
740 auto visible = window.IsVisible();
741 state[State::ENABLED] = true;
742 state[State::SENSITIVE] = true;
743 state[State::SHOWING] = visible;
744 state[State::VISIBLE] = true;
745 state[State::ACTIVE] = visible;
749 auto parentState = GetParent()->GetStates();
750 state[State::SHOWING] = parentState[State::SHOWING];
751 state[State::VISIBLE] = parentState[State::VISIBLE];
756 Attributes GetAttributes() override
759 Self().GetTypeInfo(type);
762 {"class", type.GetName()},
766 bool DoGesture(const GestureInfo& gestureInfo) override
771 std::vector<Relation> GetRelationSet() override
777 using NonControlAccessiblesType = std::unordered_map<const Dali::RefObject*, std::unique_ptr<NonControlAccessible> >;
779 NonControlAccessiblesType nonControlAccessibles;
781 std::function<Accessible*(Dali::Actor)> convertingFunctor = [](Dali::Actor) -> Accessible* {
785 ObjectRegistry objectRegistry;
788 void Accessible::SetObjectRegistry(ObjectRegistry registry)
790 objectRegistry = registry;
793 void Accessible::RegisterControlAccessibilityGetter(std::function<Accessible*(Dali::Actor)> functor)
795 convertingFunctor = functor;
798 Accessible* Accessible::Get(Dali::Actor actor, bool isRoot)
805 auto accessible = convertingFunctor(actor);
808 if(nonControlAccessibles.empty() && objectRegistry)
810 objectRegistry.ObjectDestroyedSignal().Connect([](const Dali::RefObject* obj) {
811 nonControlAccessibles.erase(obj);
814 auto pair = nonControlAccessibles.emplace(&actor.GetBaseObject(), nullptr);
817 pair.first->second.reset(new NonControlAccessible(actor, isRoot));
819 accessible = pair.first->second.get();