[AT-SPI] Add Table and TableCell interfaces
[platform/core/uifw/dali-adaptor.git] / dali / devel-api / adaptor-framework / accessibility.cpp
index fcf60cd..bba8f1d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020  Samsung Electronics Co., Ltd
+ * Copyright 2022  Samsung Electronics Co., Ltd
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <dali/public-api/object/object-registry.h>
 #include <dali/public-api/object/type-info.h>
 #include <dali/public-api/object/type-registry-helper.h>
-#include <dali/public-api/object/weak-handle.h>
+#include <string_view>
+#include <unordered_map>
 
 // INTERNAL INCLUDES
 #include <dali/devel-api/adaptor-framework/accessibility-bridge.h>
+#include <dali/devel-api/adaptor-framework/actor-accessible.h>
 #include <dali/devel-api/adaptor-framework/proxy-accessible.h>
 #include <dali/devel-api/adaptor-framework/window-devel.h>
 #include <dali/devel-api/atspi-interfaces/accessible.h>
+#include <dali/devel-api/atspi-interfaces/action.h>
+#include <dali/devel-api/atspi-interfaces/application.h>
 #include <dali/devel-api/atspi-interfaces/collection.h>
 #include <dali/devel-api/atspi-interfaces/component.h>
+#include <dali/devel-api/atspi-interfaces/editable-text.h>
+#include <dali/devel-api/atspi-interfaces/hyperlink.h>
+#include <dali/devel-api/atspi-interfaces/hypertext.h>
+#include <dali/devel-api/atspi-interfaces/selection.h>
+#include <dali/devel-api/atspi-interfaces/socket.h>
+#include <dali/devel-api/atspi-interfaces/table.h>
+#include <dali/devel-api/atspi-interfaces/table-cell.h>
+#include <dali/devel-api/atspi-interfaces/text.h>
+#include <dali/devel-api/atspi-interfaces/value.h>
 #include <dali/internal/adaptor/common/adaptor-impl.h>
+#include <dali/internal/window-system/common/window-impl.h>
 #include <dali/public-api/dali-adaptor-common.h>
 
 using namespace Dali::Accessibility;
@@ -42,510 +56,241 @@ const std::string& Dali::Accessibility::Address::GetBus() const
   return mBus.empty() && Bridge::GetCurrentBridge() ? Bridge::GetCurrentBridge()->GetBusName() : mBus;
 }
 
-std::string EmptyAccessibleWithAddress::GetRoleName()
+std::string Accessible::GetLocalizedRoleName() const
 {
-  return "";
+  return GetRoleName();
 }
 
-std::string Accessible::GetLocalizedRoleName()
+std::string Accessible::GetRoleName() const
 {
-  return GetRoleName();
+  static const std::unordered_map<Role, std::string_view> roleMap{
+    {Role::INVALID, "invalid"},
+    {Role::ACCELERATOR_LABEL, "accelerator label"},
+    {Role::ALERT, "alert"},
+    {Role::ANIMATION, "animation"},
+    {Role::ARROW, "arrow"},
+    {Role::CALENDAR, "calendar"},
+    {Role::CANVAS, "canvas"},
+    {Role::CHECK_BOX, "check box"},
+    {Role::CHECK_MENU_ITEM, "check menu item"},
+    {Role::COLOR_CHOOSER, "color chooser"},
+    {Role::COLUMN_HEADER, "column header"},
+    {Role::COMBO_BOX, "combo box"},
+    {Role::DATE_EDITOR, "date editor"},
+    {Role::DESKTOP_ICON, "desktop icon"},
+    {Role::DESKTOP_FRAME, "desktop frame"},
+    {Role::DIAL, "dial"},
+    {Role::DIALOG, "dialog"},
+    {Role::DIRECTORY_PANE, "directory pane"},
+    {Role::DRAWING_AREA, "drawing area"},
+    {Role::FILE_CHOOSER, "file chooser"},
+    {Role::FILLER, "filler"},
+    {Role::FOCUS_TRAVERSABLE, "focus traversable"},
+    {Role::FONT_CHOOSER, "font chooser"},
+    {Role::FRAME, "frame"},
+    {Role::GLASS_PANE, "glass pane"},
+    {Role::HTML_CONTAINER, "html container"},
+    {Role::ICON, "icon"},
+    {Role::IMAGE, "image"},
+    {Role::INTERNAL_FRAME, "internal frame"},
+    {Role::LABEL, "label"},
+    {Role::LAYERED_PANE, "layered pane"},
+    {Role::LIST, "list"},
+    {Role::LIST_ITEM, "list item"},
+    {Role::MENU, "menu"},
+    {Role::MENU_BAR, "menu bar"},
+    {Role::MENU_ITEM, "menu item"},
+    {Role::OPTION_PANE, "option pane"},
+    {Role::PAGE_TAB, "page tab"},
+    {Role::PAGE_TAB_LIST, "page tab list"},
+    {Role::PANEL, "panel"},
+    {Role::PASSWORD_TEXT, "password text"},
+    {Role::POPUP_MENU, "popup menu"},
+    {Role::PROGRESS_BAR, "progress bar"},
+    {Role::PUSH_BUTTON, "push button"},
+    {Role::RADIO_BUTTON, "radio button"},
+    {Role::RADIO_MENU_ITEM, "radio menu item"},
+    {Role::ROOT_PANE, "root pane"},
+    {Role::ROW_HEADER, "row header"},
+    {Role::SCROLL_BAR, "scroll bar"},
+    {Role::SCROLL_PANE, "scroll pane"},
+    {Role::SEPARATOR, "separator"},
+    {Role::SLIDER, "slider"},
+    {Role::SPIN_BUTTON, "spin button"},
+    {Role::SPLIT_PANE, "split pane"},
+    {Role::STATUS_BAR, "status bar"},
+    {Role::TABLE, "table"},
+    {Role::TABLE_CELL, "table cell"},
+    {Role::TABLE_COLUMN_HEADER, "table column header"},
+    {Role::TABLE_ROW_HEADER, "table row header"},
+    {Role::TEAROFF_MENU_ITEM, "tearoff menu item"},
+    {Role::TERMINAL, "terminal"},
+    {Role::TEXT, "text"},
+    {Role::TOGGLE_BUTTON, "toggle button"},
+    {Role::TOOL_BAR, "tool bar"},
+    {Role::TOOL_TIP, "tool tip"},
+    {Role::TREE, "tree"},
+    {Role::TREE_TABLE, "tree table"},
+    {Role::UNKNOWN, "unknown"},
+    {Role::VIEWPORT, "viewport"},
+    {Role::WINDOW, "window"},
+    {Role::EXTENDED, "extended"},
+    {Role::HEADER, "header"},
+    {Role::FOOTER, "footer"},
+    {Role::PARAGRAPH, "paragraph"},
+    {Role::RULER, "ruler"},
+    {Role::APPLICATION, "application"},
+    {Role::AUTOCOMPLETE, "autocomplete"},
+    {Role::EDITBAR, "edit bar"},
+    {Role::EMBEDDED, "embedded"},
+    {Role::ENTRY, "entry"},
+    {Role::CHART, "chart"},
+    {Role::CAPTION, "caution"},
+    {Role::DOCUMENT_FRAME, "document frame"},
+    {Role::HEADING, "heading"},
+    {Role::PAGE, "page"},
+    {Role::SECTION, "section"},
+    {Role::REDUNDANT_OBJECT, "redundant object"},
+    {Role::FORM, "form"},
+    {Role::LINK, "link"},
+    {Role::INPUT_METHOD_WINDOW, "input method window"},
+    {Role::TABLE_ROW, "table row"},
+    {Role::TREE_ITEM, "tree item"},
+    {Role::DOCUMENT_SPREADSHEET, "document spreadsheet"},
+    {Role::DOCUMENT_PRESENTATION, "document presentation"},
+    {Role::DOCUMENT_TEXT, "document text"},
+    {Role::DOCUMENT_WEB, "document web"},
+    {Role::DOCUMENT_EMAIL, "document email"},
+    {Role::COMMENT, "comment"},
+    {Role::LIST_BOX, "list box"},
+    {Role::GROUPING, "grouping"},
+    {Role::IMAGE_MAP, "image map"},
+    {Role::NOTIFICATION, "notification"},
+    {Role::INFO_BAR, "info bar"},
+    {Role::LEVEL_BAR, "level bar"},
+    {Role::TITLE_BAR, "title bar"},
+    {Role::BLOCK_QUOTE, "block quote"},
+    {Role::AUDIO, "audio"},
+    {Role::VIDEO, "video"},
+    {Role::DEFINITION, "definition"},
+    {Role::ARTICLE, "article"},
+    {Role::LANDMARK, "landmark"},
+    {Role::LOG, "log"},
+    {Role::MARQUEE, "marquee"},
+    {Role::MATH, "math"},
+    {Role::RATING, "rating"},
+    {Role::TIMER, "timer"},
+    {Role::STATIC, "static"},
+    {Role::MATH_FRACTION, "math fraction"},
+    {Role::MATH_ROOT, "math root"},
+    {Role::SUBSCRIPT, "subscript"},
+    {Role::SUPERSCRIPT, "superscript"},
+  };
+
+  auto it = roleMap.find(GetRole());
+
+  if(it == roleMap.end())
+  {
+    return {};
+  }
+
+  return std::string{it->second};
 }
 
-std::string Accessible::GetRoleName()
+AtspiInterfaces Accessible::GetInterfaces() const
 {
-  switch(GetRole())
+  if(!mInterfaces)
   {
-    case Role::INVALID:
-    {
-      return "invalid";
-    }
-    case Role::ACCELERATOR_LABEL:
-    {
-      return "accelerator label";
-    }
-    case Role::ALERT:
-    {
-      return "alert";
-    }
-    case Role::ANIMATION:
-    {
-      return "animation";
-    }
-    case Role::ARROW:
-    {
-      return "arrow";
-    }
-    case Role::CALENDAR:
-    {
-      return "calendar";
-    }
-    case Role::CANVAS:
-    {
-      return "canvas";
-    }
-    case Role::CHECK_BOX:
-    {
-      return "check box";
-    }
-    case Role::CHECK_MENU_ITEM:
-    {
-      return "check menu item";
-    }
-    case Role::COLOR_CHOOSER:
-    {
-      return "color chooser";
-    }
-    case Role::COLUMN_HEADER:
-    {
-      return "column header";
-    }
-    case Role::COMBO_BOX:
-    {
-      return "combo box";
-    }
-    case Role::DATE_EDITOR:
-    {
-      return "date editor";
-    }
-    case Role::DESKTOP_ICON:
-    {
-      return "desktop icon";
-    }
-    case Role::DESKTOP_FRAME:
-    {
-      return "desktop frame";
-    }
-    case Role::DIAL:
-    {
-      return "dial";
-    }
-    case Role::DIALOG:
-    {
-      return "dialog";
-    }
-    case Role::DIRECTORY_PANE:
-    {
-      return "directory pane";
-    }
-    case Role::DRAWING_AREA:
-    {
-      return "drawing area";
-    }
-    case Role::FILE_CHOOSER:
-    {
-      return "file chooser";
-    }
-    case Role::FILLER:
-    {
-      return "filler";
-    }
-    case Role::FOCUS_TRAVERSABLE:
-    {
-      return "focus traversable";
-    }
-    case Role::FONT_CHOOSER:
-    {
-      return "font chooser";
-    }
-    case Role::FRAME:
-    {
-      return "frame";
-    }
-    case Role::GLASS_PANE:
-    {
-      return "glass pane";
-    }
-    case Role::HTML_CONTAINER:
-    {
-      return "html container";
-    }
-    case Role::ICON:
-    {
-      return "icon";
-    }
-    case Role::IMAGE:
-    {
-      return "image";
-    }
-    case Role::INTERNAL_FRAME:
-    {
-      return "internal frame";
-    }
-    case Role::LABEL:
-    {
-      return "label";
-    }
-    case Role::LAYERED_PANE:
-    {
-      return "layered pane";
-    }
-    case Role::LIST:
-    {
-      return "list";
-    }
-    case Role::LIST_ITEM:
-    {
-      return "list item";
-    }
-    case Role::MENU:
-    {
-      return "menu";
-    }
-    case Role::MENU_BAR:
-    {
-      return "menu bar";
-    }
-    case Role::MENU_ITEM:
-    {
-      return "menu item";
-    }
-    case Role::OPTION_PANE:
-    {
-      return "option pane";
-    }
-    case Role::PAGE_TAB:
-    {
-      return "page tab";
-    }
-    case Role::PAGE_TAB_LIST:
-    {
-      return "page tab list";
-    }
-    case Role::PANEL:
-    {
-      return "panel";
-    }
-    case Role::PASSWORD_TEXT:
-    {
-      return "password text";
-    }
-    case Role::POPUP_MENU:
-    {
-      return "popup menu";
-    }
-    case Role::PROGRESS_BAR:
-    {
-      return "progress bar";
-    }
-    case Role::PUSH_BUTTON:
-    {
-      return "push button";
-    }
-    case Role::RADIO_BUTTON:
-    {
-      return "radio button";
-    }
-    case Role::RADIO_MENU_ITEM:
-    {
-      return "radio menu item";
-    }
-    case Role::ROOT_PANE:
-    {
-      return "root pane";
-    }
-    case Role::ROW_HEADER:
-    {
-      return "row header";
-    }
-    case Role::SCROLL_BAR:
-    {
-      return "scroll bar";
-    }
-    case Role::SCROLL_PANE:
-    {
-      return "scroll pane";
-    }
-    case Role::SEPARATOR:
-    {
-      return "separator";
-    }
-    case Role::SLIDER:
-    {
-      return "slider";
-    }
-    case Role::SPIN_BUTTON:
-    {
-      return "spin button";
-    }
-    case Role::SPLIT_PANE:
-    {
-      return "split pane";
-    }
-    case Role::STATUS_BAR:
-    {
-      return "status bar";
-    }
-    case Role::TABLE:
-    {
-      return "table";
-    }
-    case Role::TABLE_CELL:
-    {
-      return "table cell";
-    }
-    case Role::TABLE_COLUMN_HEADER:
-    {
-      return "table column header";
-    }
-    case Role::TABLE_ROW_HEADER:
-    {
-      return "table row header";
-    }
-    case Role::TEAROFF_MENU_ITEM:
-    {
-      return "tearoff menu item";
-    }
-    case Role::TERMINAL:
-    {
-      return "terminal";
-    }
-    case Role::TEXT:
-    {
-      return "text";
-    }
-    case Role::TOGGLE_BUTTON:
-    {
-      return "toggle button";
-    }
-    case Role::TOOL_BAR:
-    {
-      return "tool bar";
-    }
-    case Role::TOOL_TIP:
-    {
-      return "tool tip";
-    }
-    case Role::TREE:
-    {
-      return "tree";
-    }
-    case Role::TREE_TABLE:
-    {
-      return "tree table";
-    }
-    case Role::UNKNOWN:
-    {
-      return "unknown";
-    }
-    case Role::VIEWPORT:
-    {
-      return "viewport";
-    }
-    case Role::WINDOW:
-    {
-      return "window";
-    }
-    case Role::EXTENDED:
-    {
-      return "extended";
-    }
-    case Role::HEADER:
-    {
-      return "header";
-    }
-    case Role::FOOTER:
-    {
-      return "footer";
-    }
-    case Role::PARAGRAPH:
-    {
-      return "paragraph";
-    }
-    case Role::RULER:
-    {
-      return "ruler";
-    }
-    case Role::APPLICATION:
-    {
-      return "application";
-    }
-    case Role::AUTOCOMPLETE:
-    {
-      return "autocomplete";
-    }
-    case Role::EDITBAR:
-    {
-      return "edit bar";
-    }
-    case Role::EMBEDDED:
-    {
-      return "embedded";
-    }
-    case Role::ENTRY:
-    {
-      return "entry";
-    }
-    case Role::CHART:
-    {
-      return "chart";
-    }
-    case Role::CAPTION:
-    {
-      return "caution";
-    }
-    case Role::DOCUMENT_FRAME:
-    {
-      return "document frame";
-    }
-    case Role::HEADING:
-    {
-      return "heading";
-    }
-    case Role::PAGE:
-    {
-      return "page";
-    }
-    case Role::SECTION:
-    {
-      return "section";
-    }
-    case Role::REDUNDANT_OBJECT:
-    {
-      return "redundant object";
-    }
-    case Role::FORM:
-    {
-      return "form";
-    }
-    case Role::LINK:
-    {
-      return "link";
-    }
-    case Role::INPUT_METHOD_WINDOW:
-    {
-      return "input method window";
-    }
-    case Role::TABLE_ROW:
-    {
-      return "table row";
-    }
-    case Role::TREE_ITEM:
-    {
-      return "tree item";
-    }
-    case Role::DOCUMENT_SPREADSHEET:
-    {
-      return "document spreadsheet";
-    }
-    case Role::DOCUMENT_PRESENTATION:
-    {
-      return "document presentation";
-    }
-    case Role::DOCUMENT_TEXT:
-    {
-      return "document text";
-    }
-    case Role::DOCUMENT_WEB:
-    {
-      return "document web";
-    }
-    case Role::DOCUMENT_EMAIL:
-    {
-      return "document email";
-    }
-    case Role::COMMENT:
-    {
-      return "comment";
-    }
-    case Role::LIST_BOX:
-    {
-      return "list box";
-    }
-    case Role::GROUPING:
-    {
-      return "grouping";
-    }
-    case Role::IMAGE_MAP:
-    {
-      return "image map";
-    }
-    case Role::NOTIFICATION:
-    {
-      return "notification";
-    }
-    case Role::INFO_BAR:
-    {
-      return "info bar";
-    }
-    case Role::LEVEL_BAR:
-    {
-      return "level bar";
-    }
-    case Role::TITLE_BAR:
-    {
-      return "title bar";
-    }
-    case Role::BLOCK_QUOTE:
-    {
-      return "block quote";
-    }
-    case Role::AUDIO:
-    {
-      return "audio";
-    }
-    case Role::VIDEO:
-    {
-      return "video";
-    }
-    case Role::DEFINITION:
-    {
-      return "definition";
-    }
-    case Role::ARTICLE:
-    {
-      return "article";
-    }
-    case Role::LANDMARK:
-    {
-      return "landmark";
-    }
-    case Role::LOG:
-    {
-      return "log";
-    }
-    case Role::MARQUEE:
-    {
-      return "marquee";
-    }
-    case Role::MATH:
-    {
-      return "math";
-    }
-    case Role::RATING:
-    {
-      return "rating";
-    }
-    case Role::TIMER:
-    {
-      return "timer";
-    }
-    case Role::STATIC:
-    {
-      return "static";
-    }
-    case Role::MATH_FRACTION:
-    {
-      return "math fraction";
-    }
-    case Role::MATH_ROOT:
-    {
-      return "math root";
-    }
-    case Role::SUBSCRIPT:
-    {
-      return "subscript";
-    }
-    case Role::SUPERSCRIPT:
-    {
-      return "superscript";
-    }
-    case Role::MAX_COUNT:
+    mInterfaces = DoGetInterfaces();
+    DALI_ASSERT_DEBUG(mInterfaces); // There has to be at least AtspiInterface::ACCESSIBLE
+  }
+
+  return mInterfaces;
+}
+
+std::vector<std::string> Accessible::GetInterfacesAsStrings() const
+{
+  std::vector<std::string> ret;
+  AtspiInterfaces          interfaces = GetInterfaces();
+
+  for(std::size_t i = 0u; i < static_cast<std::size_t>(AtspiInterface::MAX_COUNT); ++i)
+  {
+    auto interface = static_cast<AtspiInterface>(i);
+
+    if(interfaces[interface])
     {
-      break;
+      auto name = GetInterfaceName(interface);
+
+      DALI_ASSERT_DEBUG(!name.empty());
+      ret.emplace_back(std::move(name));
     }
   }
-  return "";
+
+  return ret;
+}
+
+AtspiInterfaces Accessible::DoGetInterfaces() const
+{
+  AtspiInterfaces interfaces;
+
+  interfaces[AtspiInterface::ACCESSIBLE]    = true;
+  interfaces[AtspiInterface::ACTION]        = dynamic_cast<const Action*>(this);
+  interfaces[AtspiInterface::APPLICATION]   = dynamic_cast<const Application*>(this);
+  interfaces[AtspiInterface::COLLECTION]    = dynamic_cast<const Collection*>(this);
+  interfaces[AtspiInterface::COMPONENT]     = dynamic_cast<const Component*>(this);
+  interfaces[AtspiInterface::EDITABLE_TEXT] = dynamic_cast<const EditableText*>(this);
+  interfaces[AtspiInterface::HYPERLINK]     = dynamic_cast<const Hyperlink*>(this);
+  interfaces[AtspiInterface::HYPERTEXT]     = dynamic_cast<const Hypertext*>(this);
+  interfaces[AtspiInterface::SELECTION]     = dynamic_cast<const Selection*>(this);
+  interfaces[AtspiInterface::SOCKET]        = dynamic_cast<const Socket*>(this);
+  interfaces[AtspiInterface::TABLE]         = dynamic_cast<const Table*>(this);
+  interfaces[AtspiInterface::TABLE_CELL]    = dynamic_cast<const TableCell*>(this);
+  interfaces[AtspiInterface::TEXT]          = dynamic_cast<const Text*>(this);
+  interfaces[AtspiInterface::VALUE]         = dynamic_cast<const Value*>(this);
+
+  return interfaces;
+}
+
+std::string Accessible::GetInterfaceName(AtspiInterface interface)
+{
+  static const std::unordered_map<AtspiInterface, std::string_view> interfaceMap{
+    {AtspiInterface::ACCESSIBLE, "org.a11y.atspi.Accessible"},
+    {AtspiInterface::ACTION, "org.a11y.atspi.Action"},
+    {AtspiInterface::APPLICATION, "org.a11y.atspi.Application"},
+    {AtspiInterface::CACHE, "org.a11y.atspi.Cache"},
+    {AtspiInterface::COLLECTION, "org.a11y.atspi.Collection"},
+    {AtspiInterface::COMPONENT, "org.a11y.atspi.Component"},
+    {AtspiInterface::DEVICE_EVENT_CONTROLLER, "org.a11y.atspi.DeviceEventController"},
+    {AtspiInterface::DEVICE_EVENT_LISTENER, "org.a11y.atspi.DeviceEventListener"},
+    {AtspiInterface::DOCUMENT, "org.a11y.atspi.Document"},
+    {AtspiInterface::EDITABLE_TEXT, "org.a11y.atspi.EditableText"},
+    {AtspiInterface::EVENT_DOCUMENT, "org.a11y.atspi.Event.Document"},
+    {AtspiInterface::EVENT_FOCUS, "org.a11y.atspi.Event.Focus"},
+    {AtspiInterface::EVENT_KEYBOARD, "org.a11y.atspi.Event.Keyboard"},
+    {AtspiInterface::EVENT_MOUSE, "org.a11y.atspi.Event.Mouse"},
+    {AtspiInterface::EVENT_OBJECT, "org.a11y.atspi.Event.Object"},
+    {AtspiInterface::EVENT_TERMINAL, "org.a11y.atspi.Event.Terminal"},
+    {AtspiInterface::EVENT_WINDOW, "org.a11y.atspi.Event.Window"},
+    {AtspiInterface::HYPERLINK, "org.a11y.atspi.Hyperlink"},
+    {AtspiInterface::HYPERTEXT, "org.a11y.atspi.Hypertext"},
+    {AtspiInterface::IMAGE, "org.a11y.atspi.Image"},
+    {AtspiInterface::REGISTRY, "org.a11y.atspi.Registry"},
+    {AtspiInterface::SELECTION, "org.a11y.atspi.Selection"},
+    {AtspiInterface::SOCKET, "org.a11y.atspi.Socket"},
+    {AtspiInterface::TABLE, "org.a11y.atspi.Table"},
+    {AtspiInterface::TABLE_CELL, "org.a11y.atspi.TableCell"},
+    {AtspiInterface::TEXT, "org.a11y.atspi.Text"},
+    {AtspiInterface::VALUE, "org.a11y.atspi.Value"},
+  };
+
+  auto it = interfaceMap.find(interface);
+
+  if(it == interfaceMap.end())
+  {
+    return {};
+  }
+
+  return std::string{it->second};
 }
 
 Dali::Actor Accessible::GetCurrentlyHighlightedActor()
@@ -595,66 +340,21 @@ void Bridge::SetIsOnRootLevel(Accessible* owner)
 
 namespace
 {
-class AdaptorAccessible : public virtual Accessible, public virtual Collection, public virtual Component
+class AdaptorAccessible : public ActorAccessible
 {
-protected:
-  Dali::WeakHandle<Dali::Actor> mSelf;
-  bool                          mRoot = false;
-
-  Dali::Actor Self()
-  {
-    auto handle = mSelf.GetHandle();
-
-    // AdaptorAccessible is deleted on ObjectDestroyedSignal
-    // for the respective actor (see `nonControlAccessibles`).
-    DALI_ASSERT_ALWAYS(handle);
+private:
+  std::unique_ptr<TriggerEventInterface> mRenderNotification = nullptr;
 
-    return handle;
-  }
+protected:
+  bool mRoot = false;
 
 public:
   AdaptorAccessible(Dali::Actor actor, bool isRoot)
-  : mSelf(actor),
+  : ActorAccessible(actor),
     mRoot(isRoot)
   {
   }
 
-  Dali::Rect<> GetExtents(Dali::Accessibility::CoordinateType type) override
-  {
-    Dali::Actor actor                   = Self();
-    Vector2     screenPosition          = actor.GetProperty(Actor::Property::SCREEN_POSITION).Get<Vector2>();
-    Vector3     size                    = actor.GetCurrentProperty<Vector3>(Actor::Property::SIZE) * actor.GetCurrentProperty<Vector3>(Actor::Property::WORLD_SCALE);
-    bool        positionUsesAnchorPoint = actor.GetProperty(Actor::Property::POSITION_USES_ANCHOR_POINT).Get<bool>();
-    Vector3     anchorPointOffSet       = size * (positionUsesAnchorPoint ? actor.GetCurrentProperty<Vector3>(Actor::Property::ANCHOR_POINT) : AnchorPoint::TOP_LEFT);
-    Vector2     position                = Vector2(screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y);
-
-    if(type == Dali::Accessibility::CoordinateType::WINDOW)
-    {
-      return {position.x, position.y, size.x, size.y};
-    }
-    else // Dali::Accessibility::CoordinateType::SCREEN
-    {
-      auto window = Dali::DevelWindow::Get(actor);
-      auto windowPosition = window.GetPosition();
-      return {position.x + windowPosition.GetX(), position.y + windowPosition.GetY(), size.x, size.y};
-    }
-  }
-
-  Dali::Accessibility::ComponentLayer GetLayer() override
-  {
-    return Dali::Accessibility::ComponentLayer::WINDOW;
-  }
-
-  int16_t GetMdiZOrder() override
-  {
-    return 0;
-  }
-
-  double GetAlpha() override
-  {
-    return 0;
-  }
-
   bool GrabFocus() override
   {
     return false;
@@ -662,73 +362,72 @@ public:
 
   bool GrabHighlight() override
   {
-    return false;
-  }
-
-  bool ClearHighlight() override
-  {
-    return false;
-  }
-
-  bool IsScrollable() override
-  {
-    return false;
-  }
+    if(!IsUp())
+    {
+      return false;
+    }
 
-  std::string GetName() override
-  {
-    return Self().GetProperty<std::string>(Dali::Actor::Property::NAME);
-  }
+    // Only window accessible is able to grab and clear highlight
+    if(!mRoot)
+    {
+      return false;
+    }
 
-  std::string GetDescription() override
-  {
-    return "";
-  }
+    auto self                = Self();
+    auto oldHighlightedActor = GetCurrentlyHighlightedActor();
+    if(self == oldHighlightedActor)
+    {
+      return true;
+    }
 
-  Accessible* GetParent() override
-  {
-    if(IsOnRootLevel())
+    // Clear the old highlight.
+    if(oldHighlightedActor)
     {
-      auto data = GetBridgeData();
-      return data->mBridge->GetApplication();
+      auto oldHighlightedObject = Dali::Accessibility::Component::DownCast(Accessible::Get(oldHighlightedActor));
+      if(oldHighlightedObject)
+      {
+        oldHighlightedObject->ClearHighlight();
+      }
     }
-    return Get(Self().GetParent());
-  }
 
-  size_t GetChildCount() override
-  {
-    return static_cast<size_t>(Self().GetChildCount());
+    SetCurrentlyHighlightedActor(self);
+
+    auto                             window     = Dali::DevelWindow::Get(self);
+    Dali::Internal::Adaptor::Window& windowImpl = Dali::GetImplementation(window);
+    windowImpl.EmitAccessibilityHighlightSignal(true);
+
+    return true;
   }
 
-  Accessible* GetChildAtIndex(size_t index) override
+  bool ClearHighlight() override
   {
-    auto numberOfChildren = static_cast<size_t>(Self().GetChildCount());
-    if(index >= numberOfChildren)
+    if(!IsUp())
     {
-      throw std::domain_error{"invalid index " + std::to_string(index) + " for object with " + std::to_string(numberOfChildren) + " children"};
+      return false;
     }
-    return Get(Self().GetChildAt(static_cast<unsigned int>(index)));
-  }
 
-  size_t GetIndexInParent() override
-  {
-    auto parent = Self().GetParent();
-    if(!parent)
+    // Only window accessible is able to grab and clear highlight
+    if(!mRoot)
     {
-      return 0;
+      return false;
     }
-    auto size = static_cast<size_t>(parent.GetChildCount());
-    for(auto i = 0u; i < size; ++i)
+
+    auto self = Self();
+    if(self != GetCurrentlyHighlightedActor())
     {
-      if(parent.GetChildAt(i) == Self())
-      {
-        return i;
-      }
+      return false;
     }
-    throw std::domain_error{"actor is not a child of it's parent"};
+
+    SetCurrentlyHighlightedActor({});
+
+    auto                             window     = Dali::DevelWindow::Get(self);
+    Dali::Internal::Adaptor::Window& windowImpl = Dali::GetImplementation(window);
+    windowImpl.EmitAccessibilityHighlightSignal(false);
+
+    return true;
   }
 
-  Role GetRole() override
+  Role GetRole() const override
   {
     return mRoot ? Role::WINDOW : Role::REDUNDANT_OBJECT;
   }
@@ -738,8 +437,8 @@ public:
     States state;
     if(mRoot)
     {
-      auto window = Dali::DevelWindow::Get(Self());
-      auto visible = window.IsVisible();
+      auto window             = Dali::DevelWindow::Get(Self());
+      auto visible            = window.IsVisible();
       state[State::ENABLED]   = true;
       state[State::SENSITIVE] = true;
       state[State::SHOWING]   = visible;
@@ -748,21 +447,29 @@ public:
     }
     else
     {
-      auto parentState = GetParent()->GetStates();
+      auto parentState      = GetParent()->GetStates();
       state[State::SHOWING] = parentState[State::SHOWING];
       state[State::VISIBLE] = parentState[State::VISIBLE];
     }
     return state;
   }
 
-  Attributes GetAttributes() override
+  Attributes GetAttributes() const override
   {
+    Attributes attributes;
+
+    if(mRoot)
+    {
+      Dali::Window                     window     = Dali::DevelWindow::Get(Self());
+      Dali::Internal::Adaptor::Window& windowImpl = Dali::GetImplementation(window);
+      attributes["resID"]                         = windowImpl.GetNativeResourceId();
+    }
+
     Dali::TypeInfo type;
     Self().GetTypeInfo(type);
-    return
-    {
-      {"class", type.GetName()},
-    };
+    attributes["class"] = type.GetName();
+
+    return attributes;
   }
 
   bool DoGesture(const GestureInfo& gestureInfo) override
@@ -775,16 +482,47 @@ public:
     return {};
   }
 
-  Dali::Actor GetInternalActor() override
+  void SetListenPostRender(bool enabled) override
+  {
+    if (!mRoot)
+    {
+      return;
+    }
+
+    auto window                                 = Dali::DevelWindow::Get(Self());
+    Dali::Internal::Adaptor::Window& windowImpl = Dali::GetImplementation(window);
+
+    if(!mRenderNotification)
+    {
+      mRenderNotification = std::unique_ptr<TriggerEventInterface>(
+                                           TriggerEventFactory::CreateTriggerEvent(MakeCallback(this, &AdaptorAccessible::OnPostRender),
+                                           TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER));
+    }
+
+    if (enabled)
+    {
+      windowImpl.SetRenderNotification(mRenderNotification.get());
+    }
+    else
+    {
+      windowImpl.SetRenderNotification(nullptr);
+    }
+  }
+
+  void OnPostRender()
   {
-    return mSelf.GetHandle();
+    Accessibility::Bridge::GetCurrentBridge()->EmitPostRender(this);
   }
 }; // AdaptorAccessible
 
 using AdaptorAccessiblesType = std::unordered_map<const Dali::RefObject*, std::unique_ptr<AdaptorAccessible> >;
 
 // Save RefObject from an Actor in Accessible::Get()
-AdaptorAccessiblesType gAdaptorAccessibles;
+AdaptorAccessiblesType& GetAdaptorAccessibles()
+{
+  static AdaptorAccessiblesType gAdaptorAccessibles;
+  return gAdaptorAccessibles;
+}
 
 std::function<Accessible*(Dali::Actor)> convertingFunctor = [](Dali::Actor) -> Accessible* {
   return nullptr;
@@ -796,6 +534,9 @@ ObjectRegistry objectRegistry;
 void Accessible::SetObjectRegistry(ObjectRegistry registry)
 {
   objectRegistry = registry;
+  objectRegistry.ObjectDestroyedSignal().Connect([](const Dali::RefObject* obj) {
+    GetAdaptorAccessibles().erase(obj);
+  });
 }
 
 void Accessible::RegisterExternalAccessibleGetter(std::function<Accessible*(Dali::Actor)> functor)
@@ -803,7 +544,7 @@ void Accessible::RegisterExternalAccessibleGetter(std::function<Accessible*(Dali
   convertingFunctor = functor;
 }
 
-Accessible* Accessible::Get(Dali::Actor actor, bool isRoot)
+Accessible* Accessible::Get(Dali::Actor actor)
 {
   if(!actor)
   {
@@ -813,15 +554,15 @@ Accessible* Accessible::Get(Dali::Actor actor, bool isRoot)
   auto accessible = convertingFunctor(actor);
   if(!accessible)
   {
-    if(gAdaptorAccessibles.empty() && objectRegistry)
-    {
-      objectRegistry.ObjectDestroyedSignal().Connect([](const Dali::RefObject* obj) {
-        gAdaptorAccessibles.erase(obj);
-      });
-    }
-    auto pair = gAdaptorAccessibles.emplace(&actor.GetBaseObject(), nullptr);
+    auto pair = GetAdaptorAccessibles().emplace(&actor.GetBaseObject(), nullptr);
     if(pair.second)
     {
+      bool                     isRoot = false;
+      Dali::Integration::Scene scene  = Dali::Integration::Scene::Get(actor);
+      if(scene)
+      {
+        isRoot = (actor == scene.GetRootLayer());
+      }
       pair.first->second.reset(new AdaptorAccessible(actor, isRoot));
     }
     accessible = pair.first->second.get();