- Brings up & Refactoring accessibility in accordance with upstream.
- Make a AXPlatformNodeEfl inherit from AXPlatformNodeAuraLinux
for ATK event/callback.
- Migrate from BrowserAccessibility* to AXPlatformNode*.
- Remove BrowserAccessibilityManagerEfl / BrowserAccessibilityEfl.
- Support value change event.
Reference:
https://review.tizen.org/gerrit/279337
https://review.tizen.org/gerrit/279612
Change-Id: Ie312e18870a5d20304be4b8c5a6b11aa1b23ae33
Signed-off-by: Ayush Kumar <ayush.k123@samsung.com>
# These packages should _only_ be expected when building for a target.
assert(current_toolchain == default_toolchain)
-if (use_atk) {
+if (use_atk && !use_efl) {
assert(use_glib, "use_atk=true requires that use_glib=true")
}
assert(!use_glib || (is_linux && !is_castos))
-use_atk = use_glib && !use_efl && current_toolchain == default_toolchain
+use_atk =
+ is_tizen || (use_glib && !use_efl && current_toolchain == default_toolchain)
# Whether using Xvfb to provide a display server for a test might be
# necessary.
}
gfx::NativeViewAccessible BrowserAccessibility::GetFocus() const {
+#if defined(TIZEN_ATK_SUPPORT)
+ if (!manager_)
+ return nullptr;
+#endif
+
BrowserAccessibility* focused = manager()->GetFocus();
if (!focused)
return nullptr;
return focused->GetNativeViewAccessible();
}
+#if defined(TIZEN_ATK_SUPPORT)
+gfx::NativeViewAccessible BrowserAccessibility::GetActiveDescendant() {
+ if (!manager_)
+ return nullptr;
+
+ auto* active_descendant =
+ manager()->GetActiveDescendant(manager()->GetFocus());
+ if (!active_descendant)
+ return nullptr;
+
+ return active_descendant->GetNativeViewAccessible();
+}
+
+void BrowserAccessibility::EvasToBlinkCords(int x,
+ int y,
+ int* view_x,
+ int* view_y) {
+ if (manager_)
+ manager_->EvasToBlinkCords(x, y, view_x, view_y);
+}
+
+void BrowserAccessibility::CheckFocusOnEwebview() {
+ if (manager_)
+ manager_->CheckFocusOnEwebview();
+}
+#endif
+
ui::AXPlatformNode* BrowserAccessibility::GetFromNodeID(int32_t id) {
BrowserAccessibility* node = manager_->GetFromID(id);
if (!node)
gfx::NativeViewAccessible HitTestSync(int physical_pixel_x,
int physical_pixel_y) const override;
gfx::NativeViewAccessible GetFocus() const override;
+#if defined(TIZEN_ATK_SUPPORT)
+ gfx::NativeViewAccessible GetActiveDescendant() override;
+ void EvasToBlinkCords(int x, int y, int* view_x, int* view_y) override;
+ void CheckFocusOnEwebview() override;
+#endif
ui::AXPlatformNode* GetFromNodeID(int32_t id) override;
ui::AXPlatformNode* GetFromTreeIDAndNodeID(const ui::AXTreeID& ax_tree_id,
int32_t id) override;
return GetNode()->ComputeTextAttributes();
}
+#if defined(TIZEN_ATK_SUPPORT)
+ui::AXPlatformNode* BrowserAccessibilityAuraLinux::GetRoot() {
+ BrowserAccessibility* accessibility =
+ static_cast<BrowserAccessibility*>(manager_->RootDelegate());
+ if (!accessibility)
+ return nullptr;
+
+ return ToBrowserAccessibilityAuraLinux(accessibility)->GetNode();
+}
+
+gfx::NativeViewAccessible BrowserAccessibilityAuraLinux::GetRootAtkObject() {
+ return root_atk_object_;
+}
+
+void BrowserAccessibilityAuraLinux::SetRootAtkObject(
+ gfx::NativeViewAccessible root_atk_object) {
+ root_atk_object_ = root_atk_object;
+}
+#endif
+
} // namespace content
ui::TextAttributeList ComputeTextAttributes() const override;
+#if defined(TIZEN_ATK_SUPPORT)
+ ui::AXPlatformNode* GetRoot() override;
+ gfx::NativeViewAccessible GetRootAtkObject() override;
+ void SetRootAtkObject(gfx::NativeViewAccessible root_atk_object);
+#endif
+
private:
// TODO: use a unique_ptr since the node is owned by this class.
raw_ptr<ui::AXPlatformNodeAuraLinux> platform_node_;
+#if defined(TIZEN_ATK_SUPPORT)
+ gfx::NativeViewAccessible root_atk_object_ = nullptr;
+#endif
};
CONTENT_EXPORT BrowserAccessibilityAuraLinux* ToBrowserAccessibilityAuraLinux(
#include "content/public/common/content_switches.h"
#endif
+#if defined(TIZEN_ATK_SUPPORT)
+#include "content/browser/renderer_host/render_frame_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_aura.h"
+#endif
+
namespace content {
namespace {
device_scale_factor_ = delegate_->AccessibilityGetDeviceScaleFactor();
}
+#if defined(TIZEN_ATK_SUPPORT)
+void BrowserAccessibilityManager::EvasToBlinkCords(int x,
+ int y,
+ int* view_x,
+ int* view_y) {
+ auto view =
+ static_cast<RenderWidgetHostViewAura*>(delegate_->AccessibilityGetView());
+
+ if (!view)
+ return;
+
+ view->offscreen_helper()->EvasToBlinkCords(x, y, view_x, view_y);
+ gfx::Rect rect(*view_x, *view_y, 0, 0);
+ rect.Offset(GetViewBoundsInScreenCoordinates().OffsetFromOrigin());
+ *view_x = rect.x();
+ *view_y = rect.y();
+}
+
+void BrowserAccessibilityManager::CheckFocusOnEwebview() {
+ auto view =
+ static_cast<RenderWidgetHostViewAura*>(delegate_->AccessibilityGetView());
+
+ if (!view)
+ return;
+
+ if (!view->offscreen_helper()->HasFocus())
+ view->offscreen_helper()->Focus(true);
+}
+#endif
+
} // namespace content
class BrowserAccessibilityManagerAndroid;
#elif BUILDFLAG(IS_WIN)
class BrowserAccessibilityManagerWin;
-#elif BUILDFLAG(USE_ATK)
+#elif BUILDFLAG(USE_ATK) || defined(TIZEN_ATK_SUPPORT)
class BrowserAccessibilityManagerAuraLinux;
#elif BUILDFLAG(IS_MAC)
class BrowserAccessibilityManagerMac;
#endif
+#if defined(TIZEN_ATK_SUPPORT)
+class BrowserAccessibilityManagerEfl;
+class RenderWidgetHostView;
+#endif
+
// To be called when a BrowserAccessibilityManager fires a generated event.
// Provides the host, the event fired, and which node id the event was for.
class RenderFrameHostImpl;
BrowserAccessibilityManagerWin* ToBrowserAccessibilityManagerWin();
#endif
-#if BUILDFLAG(USE_ATK)
+#if BUILDFLAG(USE_ATK) || defined(TIZEN_ATK_SUPPORT)
BrowserAccessibilityManagerAuraLinux*
ToBrowserAccessibilityManagerAuraLinux();
#endif
// Called in response to a hover event, caches the result for the next
// call to CachingAsyncHitTest().
void CacheHitTestResult(BrowserAccessibility* hit_test_result) const;
+#if defined(TIZEN_ATK_SUPPORT)
+ void EvasToBlinkCords(int x, int y, int* view_x, int* view_y);
+ void CheckFocusOnEwebview();
+#endif
// Updates the page scale factor for this frame.
void SetPageScaleFactor(float page_scale_factor);
class RenderFrameHostImpl;
class WebContentsAccessibility;
+class RenderWidgetHostView;
// Pure abstract class that is used by `BrowserAccessibilityManager` to gather
// information or perform actions that are implemented differently between the
virtual WebContentsAccessibility*
AccessibilityGetWebContentsAccessibility() = 0;
+#if defined(TIZEN_ATK_SUPPORT)
+ virtual RenderWidgetHostView* AccessibilityGetView() = 0;
+#endif
+
protected:
WebAXPlatformTreeManagerDelegate() = default;
};
return o << LifecycleStateImplToString(s);
}
+#if defined(TIZEN_ATK_SUPPORT)
+RenderWidgetHostView* RenderFrameHostImpl::AccessibilityGetView() {
+ return render_view_host_->GetWidget()->GetView();
+}
+#endif
+
} // namespace content
RenderFrameHostImpl* AccessibilityRenderFrameHost() override;
WebContentsAccessibility* AccessibilityGetWebContentsAccessibility() override;
+#if defined(TIZEN_ATK_SUPPORT)
+ RenderWidgetHostView* AccessibilityGetView() override;
+#endif
+
// SiteInstanceGroup::Observer
void RenderProcessGone(SiteInstanceGroup* site_instance_group,
const ChildProcessTerminationInfo& info) override;
}
gfx::Rect RenderWidgetHostViewAura::GetViewBounds() {
+#if BUILDFLAG(IS_EFL)
+ return offscreen_helper()->GetViewBounds();
+#else
return window_->GetBoundsInScreen();
+#endif
}
void RenderWidgetHostViewAura::UpdateBackgroundColor() {
prefs.stylus_handwriting_enabled = stylus_handwriting_enabled_;
+#if BUILDFLAG(IS_EFL)
+ if (spatial_navigation_enabled_)
+ prefs.spatial_navigation_enabled = true;
+
+ if (atk_enabled_)
+ prefs.atk_enabled = true;
+#endif
+
prefs.disable_reading_from_canvas =
command_line.HasSwitch(switches::kDisableReadingFromCanvas);
GLSharedContextEfl::Initialize(root_window);
}
+
+void WebContentsImpl::SetSpatialNavigationEnabled(bool enabled) {
+ if (spatial_navigation_enabled_ == enabled)
+ return;
+
+ spatial_navigation_enabled_ = enabled;
+ NotifyPreferencesChanged();
+}
+
+void WebContentsImpl::SetAtkEnabled(bool enabled) {
+ if (atk_enabled_ == enabled)
+ return;
+
+ atk_enabled_ = enabled;
+ NotifyPreferencesChanged();
+}
#endif
} // namespace content
Evas_Object* GetEflNativeView() const { return efl_native_view_; }
void set_ewk_view(void* ewk_view) { ewk_view_ = ewk_view; }
void* ewk_view() const { return ewk_view_; }
+
+ void SetSpatialNavigationEnabled(bool enabled);
+ void SetAtkEnabled(bool enabled);
#endif
// Returns the SavePackage which manages the page saving job. May be NULL.
#if BUILDFLAG(IS_EFL)
Evas_Object* efl_native_view_ = nullptr;
void* ewk_view_ = nullptr;
+
+ bool atk_enabled_ = false;
+ bool spatial_navigation_enabled_ = false;
#endif
base::WeakPtrFactory<WebContentsImpl> loading_weak_factory_{this};
WebView* web_view = render_frame_->GetWebView();
WebSettings* settings = web_view->GetSettings();
+#if defined(TIZEN_ATK_SUPPORT)
+ settings->SetAccessibilityEnabled(true);
+#endif
+
SetAccessibilityCrashKey(mode);
#if BUILDFLAG(IS_ANDROID)
// Password values are only passed through on Android.
Requires(postun): /sbin/ldconfig
BuildRequires: binutils-gold
-BuildRequires: bison, edje-tools, expat-devel, flex, gettext, gperf, libcap-devel, libcurl, libatomic
+BuildRequires: at-spi2-atk-devel, bison, edje-tools, expat-devel, flex, gettext, gperf, libatk-bridge-2_0-0, libcap-devel, libcurl, libatomic
BuildRequires: libjpeg-turbo-devel, ninja, perl, python3, python3-xml, which
+BuildRequires: pkgconfig(atk)
BuildRequires: pkgconfig(capi-appfw-application)
BuildRequires: pkgconfig(capi-appfw-app-manager)
BuildRequires: pkgconfig(capi-location-manager)
default_minimum_page_scale_factor(1.f),
default_maximum_page_scale_factor(4.f),
#endif
+#if BUILDFLAG(IS_EFL)
+ atk_enabled(false),
+#endif
hide_download_ui(false),
presentation_receiver(false),
media_controls_enabled(true),
#if BUILDFLAG(IS_TIZEN)
out->max_refresh_rate = data.max_refresh_rate();
#endif
+#if BUILDFLAG(IS_EFL)
+ out->atk_enabled = data.atk_enabled();
+#endif
#if BUILDFLAG(IS_ANDROID)
out->font_scale_factor = data.font_scale_factor();
out->device_scale_adjustment = data.device_scale_adjustment();
#if BUILDFLAG(IS_EFL)
float font_scale_factor;
bool link_effect_enabled = false;
+ bool atk_enabled;
#endif
bool double_tap_to_zoom_enabled;
static bool link_effect_enabled(const blink::web_pref::WebPreferences& r) {
return r.link_effect_enabled;
}
+
+ static bool atk_enabled(const blink::web_pref::WebPreferences& r) {
+ return r.atk_enabled;
+}
#endif
#if BUILDFLAG(IS_TIZEN)
[EnableIf=is_efl]
bool link_effect_enabled;
+ [EnableIf=is_efl]
+ bool atk_enabled;
+
// Representation of the Web App Manifest scope if any.
url.mojom.Url web_app_scope;
virtual bool LinkEffectEnabled() const = 0;
#endif
+#if defined(TIZEN_ATK_SUPPORT)
+ virtual void SetAccessibilityEnabled(bool) = 0;
+ virtual bool GetAccessibilityEnabled() = 0;
+#endif
+
protected:
~WebSettings() = default;
};
if (new_focused_element)
UpdateStyleAndLayoutTreeForNode(new_focused_element);
+#if defined(TIZEN_ATK_SUPPORT) && !defined(TIZEN_ATK_FEATURE_VD)
+ LocalFrame* frame = this->GetFrame();
+ if (new_focused_element &&
+ (new_focused_element->IsFocusable() ||
+ (frame && frame->GetSettings() &&
+ frame->GetSettings()->GetAccessibilityEnabled()))) {
+#else
if (new_focused_element && new_focused_element->IsFocusable()) {
+#endif
if (IsRootEditableElement(*new_focused_element) &&
!AcceptsEditingFocus(*new_focused_element)) {
// delegate blocks focus change
// https://html.spec.whatwg.org/C/#focusing-steps
//
// 1. If new focus target is not a focusable area, ...
+#if defined(TIZEN_ATK_SUPPORT) && !defined(TIZEN_ATK_FEATURE_VD)
+ if (!IsFocusable() &&
+ !(GetDocument().GetFrame() && GetDocument().GetFrame()->GetSettings() &&
+ GetDocument().GetFrame()->GetSettings()->GetAccessibilityEnabled())) {
+#else
if (!IsFocusable()) {
+#endif
if (Element* new_focus_target = GetFocusableArea()) {
// Unlike the specification, we re-run focus() for new_focus_target
// because we can't change |this| in a member function.
// are. Here we make Hand-trees' tip, the first (biggest) node with {cursor:
// pointer}, navigable because users shouldn't need to navigate through every
// sub element that inherit this CSS.
+#if defined(TIZEN_ATK_SUPPORT)
+ if (GetComputedStyle() && GetComputedStyle()->Cursor() == ECursor::kPointer &&
+ ParentComputedStyle() &&
+ ParentComputedStyle()->Cursor() != ECursor::kPointer) {
+ return true;
+ }
+#else
if (GetComputedStyle()->Cursor() == ECursor::kPointer &&
(!ParentComputedStyle() ||
(ParentComputedStyle()->Cursor() != ECursor::kPointer))) {
return true;
}
+#endif
if (!IsSVGElement())
return false;
}
#endif
+#if defined(TIZEN_ATK_SUPPORT)
+void WebSettingsImpl::SetAccessibilityEnabled(bool enabled) {
+ settings_->SetAccessibilityEnabled(enabled);
+}
+
+bool WebSettingsImpl::GetAccessibilityEnabled() {
+ return settings_->GetAccessibilityEnabled();
+}
+#endif
+
} // namespace blink
bool TizenCompatibilityModeEnabled() const override;
#endif
+#if defined(TIZEN_ATK_SUPPORT)
+ void SetAccessibilityEnabled(bool) override;
+ bool GetAccessibilityEnabled() override;
+#endif
+
bool RenderVSyncNotificationEnabled() const {
return render_v_sync_notification_enabled_;
}
settings->SetDontSendKeyEventsToJavascript(
prefs.dont_send_key_events_to_javascript);
settings->SetWebAppScope(WebString::FromASCII(prefs.web_app_scope.spec()));
+#if defined(TIZEN_ATK_SUPPORT)
+ settings->SetAccessibilityEnabled(prefs.atk_enabled);
+#endif
#if BUILDFLAG(IS_EFL)
settings->SetTizenVersion(prefs.tizen_version_major,
ScriptState* script_state,
Element* element) {
DCHECK(element);
+#if defined(TIZEN_ATK_SUPPORT)
+ element->GetDocument().GetPage()->GetSettings().SetAccessibilityEnabled(true);
+#endif
auto* resolver = MakeGarbageCollected<ComputedAccessibleNodePromiseResolver>(
script_state, *element);
ScriptPromise promise = resolver->Promise();
bool TizenCompatibilityModeEnabled() const;
#endif
+#if defined(TIZEN_ATK_SUPPORT)
+ void SetAccessibilityEnabled(bool enabled) { atk_enabled_ = enabled; }
+
+ bool GetAccessibilityEnabled() { return atk_enabled_; }
+#endif
+
void SetDelegate(SettingsDelegate*);
private:
} tizen_compatibility_settings_;
#endif
+#if defined(TIZEN_ATK_SUPPORT)
+ bool atk_enabled_ : 1 = false;
+#endif
+
SETTINGS_MEMBER_VARIABLES
};
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/gfx/geometry/transform.h"
+#if defined(TIZEN_ATK_SUPPORT)
+#include "tizen/system_info.h"
+#endif
+
namespace {
// It is not easily possible to find out if an element is the target of an
if (IsPotentialInPageLinkTarget(*element))
return kIncludeObject;
+#if defined(TIZEN_ATK_SUPPORT)
+ if (IsMobileProfile() && IsA<HTMLSpanElement>(node)) {
+ return kIncludeObject;
+ } else if (IsA<HTMLSpanElement>(node)) {
+ if (ignored_reasons)
+ ignored_reasons->push_back(IgnoredReason(kAXUninteresting));
+ return kIgnoreObject;
+ }
+#else
// <span> tags are inline tags and not meant to convey information if they
// have no other ARIA information on them. If we don't ignore them, they may
// emit signals expected to come from their parent.
ignored_reasons->push_back(IgnoredReason(kAXUninteresting));
return kIgnoreObject;
}
+#endif
// Ignore labels that are already used to name a control.
// See IsRedundantLabel() for more commentary.
return ax::mojom::blink::Role::kTextField;
}
+#if defined(TIZEN_ATK_SUPPORT)
+ if (IsMobileProfile() && IsA<HTMLSpanElement>(*GetNode())) {
+ return ax::mojom::Role::kGroup;
+ }
+#endif
+
if (auto* select_element = DynamicTo<HTMLSelectElement>(*GetNode())) {
if (select_element->IsMultiple())
return ax::mojom::blink::Role::kListBox;
if (HeadingLevel())
return ax::mojom::blink::Role::kHeading;
- if (IsA<HTMLDivElement>(*GetNode()))
+ if (IsA<HTMLDivElement>(*GetNode())
+#if defined(TIZEN_ATK_SUPPORT) && !defined(TIZEN_ATK_FEATURE_VD)
+ && IsMobileProfile() &&
+ // Skip empty div tag in mobile and wearable profile.
+ (!ComputedName().empty() && HasAttribute(html_names::kRoleAttr) &&
+ (!GetAttribute(html_names::kAriaValuetextAttr).GetString().empty() ||
+ !GetValueForControl().empty()) &&
+ !GetAttribute(html_names::kAriaDescribedbyAttr).GetString().empty())
+#endif
+ ) {
return RoleFromLayoutObjectOrNode();
-
+ }
if (IsA<HTMLMenuElement>(*GetNode()) || IsA<HTMLUListElement>(*GetNode()) ||
IsA<HTMLOListElement>(*GetNode())) {
// <menu> is a deprecated feature of HTML 5, but is included for semantic
document->UpdateStyleAndLayoutTreeForNode(node);
+#if defined(TIZEN_ATK_SUPPORT)
+ if (!IsMobileProfile() && !CanSetFocusAttribute())
+ return false;
+#else
if (!CanSetFocusAttribute())
return false;
+#endif
if (IsWebArea()) {
// If another Frame has focused content (e.g. nested iframe), then we
}
bool AXObject::SupportsNameFromContents(bool recursive) const {
+#if defined(TIZEN_ATK_SUPPORT)
+ // From Tizen 3.0, use role="" for div to avoid speaking role name
+ // and at the same time get name from content
+ if (GetNode() && IsA<HTMLDivElement>(*GetNode()) &&
+ HasAttribute(html_names::kRoleAttr) &&
+ GetAttribute(html_names::kRoleAttr).empty()) {
+ return true;
+ }
+#endif
+
// ARIA 1.1, section 5.2.7.5.
bool result = false;
switch (RoleValue()) {
+#if defined(TIZEN_ATK_SUPPORT)
+ case ax::mojom::blink::Role::kUnknown:
+ return false;
+#endif
// ----- NameFrom: contents -------------------------
// Get their own name from contents, or contribute to ancestors
case ax::mojom::blink::Role::kButton:
case ax::mojom::blink::Role::kPdfRoot:
case ax::mojom::blink::Role::kTableHeaderContainer:
case ax::mojom::blink::Role::kTitleBar:
+#if !defined(TIZEN_ATK_SUPPORT)
case ax::mojom::blink::Role::kUnknown:
case ax::mojom::blink::Role::kWebView:
case ax::mojom::blink::Role::kWindow:
+#endif
NOTREACHED() << "Role shouldn't occur in Blink: " << ToString(true, true);
break;
}
config("ecore-evas-public") {
}
+config("atk") {
+ ldflags = [ "-latk-1.0" ]
+}
+
+tizen_pkg_config("libatk") {
+ packages = [ "atk" ]
+}
+
+config("atk-bridge") {
+ ldflags = [ "-latk-bridge-2.0" ]
+}
+
+tizen_pkg_config("libatk-bridge") {
+ packages = [ "atk-bridge-2.0" ]
+}
+
config("ecore-input") {
ldflags = [ "-lecore_input" ]
}
if (wayland_bringup) {
defines += [ "WAYLAND_BRINGUP" ]
}
+
+ if (tizen_atk_support) {
+ defines += [ "TIZEN_ATK_SUPPORT" ]
+ if (tizen_atk_feature_vd) {
+ defines += [ "TIZEN_ATK_FEATURE_VD" ]
+ }
+ }
+
if (tizen_product_tv) {
defines += [ "OS_TIZEN_TV_PRODUCT" ]
}
tizen_multimedia_eme_support = false
}
+if (use_atk) {
+ tizen_atk_support = true
+ if (tizen_product_tv) {
+ tizen_atk_feature_vd = true
+ } else {
+ tizen_atk_feature_vd = false
+ }
+} else {
+ tizen_atk_support = false
+ tizen_atk_feature_vd = false
+}
+
werror = false
# This file should contain gn code that is supposed to be common
"tracing/tracing_ui.h",
]
}
+
if (tizen_multimedia_support) {
external_content_browser_efl_sources += [
"//tizen_src/chromium_impl/content/browser/media/efl/browser_demuxer_efl.cc",
]
}
+if (tizen_atk_support) {
+ external_content_browser_efl_configs += [
+ "//tizen_src/build:atk",
+ "//tizen_src/build:libatk",
+ "//tizen_src/build:atk-bridge",
+ "//tizen_src/build:libatk-bridge",
+ ]
+}
+
if (tizen_multimedia) {
external_content_browser_efl_configs += [
"//tizen_src/build:esplusplayer",
--- /dev/null
+// Copyright (c) 2019 Samsung Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/accessibility/platform/ax_platform_node_efl.h"
+
+#include "base/strings/string_util.h"
+#include "tizen/system_info.h"
+#include "ui/accessibility/ax_node_data.h"
+#include "ui/display/device_display_info_efl.h"
+#include "ui/display/display.h"
+#include "ui/display/screen.h"
+#include "ui/gfx/geometry/dip_util.h"
+#include "ui/gfx/geometry/point.h"
+
+namespace ui {
+
+AXCoordinateSystem AXPlatformNodeEfl::preferred_ax_coordinate_system_ =
+ AXCoordinateSystem::kScreenPhysicalPixels;
+
+AXPlatformNode* AXPlatformNode::Create(AXPlatformNodeDelegate* delegate) {
+ AXPlatformNodeEfl* node = new AXPlatformNodeEfl();
+ node->Init(delegate);
+ return node;
+}
+
+AXPlatformNodeEfl* ToAXPlatformNodeEfl(AXPlatformNode* obj) {
+ DCHECK(!obj);
+ return static_cast<AXPlatformNodeEfl*>(obj);
+}
+
+AXPlatformNodeEfl* ToAXPlatformNodeEfl(AXPlatformNodeAuraLinux* obj) {
+ DCHECK(!obj);
+ return static_cast<AXPlatformNodeEfl*>(obj);
+}
+
+//
+// AtkText interface
+//
+
+static gchar* AxPlatformNodeGetText(AtkText* atk_text,
+ gint start_offset,
+ gint end_offset) {
+ g_return_val_if_fail(ATK_IS_TEXT(atk_text), nullptr);
+
+ AXPlatformNode* obj =
+ AXPlatformNode::FromNativeViewAccessible(ATK_OBJECT(atk_text));
+ if (!obj)
+ return nullptr;
+
+ return ToAXPlatformNodeEfl(obj)->GetObjectText();
+}
+
+static void TextInterfaceInit(AtkTextIface* iface) {
+ iface->get_text = AxPlatformNodeGetText;
+}
+
+static const GInterfaceInfo TextInfo = {
+ reinterpret_cast<GInterfaceInitFunc>(TextInterfaceInit), 0, 0};
+
+AXPlatformNodeEfl::AXPlatformNodeEfl() {}
+
+void AXPlatformNodeEfl::NotifyAccessibilityEvent(ax::mojom::Event event_type) {
+ AXPlatformNodeAuraLinux::NotifyAccessibilityEvent(event_type);
+
+ switch (event_type) {
+#if defined(TIZEN_ATK_FEATURE_VD) && !defined(EWK_BRINGUP)
+ case ax::mojom::Event::kLiveRegionChanged:
+ OnLiveRegionChanged();
+ break;
+#endif
+ case ax::mojom::Event::kFocus:
+ case ax::mojom::Event::kFocusContext:
+ OnFocused();
+ break;
+ case ax::mojom::Event::kSelection:
+ OnSelected();
+ // When changing tabs also fire a name changed event.
+ if (GetData().role == ax::mojom::Role::kTab)
+ OnDocumentTitleChanged();
+ break;
+ case ax::mojom::Event::kTextSelectionChanged:
+ OnTextSelectionChanged();
+ break;
+ case ax::mojom::Event::kValueChanged:
+ OnValueChanged();
+ break;
+ default:
+ break;
+ }
+}
+
+void AXPlatformNodeEfl::SetInterfaceFromObject(
+ GType type,
+ ui::ImplementedAtkInterfaces interface_mask) {
+ if (interface_mask_.Implements(ImplementedAtkInterfaces::Value::kText))
+ g_type_add_interface_static(type, ATK_TYPE_TEXT, &TextInfo);
+}
+
+void AXPlatformNodeEfl::SetInterfaceMaskFromObject(
+ ui::ImplementedAtkInterfaces& interface_mask) {
+ // AX_ATTR_NAME attribute value which contains link or heading contents will
+ // be read by screen-reader anyway as it is returned from get_name atk
+ // interface.
+ switch (GetData().role) {
+ case ax::mojom::Role::kHeading:
+ case ax::mojom::Role::kLink:
+ return;
+ }
+ if (IsTextObjectType() || IsColorWell() || IsSection())
+ interface_mask.Add(ImplementedAtkInterfaces::Value::kText);
+
+ // FIXME ATK_EDITABLE_TEXT_INTERFACE is removed
+#if !defined(EWK_BRINGUP)
+ if (GetData().role == ax::mojom::Role::kTextField)
+ interface_mask |= 1 << ATK_EDITABLE_TEXT_INTERFACE;
+#endif
+}
+
+bool AXPlatformNodeEfl::IsColorWell() const {
+ return GetData().role == ax::mojom::Role::kColorWell;
+}
+
+bool AXPlatformNodeEfl::IsChecked() const {
+ return GetData().GetCheckedState() == ax::mojom::CheckedState::kTrue;
+}
+
+bool AXPlatformNodeEfl::IsCheckable() const {
+ return GetData().HasIntAttribute(ax::mojom::IntAttribute::kCheckedState);
+}
+
+bool AXPlatformNodeEfl::IsStaticText() const {
+ return GetData().role == ax::mojom::Role::kStaticText;
+}
+
+bool AXPlatformNodeEfl::IsTextObjectType() const {
+ switch (GetData().role) {
+ case ax::mojom::Role::kHeading:
+ case ax::mojom::Role::kLink:
+ case ax::mojom::Role::kParagraph:
+ case ax::mojom::Role::kPopUpButton:
+ case ax::mojom::Role::kStaticText:
+ case ax::mojom::Role::kTextField:
+ case ax::mojom::Role::kInlineTextBox:
+ return true;
+ default:
+ return false;
+ }
+ return false;
+}
+
+bool AXPlatformNodeEfl::IsSection() const {
+ switch (GetData().role) {
+ case ax::mojom::Role::kGroup:
+ case ax::mojom::Role::kGenericContainer:
+ return true;
+ default:
+ return false;
+ }
+}
+
+gchar* AXPlatformNodeEfl::GetObjectText() const {
+ // For color inputs, return string with attributes
+ if (IsColorWell()) {
+ int color = GetData().GetIntAttribute(ax::mojom::IntAttribute::kColorValue);
+ int red = (color >> 16) & 0xFF;
+ int green = (color >> 8) & 0xFF;
+ int blue = color & 0xFF;
+ return g_strdup_printf("rgb %7.5f %7.5f %7.5f 1", red / 255., green / 255.,
+ blue / 255.);
+ }
+
+#if defined(TIZEN_ATK_FEATURE_VD)
+ if (IsTvProfile())
+ return g_strdup(GetSupplementaryText().c_str());
+#endif
+
+ // Always prefer value first
+ std::string text =
+ GetData().GetStringAttribute(ax::mojom::StringAttribute::kValue);
+ if (!text.empty())
+ return g_strdup(text.c_str());
+ if ((GetData().role == ax::mojom::Role::kTextField) &&
+ GetData().GetHtmlAttribute("placeholder", &text)) {
+ if (!text.empty())
+ return g_strdup(text.c_str());
+ }
+ text = GetData().GetStringAttribute(ax::mojom::StringAttribute::kDescription);
+ if (!text.empty())
+ return g_strdup(text.c_str());
+
+ return g_strdup(GetObjectValue().c_str());
+}
+
+std::string AXPlatformNodeEfl::GetObjectValue() const {
+ std::string value =
+ GetData().GetStringAttribute(ax::mojom::StringAttribute::kValue);
+ if (!value.empty())
+ return value;
+ for (uint32_t i = 0; i < GetChildCount(); i++) {
+ AXPlatformNodeEfl* obj = ToAXPlatformNodeEfl(
+ AXPlatformNode::FromNativeViewAccessible(ChildAtIndex(i)));
+ if (obj) {
+ std::string child_value = obj->GetObjectValue();
+ if (value.length() > 0 &&
+ !base::IsAsciiWhitespace(value[value.length() - 1]) &&
+ (!child_value.empty() && !base::IsAsciiWhitespace(child_value[0])))
+ value += " ";
+ value += child_value;
+ }
+ }
+ return value;
+}
+
+void AXPlatformNodeEfl::RecalculateHighlightableSingle() {
+ AtkObject* atk_obj = GetAtkObject();
+ if (atk_obj)
+ highlightable_ = IsAccessible();
+}
+
+bool AXPlatformNodeEfl::IsUnknown() const {
+ return GetData().role == ax::mojom::Role::kUnknown;
+}
+
+bool AXPlatformNodeEfl::IsInlineTextBox() const {
+ return GetData().role == ax::mojom::Role::kInlineTextBox;
+}
+
+bool AXPlatformNodeEfl::IsFocusable() const {
+ return GetData().HasState(ax::mojom::State::kFocusable);
+}
+
+bool AXPlatformNodeEfl::HasTextValue() const {
+ if (IsTextObjectType() &&
+ !GetData().GetStringAttribute(ax::mojom::StringAttribute::kValue).empty())
+ return true;
+
+ for (int i = 0; i < GetChildCount(); i++) {
+ AXPlatformNodeEfl* obj = ToAXPlatformNodeEfl(
+ AXPlatformNode::FromNativeViewAccessible(ChildAtIndex(i)));
+ if (obj && obj->HasTextValue())
+ return true;
+ }
+ return false;
+}
+
+bool AXPlatformNodeEfl::HasText() const {
+ std::string text =
+ GetData().GetStringAttribute(ax::mojom::StringAttribute::kValue);
+ if (!text.empty())
+ return true;
+
+ std::string description =
+ GetData().GetStringAttribute(ax::mojom::StringAttribute::kDescription);
+ if (!description.empty())
+ return true;
+
+ for (int i = 0; i < GetChildCount(); i++) {
+ AXPlatformNodeEfl* obj = ToAXPlatformNodeEfl(
+ AXPlatformNode::FromNativeViewAccessible(ChildAtIndex(i)));
+ if (obj && obj->HasTextValue())
+ return true;
+ }
+ return false;
+}
+
+bool AXPlatformNodeEfl::MoreThanOneKnownChild() const {
+ int count = 0;
+ for (int i = 0; i < GetChildCount(); i++) {
+ AXPlatformNodeEfl* obj = ToAXPlatformNodeEfl(
+ AXPlatformNode::FromNativeViewAccessible(ChildAtIndex(i)));
+ if (obj && (obj->IsUnknown() ||
+ obj->GetData().role == ax::mojom::Role::kLineBreak))
+ continue;
+ ++count;
+ if (count > 1)
+ return true;
+ }
+ return false;
+}
+
+bool AXPlatformNodeEfl::IsDocument() const {
+ switch (GetData().role) {
+ case ax::mojom::Role::kDocument:
+ case ax::mojom::Role::kRootWebArea:
+ case ax::mojom::Role::kPdfRoot:
+ return true;
+ }
+ return false;
+}
+
+bool AXPlatformNodeEfl::IsAccessible() const {
+ if (IsUnknown())
+ return false;
+ if (IsFocusable())
+ return true;
+ // Text object types are accessible for its direct reading purpose, while
+ // sections allow to group accessible nodes for better ui experiance.
+ if (!IsTextObjectType() && !IsSection())
+ return false;
+ // There is no need to group only one child (skipping unknown ones).
+ if (IsSection() && !MoreThanOneKnownChild())
+ return false;
+ // Some text object may be empty.
+ if (!HasText())
+ return false;
+ // We continue further check on parent as static text can be grouped.
+ if (!IsStaticText() && !IsInlineTextBox())
+ return true;
+
+ // Check if parent can be a grouper of static text. If not then static text
+ // is accessible.
+ gfx::NativeViewAccessible parent = GetParent();
+ if (!parent)
+ return false;
+ AXPlatformNodeEfl* parent_efl =
+ ToAXPlatformNodeEfl(AXPlatformNode::FromNativeViewAccessible(parent));
+ if (!parent_efl)
+ return false;
+ if (parent_efl->IsUnknown())
+ return true;
+ // Don't let document be grouping object
+ if (parent_efl->IsDocument())
+ return true;
+ if (parent_efl->IsFocusable())
+ return false;
+ if (!parent_efl->IsTextObjectType() && !parent_efl->IsSection())
+ return true;
+ if (parent_efl->IsSection() && !parent_efl->MoreThanOneKnownChild())
+ return true;
+ return false;
+}
+
+#if defined(TIZEN_ATK_FEATURE_VD)
+std::string AXPlatformNodeEfl::GetSupplementaryText() const {
+ // name and description have been got from BrowserAccessibilityAuraLinux
+ // if return here again, it will be speak twice
+ if (!GetData()
+ .GetStringAttribute(ax::mojom::StringAttribute::kName)
+ .empty() ||
+ !GetData()
+ .GetStringAttribute(ax::mojom::StringAttribute::kDescription)
+ .empty())
+ return std::string();
+
+ // Always prefer value first
+ std::string text =
+ GetData().GetStringAttribute(ax::mojom::StringAttribute::kValue);
+ if (!text.empty())
+ return text;
+
+ if ((GetData().role == ax::mojom::Role::kTextField) &&
+ GetData().GetHtmlAttribute("placeholder", &text)) {
+ if (!text.empty())
+ return text;
+ }
+
+ if (HasOnlyTextChildren() ||
+ (IsFocusable() && HasOnlyTextAndImageChildren())) {
+ text.append(GetChildrenText());
+ if (!text.empty())
+ return text;
+ }
+
+ return GetObjectValue();
+}
+
+std::string AXPlatformNodeEfl::GetChildrenText() const {
+ std::string text;
+ for (uint32_t i = 0; i < GetChildCount(); i++) {
+ AXPlatformNodeEfl* obj = ToAXPlatformNodeEfl(
+ AXPlatformNode::FromNativeViewAccessible(ChildAtIndex(i)));
+ if (obj) {
+ std::string name =
+ obj->GetData().GetStringAttribute(ax::mojom::StringAttribute::kName);
+ if (!text.empty() && !name.empty())
+ text.append(" ");
+ text.append(name);
+
+ std::string description = obj->GetData().GetStringAttribute(
+ ax::mojom::StringAttribute::kDescription);
+ if (!text.empty() && !description.empty())
+ text.append(" ");
+ text.append(description);
+
+ std::string supplementary = obj->GetSupplementaryText();
+ if (!text.empty() && !supplementary.empty())
+ text.append(" ");
+ text.append(supplementary);
+ }
+ }
+ return text;
+}
+
+bool AXPlatformNodeEfl::HasOnlyTextChildren() const {
+ for (uint32_t i = 0; i < GetChildCount(); i++) {
+ AXPlatformNodeEfl* obj = ToAXPlatformNodeEfl(
+ AXPlatformNode::FromNativeViewAccessible(ChildAtIndex(i)));
+ if (obj && !obj->IsTextObjectType())
+ return false;
+ }
+ return true;
+}
+
+bool AXPlatformNodeEfl::HasOnlyTextAndImageChildren() const {
+ for (uint32_t i = 0; i < GetChildCount(); i++) {
+ AXPlatformNodeEfl* obj = ToAXPlatformNodeEfl(
+ AXPlatformNode::FromNativeViewAccessible(ChildAtIndex(i)));
+ if (obj && !obj->IsTextObjectType() &&
+ obj->GetData().role != ax::mojom::Role::kImage)
+ return false;
+ }
+ return true;
+}
+
+bool AXPlatformNodeEfl::HasSpeechContent() {
+ if (!GetData()
+ .GetStringAttribute(ax::mojom::StringAttribute::kName)
+ .empty() ||
+ !GetData()
+ .GetStringAttribute(ax::mojom::StringAttribute::kDescription)
+ .empty())
+ return true;
+
+ ImplementedAtkInterfaces mask;
+ mask.Add(ImplementedAtkInterfaces::Value::kDefault);
+ SetInterfaceMaskFromObject(mask);
+ return (interface_mask_.Implements(ImplementedAtkInterfaces::Value::kText) &&
+ !GetSupplementaryText().empty())
+ ? true
+ : false;
+}
+
+std::string AXPlatformNodeEfl::GetSpeechContent() {
+ std::string result;
+ if (!GetData()
+ .GetStringAttribute(ax::mojom::StringAttribute::kName)
+ .empty()) {
+ result.append(
+ GetData().GetStringAttribute(ax::mojom::StringAttribute::kName));
+ result.append(" ");
+ }
+
+ if (!GetData()
+ .GetStringAttribute(ax::mojom::StringAttribute::kDescription)
+ .empty()) {
+ result.append(
+ GetData().GetStringAttribute(ax::mojom::StringAttribute::kDescription));
+ result.append(" ");
+ }
+
+ ImplementedAtkInterfaces mask;
+ mask.Add(ImplementedAtkInterfaces::Value::kDefault);
+ SetInterfaceMaskFromObject(mask);
+ if (interface_mask_.Implements(ImplementedAtkInterfaces::Value::kText) &&
+ !GetSupplementaryText().empty()) {
+ result.append(GetSupplementaryText());
+ result.append(" ");
+ }
+
+ return result;
+}
+std::string AXPlatformNodeEfl::GetSubTreeSpeechContent() const {
+ std::string result;
+
+ // if name from contents, will get it from children
+ if (static_cast<ax::mojom::NameFrom>(
+ GetData().GetIntAttribute(ax::mojom::IntAttribute::kNameFrom)) !=
+ ax::mojom::NameFrom::kContents &&
+ !GetData()
+ .GetStringAttribute(ax::mojom::StringAttribute::kName)
+ .empty()) {
+ result.append(
+ GetData().GetStringAttribute(ax::mojom::StringAttribute::kName));
+ result.append(" ");
+ }
+
+ if (!GetData()
+ .GetStringAttribute(ax::mojom::StringAttribute::kDescription)
+ .empty()) {
+ result.append(
+ GetData().GetStringAttribute(ax::mojom::StringAttribute::kDescription));
+ result.append(" ");
+ }
+
+ for (uint32_t i = 0; i < GetChildCount(); i++) {
+ AXPlatformNodeEfl* obj = ToAXPlatformNodeEfl(
+ AXPlatformNode::FromNativeViewAccessible(ChildAtIndex(i)));
+ if (obj) {
+ std::string child_string = obj->GetSpeechContent();
+ if (!result.empty() && !child_string.empty())
+ result.append(" ");
+ result.append(child_string);
+ }
+ }
+
+ return result;
+}
+#endif
+
+} // namespace ui
--- /dev/null
+// Copyright (c) 2019 Samsung Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <atk/atk.h>
+
+#include "ui/accessibility/ax_coordinate_system.h"
+#include "ui/accessibility/ax_export.h"
+#include "ui/accessibility/platform/ax_platform_node_auralinux.h"
+#include "ui/accessibility/platform/ax_platform_node_base.h"
+
+namespace ui {
+// Implements accessibility on Aura Linux using ATK.
+class AX_EXPORT AXPlatformNodeEfl : public AXPlatformNodeAuraLinux {
+ public:
+ AXPlatformNodeEfl();
+ ~AXPlatformNodeEfl() {}
+
+ AXPlatformNodeEfl(const AXPlatformNodeEfl&) = delete;
+ AXPlatformNodeEfl& operator=(const AXPlatformNodeEfl&) = delete;
+
+ // AXPlatformNode overrides.
+ void NotifyAccessibilityEvent(ax::mojom::Event event_type) override;
+
+ void RecalculateHighlightableSingle();
+ bool IsChecked() const;
+ bool IsCheckable() const;
+ bool IsColorWell() const;
+ bool Ishighlightable() const { return highlightable_; }
+ bool IsStaticText() const;
+ bool IsTextObjectType() const;
+
+ void SetInterfaceFromObject(GType, ui::ImplementedAtkInterfaces);
+ void SetInterfaceMaskFromObject(ui::ImplementedAtkInterfaces&);
+ gchar* GetObjectText() const;
+ bool IsAccessible() const;
+#if defined(TIZEN_ATK_FEATURE_VD)
+ std::string GetSupplementaryText() const;
+ std::string GetSubTreeSpeechContent() const;
+ std::string GetSpeechContent();
+ bool HasSpeechContent();
+#endif
+
+ static AXCoordinateSystem GetPreferredAXCoordinateSystem() {
+ return preferred_ax_coordinate_system_;
+ }
+
+ private:
+ bool MoreThanOneKnownChild() const;
+ bool IsDocument() const;
+ bool IsFocusable() const;
+ bool IsInlineTextBox() const;
+ bool IsSection() const;
+ bool IsUnknown() const;
+ bool HasTextValue() const;
+ bool HasText() const;
+ std::string GetObjectValue() const;
+#if defined(TIZEN_ATK_FEATURE_VD)
+ bool HasOnlyTextChildren() const;
+ bool HasOnlyTextAndImageChildren() const;
+ std::string GetChildrenText() const;
+#endif
+
+ bool highlightable_ = false;
+ static AXCoordinateSystem preferred_ax_coordinate_system_;
+};
+
+} // namespace ui
[ "gesture_detection/gesture_configuration_default.cc" ]
external_ui_gesture_detection_sources += [ "//tizen_src/chromium_impl/ui/events/gesture_detection/gesture_configuration_efl.cc" ]
}
+
+external_ui_accessiblility_platform_sources = [
+ "//tizen_src/chromium_impl/ui/accessibility/platform/ax_platform_node_efl.cc",
+ "//tizen_src/chromium_impl/ui/accessibility/platform/ax_platform_node_efl.h",
+]
\ No newline at end of file
"wrt/wrtwidget.h",
]
+ if (tizen_atk_support) {
+ configs += [ "//tizen_src/build:atk" ]
+ configs += [ "//tizen_src/build:libatk" ]
+ configs += [ "//tizen_src/build:atk-bridge" ]
+ configs += [ "//tizen_src/build:libatk-bridge" ]
+ sources += [
+ "eweb_accessibility.cc",
+ "eweb_accessibility.h",
+ "eweb_accessibility_object.cc",
+ "eweb_accessibility_object.h",
+ "eweb_accessibility_util.cc",
+ "eweb_accessibility_util.h",
+ ]
+ }
+
if (tizen_product_tv) {
sources += [
"common/application_type.cc",
--- /dev/null
+// Copyright 2015-17 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "eweb_accessibility.h"
+
+#include <atk-bridge.h>
+
+#include "base/logging.h"
+#include "content/browser/accessibility/browser_accessibility_state_impl.h"
+#include "eweb_accessibility_util.h"
+#include "tizen/system_info.h"
+
+static const char* const kPlugIdKey = "__PlugID";
+
+EWebAccessibility::EWebAccessibility(Evas_Object* root_object,
+ content::WebContents* web_contents,
+ std::unique_ptr<Observer> observer)
+ : root_object_(root_object),
+ web_contents_(web_contents),
+ observer_(std::move(observer)) {}
+
+EWebAccessibility::~EWebAccessibility() {}
+
+AtkObject* EWebAccessibility::GetRootObject() {
+ if (!IsMobileProfile())
+ return nullptr;
+
+ if (!accessibility_object_)
+ accessibility_object_.reset(new EWebAccessibilityObject(web_contents_));
+ return ATK_OBJECT(accessibility_object_->GetEflAtkObject());
+}
+
+void EWebAccessibility::OnFocusOut() {
+ if (!IsMobileProfile())
+ return;
+
+ if (!accessibility_object_)
+ return;
+
+ accessibility_object_->InvalidateHighlighted(true);
+}
+
+void EWebAccessibility::AddPlug() {
+ if (!IsMobileProfile())
+ return;
+
+ if (!accessibility_object_)
+ accessibility_object_.reset(new EWebAccessibilityObject(web_contents_));
+
+ auto plug_id =
+ atk_plug_get_id(ATK_PLUG(accessibility_object_->GetEflAtkObject()));
+ if (plug_id) {
+ auto data = evas_object_data_get(root_object_, kPlugIdKey);
+ if (data && !strcmp((char*)plug_id, (char*)data))
+ return;
+
+ evas_object_data_set(root_object_, kPlugIdKey, strdup(plug_id));
+ LOG(INFO) << "Web accessibility address was set to " << plug_id;
+ } else if (accessibility_object_) {
+ accessibility_object_.reset();
+ atk_bridge_adaptor_cleanup();
+ LOG(ERROR) << "atk_plug_get_id failed.";
+ }
+}
+
+void EWebAccessibility::RemovePlug() {
+ if (!IsMobileProfile())
+ return;
+
+ auto plug_id =
+ static_cast<char*>(evas_object_data_get(root_object_, kPlugIdKey));
+ if (plug_id) {
+ evas_object_data_set(root_object_, kPlugIdKey, nullptr);
+ free(plug_id);
+ }
+ accessibility_object_.reset();
+}
+
+void EWebAccessibility::NotifyAccessibilityStatus(bool is_enabled) {
+ if (IsMobileProfile())
+ (is_enabled) ? AddPlug() : RemovePlug();
+
+ if (observer_) {
+ observer_->OnSpatialNavigationStatusChanged(is_enabled);
+ observer_->OnAccessibilityStatusChanged(is_enabled);
+ }
+}
--- /dev/null
+// Copyright 2015-17 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EWEB_ACCESSIBILITY_H
+#define EWEB_ACCESSIBILITY_H
+
+#include <Ecore_Evas.h>
+#include <memory>
+#include "eweb_accessibility_object.h"
+
+namespace content {
+class WebContents;
+}
+
+// pre-conditions:
+// |ecore_main_loop| SHOULD be running before using this class.
+//
+// This class initializes and owns all accessibility objects.
+class EWebAccessibility {
+ public:
+ class Observer {
+ public:
+ virtual ~Observer() {}
+
+ virtual void OnSpatialNavigationStatusChanged(Eina_Bool enable) = 0;
+
+ virtual void OnAccessibilityStatusChanged(Eina_Bool enable) = 0;
+ };
+
+ EWebAccessibility(Evas_Object* root_object,
+ content::WebContents* web_contents,
+ std::unique_ptr<Observer> observer);
+ ~EWebAccessibility();
+
+ EWebAccessibility(const EWebAccessibility&) = delete;
+ EWebAccessibility& operator=(const EWebAccessibility&) = delete;
+
+ void NotifyAccessibilityStatus(bool);
+ AtkObject* GetRootObject();
+ void OnFocusOut();
+
+ private:
+ void AddPlug();
+ void RemovePlug();
+
+ Evas_Object* root_object_;
+ content::WebContents* web_contents_;
+ std::unique_ptr<Observer> observer_;
+
+ std::unique_ptr<EWebAccessibilityObject> accessibility_object_;
+};
+
+#endif // EWEB_ACCESSIBILITY_H
--- /dev/null
+// Copyright 2015-17 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "eweb_accessibility_object.h"
+
+#include "content/browser/accessibility/browser_accessibility.h"
+#include "content/browser/accessibility/browser_accessibility_auralinux.h"
+#include "content/browser/accessibility/browser_accessibility_manager_auralinux.h"
+#include "content/browser/renderer_host/render_frame_host_impl.h"
+#include "content/browser/web_contents/web_contents_impl_efl.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/web_contents.h"
+#include "tizen/system_info.h"
+#include "ui/accessibility/platform/ax_platform_node_auralinux.h"
+
+static const char* const kWebViewAccessibilityObjectName = "eweb accessibility";
+static const char* const kWebViewAccessibilityObjectDescription =
+ "chromium-efl accessibility for webview";
+
+struct _WebViewAccessibilityObjectPrivate {
+ EWebAccessibilityObject* m_object;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE(WebViewAccessibilityObject,
+ web_view_accessibility_object,
+ ATK_TYPE_PLUG)
+
+static void web_view_accessibility_object_init(
+ WebViewAccessibilityObject* accessible) {
+ accessible->priv = static_cast<_WebViewAccessibilityObjectPrivate*>(
+ web_view_accessibility_object_get_instance_private(accessible));
+}
+
+static void web_view_accessibility_object_initialize(AtkObject* atk_object,
+ gpointer data) {
+ if (ATK_OBJECT_CLASS(web_view_accessibility_object_parent_class)
+ ->initialize) {
+ ATK_OBJECT_CLASS(web_view_accessibility_object_parent_class)
+ ->initialize(atk_object, data);
+ }
+ WEB_VIEW_ACCESSIBILITY_OBJECT(atk_object)->priv->m_object =
+ reinterpret_cast<EWebAccessibilityObject*>(data);
+}
+
+static void web_view_accessibility_object_finalize(GObject* atk_object) {
+ G_OBJECT_CLASS(web_view_accessibility_object_parent_class)
+ ->finalize(atk_object);
+}
+
+static EWebAccessibilityObject* ToEWebAccessibilityObject(
+ AtkObject* atk_object) {
+ if (!atk_object) {
+ LOG(ERROR) << "atk_object is null";
+ return nullptr;
+ }
+
+ if (!IS_WEB_VIEW_ACCESSIBILITY_OBJECT(atk_object)) {
+ LOG(ERROR) << "atk_object is not webview accessibility object";
+ return nullptr;
+ }
+
+ WebViewAccessibilityObject* ax_object =
+ WEB_VIEW_ACCESSIBILITY_OBJECT(atk_object);
+ return ax_object->priv->m_object;
+}
+
+static gint web_view_accessibility_object_get_index_in_parent(
+ AtkObject* atk_object) {
+ g_return_val_if_fail(IS_WEB_VIEW_ACCESSIBILITY_OBJECT(atk_object), -1);
+ auto obj = ToEWebAccessibilityObject(atk_object);
+ return obj->GetIndexInParent();
+}
+
+static gint web_view_accessibility_object_get_n_children(
+ AtkObject* atk_object) {
+ g_return_val_if_fail(IS_WEB_VIEW_ACCESSIBILITY_OBJECT(atk_object), -1);
+ auto obj = ToEWebAccessibilityObject(atk_object);
+ return obj->GetNChildren();
+}
+
+static AtkObject* web_view_accessibility_object_ref_child(AtkObject* atk_object,
+ gint index) {
+ g_return_val_if_fail(IS_WEB_VIEW_ACCESSIBILITY_OBJECT(atk_object), nullptr);
+ auto obj = ToEWebAccessibilityObject(atk_object);
+ return obj->RefChild(index);
+}
+
+static const gchar* web_view_accessibility_object_get_name(
+ AtkObject* atk_object) {
+ return kWebViewAccessibilityObjectName;
+}
+
+static const gchar* web_view_accessibility_object_get_description(
+ AtkObject* atk_object) {
+ return kWebViewAccessibilityObjectDescription;
+}
+
+static AtkStateSet* web_view_accessibility_object_ref_state_set(
+ AtkObject* atk_object) {
+ g_return_val_if_fail(IS_WEB_VIEW_ACCESSIBILITY_OBJECT(atk_object), nullptr);
+ auto obj = ToEWebAccessibilityObject(atk_object);
+ return obj->RefStateSet();
+}
+
+static void web_view_accessibility_object_class_init(
+ WebViewAccessibilityObjectClass* klass) {
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+ AtkObjectClass* atkObjectClass = ATK_OBJECT_CLASS(klass);
+ gobject_class->finalize = web_view_accessibility_object_finalize;
+ atkObjectClass->initialize = web_view_accessibility_object_initialize;
+ atkObjectClass->get_index_in_parent =
+ web_view_accessibility_object_get_index_in_parent;
+ atkObjectClass->get_n_children = web_view_accessibility_object_get_n_children;
+ atkObjectClass->ref_child = web_view_accessibility_object_ref_child;
+ atkObjectClass->get_name = web_view_accessibility_object_get_name;
+ atkObjectClass->get_description =
+ web_view_accessibility_object_get_description;
+ atkObjectClass->ref_state_set = web_view_accessibility_object_ref_state_set;
+}
+
+static AtkObject* web_view_accessibility_object_ref_accessible_at_point(
+ AtkComponent* component,
+ gint x,
+ gint y,
+ AtkCoordType coord_type) {
+ auto obj = ToEWebAccessibilityObject(ATK_OBJECT(component));
+ return obj->RefAccessibleAtPoint(x, y, coord_type);
+}
+
+static void web_view_accessibility_object_get_extents(AtkComponent* component,
+ gint* x,
+ gint* y,
+ gint* width,
+ gint* height,
+ AtkCoordType coord_type) {
+ auto obj = ToEWebAccessibilityObject(ATK_OBJECT(component));
+ if (ATK_XY_SCREEN) {
+ obj->GetScreenGeometry(x, y, width, height);
+ } else { // ATK_XY_WINDOW
+ obj->GetWindowGeometry(x, y, width, height);
+ }
+}
+
+static void web_view_accessibility_object_get_position(
+ AtkComponent* component,
+ gint* x,
+ gint* y,
+ AtkCoordType coord_type) {
+ auto obj = ToEWebAccessibilityObject(ATK_OBJECT(component));
+ if (ATK_XY_SCREEN) {
+ obj->GetScreenGeometry(x, y, nullptr, nullptr);
+ } else { // ATK_XY_WINDOW
+ obj->GetWindowGeometry(x, y, nullptr, nullptr);
+ }
+}
+
+static void web_view_accessibility_object_get_size(AtkComponent* component,
+ gint* width,
+ gint* height) {
+ auto obj = ToEWebAccessibilityObject(ATK_OBJECT(component));
+ obj->GetWindowGeometry(nullptr, nullptr, width, height);
+}
+
+EWebAccessibilityObject::EWebAccessibilityObject(
+ content::WebContents* web_contents)
+ : web_contents_(web_contents),
+ native_view_(static_cast<content::WebContentsImplEfl*>(web_contents_)
+ ->GetEflNativeView()) {
+ evas_object_event_callback_add(native_view_, EVAS_CALLBACK_SHOW,
+ NativeViewShowCallback, this);
+ evas_object_event_callback_add(native_view_, EVAS_CALLBACK_HIDE,
+ NativeViewHideCallback, this);
+ efl_atk_obj_ = static_cast<AtkObject*>(
+ g_object_new(WEB_VIEW_ACCESSIBILITY_OBJECT_TYPE, nullptr));
+
+ // init
+ atk_object_initialize(efl_atk_obj_, this);
+ AtkComponent* component = ATK_COMPONENT(efl_atk_obj_);
+
+ AtkComponentIface* iface = ATK_COMPONENT_GET_IFACE(component);
+ iface->ref_accessible_at_point =
+ web_view_accessibility_object_ref_accessible_at_point;
+ iface->get_extents = web_view_accessibility_object_get_extents;
+ iface->get_position = web_view_accessibility_object_get_position;
+ iface->get_size = web_view_accessibility_object_get_size;
+
+ // Set the root atk object to BrowserAccessibilityAuraLinux(delegate)
+ // to access it from the ui/accessibility layer.
+ if (GetRootObject())
+ GetRootObject()->SetRootAtkObject(efl_atk_obj_);
+}
+
+EWebAccessibilityObject::~EWebAccessibilityObject() {
+ evas_object_event_callback_del(native_view_, EVAS_CALLBACK_SHOW,
+ NativeViewShowCallback);
+ evas_object_event_callback_del(native_view_, EVAS_CALLBACK_HIDE,
+ NativeViewHideCallback);
+ g_object_unref(efl_atk_obj_);
+}
+
+// static
+void EWebAccessibilityObject::NativeViewShowCallback(void* data,
+ Evas*,
+ Evas_Object*,
+ void*) {
+ auto thiz = static_cast<EWebAccessibilityObject*>(data);
+ atk_object_notify_state_change(ATK_OBJECT(thiz->GetEflAtkObject()),
+ ATK_STATE_SHOWING, TRUE);
+}
+
+// static
+void EWebAccessibilityObject::NativeViewHideCallback(void* data,
+ Evas*,
+ Evas_Object*,
+ void*) {
+ auto thiz = static_cast<EWebAccessibilityObject*>(data);
+ atk_object_notify_state_change(ATK_OBJECT(thiz->GetEflAtkObject()),
+ ATK_STATE_SHOWING, FALSE);
+}
+
+content::BrowserAccessibilityManager*
+EWebAccessibilityObject::GetBrowserAccessibilityManager() const {
+ auto frame = static_cast<content::RenderFrameHostImpl*>(
+ web_contents_->GetPrimaryMainFrame());
+ if (!frame) {
+ LOG(ERROR) << "Unable to get render frame host impl";
+ return nullptr;
+ }
+ return frame->GetOrCreateBrowserAccessibilityManager();
+}
+
+AtkObject* EWebAccessibilityObject::RefAccessibleAtPoint(
+ gint x,
+ gint y,
+ AtkCoordType coord_type) {
+ auto child = GetAtkObject();
+ if (!child) {
+ LOG(ERROR) << "Child was not found";
+ return nullptr;
+ }
+ return atk_component_ref_accessible_at_point(ATK_COMPONENT(child), x, y,
+ coord_type);
+}
+
+void EWebAccessibilityObject::GetScreenGeometry(int* x,
+ int* y,
+ int* width,
+ int* height) const {
+ auto ee = ecore_evas_ecore_evas_get(evas_object_evas_get(native_view_));
+ ecore_evas_screen_geometry_get(ee, x, y, width, height);
+}
+
+void EWebAccessibilityObject::GetWindowGeometry(int* x,
+ int* y,
+ int* width,
+ int* height) const {
+ evas_object_geometry_get(native_view_, x, y, width, height);
+}
+
+gint EWebAccessibilityObject::GetIndexInParent() const {
+ // AtkPlug is the only child of AtkSocket.
+ return 0;
+}
+
+gint EWebAccessibilityObject::GetNChildren() const {
+ // One and only child of AtkPlug is the browser root accessibility object.
+ auto child = GetAtkObject();
+ if (!child) {
+ LOG(ERROR) << "Child was not found";
+ return 0;
+ }
+ return 1;
+}
+
+AtkObject* EWebAccessibilityObject::RefChild(gint index) const {
+ if (index != 0) {
+ LOG(ERROR) << "Invalid index passed: " << index;
+ return nullptr;
+ }
+
+ auto child = GetAtkObject();
+ if (!child) {
+ LOG(ERROR) << "Child was not found";
+ return nullptr;
+ }
+
+ g_object_ref(child);
+ return child;
+}
+
+AtkStateSet* EWebAccessibilityObject::RefStateSet() const {
+ auto atk_state_set = atk_state_set_new();
+ if (evas_object_visible_get(native_view_))
+ atk_state_set_add_state(atk_state_set, ATK_STATE_SHOWING);
+ return atk_state_set;
+}
+
+AtkObject* EWebAccessibilityObject::GetEflAtkObject() const {
+ return efl_atk_obj_;
+}
+
+content::BrowserAccessibilityAuraLinux* EWebAccessibilityObject::GetRootObject()
+ const {
+ auto manager = GetBrowserAccessibilityManager();
+ if (!manager) {
+ LOG(ERROR) << "Unable to get accessibility manager";
+ return nullptr;
+ }
+
+ content::BrowserAccessibility* obj =
+ static_cast<content::BrowserAccessibility*>(manager->RootDelegate());
+ if (!obj) {
+ LOG(ERROR) << "Unable to get root object from accessibility manager";
+ return nullptr;
+ }
+ content::BrowserAccessibilityAuraLinux* root_object =
+ ToBrowserAccessibilityAuraLinux(obj);
+
+ return root_object;
+}
+
+ui::AXPlatformNodeAuraLinux* EWebAccessibilityObject::GetNode() const {
+ auto root_object = GetRootObject();
+ if (!root_object)
+ return nullptr;
+
+ auto node = root_object->GetNode();
+ if (!node) {
+ LOG(ERROR) << "Unable to get auralinux node";
+ return nullptr;
+ }
+
+ return node;
+}
+
+AtkObject* EWebAccessibilityObject::GetAtkObject() const {
+ auto node = GetNode();
+ return (node) ? node->GetAtkObject() : nullptr;
+}
+
+void EWebAccessibilityObject::InvalidateHighlighted(bool focus) {
+ auto node = GetNode();
+ if (node)
+ node->InvalidateHighlighted(focus);
+}
--- /dev/null
+// Copyright 2015-17 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EWEB_ACCESSIBILITY_OBJECT_H
+#define EWEB_ACCESSIBILITY_OBJECT_H
+
+#include <Ecore_Evas.h>
+#include <atk/atk.h>
+
+namespace ui {
+class AXPlatformNodeAuraLinux;
+}
+
+namespace content {
+class BrowserAccessibility;
+class BrowserAccessibilityManager;
+class BrowserAccessibilityAuraLinux;
+class BrowserAccessibilityManagerAuraLinux;
+class BrowserAccessibilityManager;
+class WebContents;
+} // namespace content
+
+G_BEGIN_DECLS
+
+#define WEB_VIEW_ACCESSIBILITY_OBJECT_TYPE \
+ (web_view_accessibility_object_get_type())
+#define WEB_VIEW_ACCESSIBILITY_OBJECT(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), WEB_VIEW_ACCESSIBILITY_OBJECT_TYPE, \
+ WebViewAccessibilityObject))
+#define WEB_VIEW_ACCESSIBILITY_OBJECT_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), WEB_VIEW_ACCESSIBILITY_OBJECT_TYPE, \
+ WebViewAccessibilityObjectClass))
+#define IS_WEB_VIEW_ACCESSIBILITY_OBJECT(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEB_VIEW_ACCESSIBILITY_OBJECT_TYPE))
+#define IS_WEB_VIEW_ACCESSIBILITY_OBJECT_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), WEB_VIEW_ACCESSIBILITY_OBJECT_TYPE))
+#define WEB_VIEW_ACCESSIBILITY_OBJECT_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj), WEB_VIEW_ACCESSIBILITY_OBJECT_TYPE, \
+ WebViewAccessibilityObjectClass))
+
+typedef struct _WebViewAccessibilityObject WebViewAccessibilityObject;
+typedef struct _WebViewAccessibilityObjectClass WebViewAccessibilityObjectClass;
+typedef struct _WebViewAccessibilityObjectPrivate
+ WebViewAccessibilityObjectPrivate;
+
+struct _WebViewAccessibilityObject {
+ AtkPlug parent;
+ _WebViewAccessibilityObjectPrivate* priv;
+};
+
+struct _WebViewAccessibilityObjectClass {
+ AtkPlugClass parent_class;
+};
+
+GType web_view_accessibility_object_get_type();
+
+G_END_DECLS
+
+// This class represents EWebView root accessibility object.
+// EWebView root accessibility object is an entry point for browser
+// to have top-down navigation through accessibility objects.
+class EWebAccessibilityObject {
+ public:
+ explicit EWebAccessibilityObject(content::WebContents* web_contents);
+ ~EWebAccessibilityObject();
+
+ EWebAccessibilityObject(const EWebAccessibilityObject&) = delete;
+ EWebAccessibilityObject& operator=(const EWebAccessibilityObject&) = delete;
+
+ AtkObject* GetEflAtkObject() const;
+ AtkObject* RefAccessibleAtPoint(gint x, gint y, AtkCoordType coord_type);
+ void GetScreenGeometry(int* x, int* y, int* width, int* height) const;
+ void GetWindowGeometry(int* x, int* y, int* width, int* height) const;
+ gint GetIndexInParent() const;
+ gint GetNChildren() const;
+ AtkObject* RefChild(gint index) const;
+ AtkStateSet* RefStateSet() const;
+ content::BrowserAccessibilityManager* GetBrowserAccessibilityManager() const;
+ content::BrowserAccessibilityAuraLinux* GetRootObject() const;
+ void InvalidateHighlighted(bool focus);
+
+ private:
+ static void NativeViewShowCallback(void*, Evas*, Evas_Object*, void*);
+ static void NativeViewHideCallback(void*, Evas*, Evas_Object*, void*);
+ ui::AXPlatformNodeAuraLinux* GetNode() const;
+ AtkObject* GetAtkObject() const;
+
+ content::WebContents* web_contents_;
+ Evas_Object* native_view_;
+ AtkObject* efl_atk_obj_;
+};
+
+#endif // EWEB_ACCESSIBILITY_OBJECT_H
--- /dev/null
+// Copyright 2015-17 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "eweb_accessibility_util.h"
+
+#include <atk-bridge.h>
+#include <atk/atk.h>
+
+#include "common/web_contents_utils.h"
+#include "content/browser/accessibility/browser_accessibility_state_impl.h"
+#include "content/browser/web_contents/web_contents_impl_efl.h"
+#include "eweb_accessibility.h"
+#include "eweb_view.h"
+#include "tizen/system_info.h"
+
+#include <vconf.h>
+
+using web_contents_utils::WebViewFromWebContents;
+
+G_BEGIN_DECLS
+
+#define EWEB_ACCESSIBILITY_ROOT_TYPE (eweb_accessibility_root_get_type())
+#define EWEB_ACCESSIBILITY_ROOT(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), EWEB_ACCESSIBILITY_ROOT_TYPE, \
+ EWebAccessibilityRoot))
+#define EWEB_ACCESSIBILITY_ROOT_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), EWEB_ACCESSIBILITY_ROOT_TYPE, \
+ EWebAccessibilityRootClass))
+#define IS_EWEB_ACCESSIBILITY_ROOT(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), EWEB_ACCESSIBILITY_ROOT_TYPE))
+#define IS_EWEB_ACCESSIBILITY_ROOT_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), EWEB_ACCESSIBILITY_ROOT_TYPE))
+#define EWEB_ACCESSIBILITY_ROOT_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj), EWEB_ACCESSIBILITY_ROOT_TYPE, \
+ EWebAccessibilityRootClass))
+
+typedef struct _EWebAccessibilityRoot EWebAccessibilityRoot;
+typedef struct _EWebAccessibilityRootClass EWebAccessibilityRootClass;
+typedef struct _EWebAccessibilityRootPrivate EWebAccessibilityRootPrivate;
+
+struct _EWebAccessibilityRootPrivate {};
+
+struct _EWebAccessibilityRoot {
+ AtkObject parent;
+ _EWebAccessibilityRootPrivate* priv;
+};
+
+struct _EWebAccessibilityRootClass {
+ AtkObjectClass parentClass;
+};
+
+GType eweb_accessibility_root_get_type();
+
+G_END_DECLS
+
+G_DEFINE_TYPE_WITH_PRIVATE(EWebAccessibilityRoot,
+ eweb_accessibility_root,
+ ATK_TYPE_OBJECT);
+
+#if defined(ENABLE_WRT_JS)
+EWebAccessibility* eweb_accessibility_ = nullptr;
+#endif
+
+static void eweb_accessibility_root_init(
+ EWebAccessibilityRoot* accessible_root) {
+ accessible_root->priv = static_cast<_EWebAccessibilityRootPrivate*>(
+ eweb_accessibility_root_get_instance_private(accessible_root));
+}
+
+static void eweb_accessibility_root_class_init(
+ EWebAccessibilityRootClass* klass) {}
+
+static AtkObject* eweb_util_get_root() {
+ if (IsMobileProfile()) {
+ for (const auto& wc : content::WebContentsImpl::GetAllWebContents()) {
+ if (EWebView* ewebview = WebViewFromWebContents(wc))
+ return ewebview->eweb_accessibility().GetRootObject();
+ }
+#if defined(ENABLE_WRT_JS)
+ if (eweb_accessibility_)
+ return eweb_accessibility_->GetRootObject();
+#endif
+ return nullptr;
+ }
+
+ return ATK_OBJECT(g_object_new(EWEB_ACCESSIBILITY_ROOT_TYPE, nullptr));
+}
+
+static G_CONST_RETURN gchar* eweb_util_get_toolkit_name(void) {
+ return "Chromium-EFL";
+}
+
+static G_CONST_RETURN gchar* eweb_util_get_toolkit_version(void) {
+ return "1.0";
+}
+
+static void PropertyChangedCb(keynode_t* keynodeName, void* data) {
+ EWebAccessibilityUtil* obj = static_cast<EWebAccessibilityUtil*>(data);
+ if (!obj) {
+ LOG(ERROR) << "obj is NULL";
+ return;
+ }
+
+ int result = 0;
+ if (vconf_get_bool(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, &result) != 0) {
+ LOG(ERROR)
+ << "Could not read VCONFKEY_SETAPPL_ACCESSIBILITY_TTS key value.";
+ return;
+ }
+ obj->ToggleBrowserAccessibility(result);
+}
+
+EWebAccessibilityUtil* EWebAccessibilityUtil::GetInstance() {
+ return base::Singleton<EWebAccessibilityUtil>::get();
+}
+
+EWebAccessibilityUtil::EWebAccessibilityUtil() {
+ if (getuid() == 0)
+ return;
+
+ AtkUtilClass* atkUtilClass = ATK_UTIL_CLASS(g_type_class_ref(ATK_TYPE_UTIL));
+ atkUtilClass->get_toolkit_name = eweb_util_get_toolkit_name;
+ atkUtilClass->get_toolkit_version = eweb_util_get_toolkit_version;
+ atkUtilClass->get_root = eweb_util_get_root;
+ vconf_notify_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS,
+ PropertyChangedCb, this);
+}
+
+EWebAccessibilityUtil::~EWebAccessibilityUtil() {
+ vconf_ignore_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS,
+ PropertyChangedCb);
+ CleanAtkBridgeAdaptor();
+}
+
+void EWebAccessibilityUtil::NotifyAccessibilityStatus(bool mode) {
+ for (const auto& wc : content::WebContentsImpl::GetAllWebContents()) {
+ if (EWebView* ewebview = WebViewFromWebContents(wc))
+ ewebview->eweb_accessibility().NotifyAccessibilityStatus(mode);
+ }
+
+#if defined(ENABLE_WRT_JS)
+ if (eweb_accessibility_)
+ eweb_accessibility_->NotifyAccessibilityStatus(mode);
+#endif
+}
+
+void EWebAccessibilityUtil::ToggleBrowserAccessibility(bool mode) {
+ content::BrowserAccessibilityStateImpl* state =
+ content::BrowserAccessibilityStateImpl::GetInstance();
+
+ if (mode) {
+ InitAtkBridgeAdaptor();
+ state->EnableAccessibility();
+ }
+
+ NotifyAccessibilityStatus(mode);
+ if (!mode) {
+ state->DisableAccessibility();
+ CleanAtkBridgeAdaptor();
+ }
+}
+
+void EWebAccessibilityUtil::InitAtkBridgeAdaptor() {
+ if (!atk_bridge_initialized_) {
+ if (!atk_bridge_adaptor_init(nullptr, nullptr))
+ atk_bridge_initialized_ = true;
+ else
+ LOG(ERROR) << "atk_bridge_adaptor_init failed.";
+ }
+}
+
+void EWebAccessibilityUtil::CleanAtkBridgeAdaptor() {
+ if (atk_bridge_initialized_) {
+ atk_bridge_adaptor_cleanup();
+ atk_bridge_initialized_ = false;
+ }
+}
+
+void EWebAccessibilityUtil::ToggleAtk(bool& atk_status) {
+ if (IsDesktopProfile())
+ return;
+
+ if (atk_status)
+ atk_status = false;
+ else
+ return;
+
+ int result = 0;
+ if (vconf_get_bool(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, &result) != 0) {
+ LOG(ERROR)
+ << "Could not read VCONFKEY_SETAPPL_ACCESSIBILITY_TTS key value.";
+ return;
+ }
+
+ ToggleBrowserAccessibility(result);
+}
+
+#if defined(ENABLE_WRT_JS)
+void EWebAccessibilityUtil::SetEWebAccessibility(
+ EWebAccessibility* eweb_accessibility) {
+ eweb_accessibility_ = eweb_accessibility;
+}
+#endif
--- /dev/null
+// Copyright 2015-17 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EWEB_ACCESSIBILITY_UTIL_H
+#define EWEB_ACCESSIBILITY_UTIL_H
+
+#include "base/memory/singleton.h"
+
+#if defined(ENABLE_WRT_JS)
+class EWebAccessibility;
+#endif
+// This singleton class initializes atk-bridge and
+// registers an implementation of AtkUtil class.
+// Global class that every accessible application
+// needs to registers once.
+class EWebAccessibilityUtil {
+ public:
+ static EWebAccessibilityUtil* GetInstance();
+ void ToggleBrowserAccessibility(bool mode);
+
+#if defined(ENABLE_WRT_JS)
+ void SetEWebAccessibility(EWebAccessibility* eweb_accessibility);
+#endif
+ void ToggleAtk(bool& atk_status);
+
+ private:
+ EWebAccessibilityUtil();
+ ~EWebAccessibilityUtil();
+
+ EWebAccessibilityUtil(const EWebAccessibilityUtil&) = delete;
+ EWebAccessibilityUtil& operator=(const EWebAccessibilityUtil&) = delete;
+
+ void NotifyAccessibilityStatus(bool mode);
+ void InitAtkBridgeAdaptor();
+ void CleanAtkBridgeAdaptor();
+
+ bool atk_bridge_initialized_ = false;
+ friend struct base::DefaultSingletonTraits<EWebAccessibilityUtil>;
+};
+
+#endif // EWEB_ACCESSIBILITY_UTIL_H
#include <iostream>
+#if defined(TIZEN_ATK_SUPPORT)
+#include "content/browser/accessibility/browser_accessibility_state_impl.h"
+#include "eweb_accessibility.h"
+#include "eweb_accessibility_util.h"
+#endif
+
using namespace content;
using web_contents_utils::WebViewFromWebContents;
void* user_data_;
};
+#if defined(TIZEN_ATK_SUPPORT)
+class EWebAccessibilityObserver : public EWebAccessibility::Observer {
+ public:
+ explicit EWebAccessibilityObserver(EWebView* webview) : webview_(webview) {}
+ virtual ~EWebAccessibilityObserver() {}
+
+ // EWebAccessibility::Observer implementation
+ void OnSpatialNavigationStatusChanged(Eina_Bool enable) override {
+ webview_->UpdateSpatialNavigationStatus(enable);
+ }
+
+ void OnAccessibilityStatusChanged(Eina_Bool enable) override {
+ webview_->UpdateAccessibilityStatus(enable);
+ }
+
+ private:
+ EWebView* webview_;
+};
+#endif
+
int EWebView::find_request_id_counter_ = 0;
content::WebContentsEflDelegate::WebContentsCreateCallback
EWebView::create_new_window_web_contents_cb_ =
// RenderViewHostImpl::ComputeWebkitPrefs() based on command line switches.
settings_.reset(new Ewk_Settings(evas_object_,
web_contents_->GetOrCreateWebPreferences()));
+#if defined(TIZEN_ATK_SUPPORT)
+ std::unique_ptr<EWebAccessibilityObserver> observer(
+ new EWebAccessibilityObserver(this));
+ eweb_accessibility_.reset(new EWebAccessibility(
+ evas_object_, web_contents_.get(), std::move(observer)));
+ lazy_initialize_atk_ = true;
+#endif
+
base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
if (cmdline->HasSwitch(switches::kTouchEventFeatureDetection)) {
SetTouchEventsEnabled(
return;
}
+#if defined(TIZEN_ATK_SUPPORT)
+ eweb_accessibility_.reset();
+#endif
+
context_menu_.reset();
mhtml_callback_map_.Clear();
return true;
}
+
+#if defined(TIZEN_ATK_SUPPORT)
+void EWebView::UpdateSpatialNavigationStatus(Eina_Bool enable) {
+ if (settings_->getPreferences().spatial_navigation_enabled == enable)
+ return;
+
+ settings_->getPreferences().spatial_navigation_enabled = enable;
+ WebContentsImpl* wc = static_cast<WebContentsImpl*>(web_contents_.get());
+ if (wc)
+ wc->SetSpatialNavigationEnabled(enable);
+}
+
+void EWebView::UpdateAccessibilityStatus(Eina_Bool enable) {
+ if (settings_->getPreferences().atk_enabled == enable)
+ return;
+
+ settings_->getPreferences().atk_enabled = enable;
+ WebContentsImpl* wc = static_cast<WebContentsImpl*>(web_contents_.get());
+ if (wc)
+ wc->SetAtkEnabled(enable);
+}
+
+void EWebView::InitAtk() {
+ EWebAccessibilityUtil::GetInstance()->ToggleAtk(lazy_initialize_atk_);
+}
+
+/* LCOV_EXCL_START */
+bool EWebView::GetAtkStatus() {
+ auto state = content::BrowserAccessibilityStateImpl::GetInstance();
+ if (!state)
+ return false;
+ return state->IsAccessibleBrowser();
+}
+/* LCOV_EXCL_STOP */
+#endif
class WebViewEvasEventHandler;
class _Ewk_Quota_Permission_Request;
+#if defined(TIZEN_ATK_SUPPORT)
+class EWebAccessibility;
+#endif
+
template <typename CallbackPtr, typename CallbackParameter>
class WebViewCallback {
public:
content::WebContents& web_contents() const { return *web_contents_.get(); }
+#if defined(TIZEN_ATK_SUPPORT)
+ EWebAccessibility& eweb_accessibility() const {
+ return *eweb_accessibility_.get();
+ }
+#endif
+
template <EWebViewCallbacks::CallbackType callbackType>
EWebViewCallbacks::CallBack<callbackType> SmartCallback() const {
return EWebViewCallbacks::CallBack<callbackType>(evas_object_);
bool SetVisibility(bool enable);
+#if defined(TIZEN_ATK_SUPPORT)
+ void UpdateSpatialNavigationStatus(Eina_Bool enable);
+ void UpdateAccessibilityStatus(Eina_Bool enable);
+
+ bool CheckLazyInitializeAtk() {
+ return is_initialized_ && lazy_initialize_atk_;
+ }
+ void InitAtk();
+ bool GetAtkStatus();
+#endif
+
content::DateTimeChooserEfl* GetDateTimeChooser() {
return date_time_chooser_;
}
std::unique_ptr<aura::client::FocusClient> focus_client_;
std::unique_ptr<aura::client::WindowParentingClient> window_parenting_client_;
content::DateTimeChooserEfl* date_time_chooser_ = nullptr;
+
+#if defined(TIZEN_ATK_SUPPORT)
+ std::unique_ptr<EWebAccessibility> eweb_accessibility_;
+ bool lazy_initialize_atk_ = false;
+#endif
};
const unsigned int g_default_tilt_motion_sensitivity = 3;
NavigationHandle* navigation_handle) {
if (!navigation_handle->IsInMainFrame())
return;
+#if defined(TIZEN_ATK_SUPPORT)
+ if (web_view_->CheckLazyInitializeAtk())
+ web_view_->InitAtk();
+#endif
web_view_->SmartCallback<EWebViewCallbacks::ProvisionalLoadStarted>().call();
}
import("//tools/json_schema_compiler/json_schema_api.gni")
import("//ui/base/ui_features.gni")
+if (tizen_atk_support) {
+ import("//tizen_src/chromium_impl/ui/ui_efl.gni")
+}
+
if (is_android) {
import("//build/config/android/rules.gni")
}
public_deps += [ "//ui/aura" ]
}
+
+ if (tizen_atk_support) {
+ sources += external_ui_accessiblility_platform_sources
+ }
}
source_set("ax_assistant") {
}
GType ax_platform_atk_hyperlink_get_type() {
+#if defined(TIZEN_ATK_SUPPORT)
+ static gsize type_volatile = 0;
+#else
static volatile gsize type_volatile = 0;
+#endif
AXPlatformNodeAuraLinux::EnsureGTypeInit();
#include "ui/accessibility/platform/ax_platform_text_boundary.h"
#include "ui/gfx/geometry/rect_conversions.h"
+#if defined(TIZEN_ATK_SUPPORT)
+#include "tizen/system_info.h"
+#include "ui/accessibility/platform/ax_platform_node_efl.h"
+static const char kActivateActionName[] = "activate";
+#endif
+
#if defined(ATK_CHECK_VERSION) && ATK_CHECK_VERSION(2, 10, 0)
#define ATK_210
#endif
*pointer = value;
}
+#if defined(TIZEN_ATK_SUPPORT)
+AXPlatformNodeEfl* ToAXPlatformNodeEfl(AXPlatformNodeAuraLinux* obj) {
+ DCHECK(!obj);
+ return static_cast<AXPlatformNodeEfl*>(obj);
+}
+#endif
+
#if defined(ATK_230)
bool SupportsAtkComponentScrollingInterface() {
return dlsym(RTLD_DEFAULT, "atk_component_scroll_to_point");
if (!obj)
return nullptr;
+#if defined(TIZEN_ATK_SUPPORT)
+ if (AXPlatformNodeEfl::GetPreferredAXCoordinateSystem() ==
+ AXCoordinateSystem::kScreenDIPs) {
+ int view_x, view_y;
+ obj->GetDelegate()->EvasToBlinkCords(x, y, &view_x, &view_y);
+ x = view_x;
+ y = view_y;
+ }
+
+ AtkObject* result = nullptr;
+ for (int i = 0; i < obj->GetChildCount(); ++i) {
+ AXPlatformNodeAuraLinux* child =
+ AXPlatformNodeAuraLinux::FromAtkObject(obj->ChildAtIndex(i));
+ if (!child)
+ return nullptr;
+
+ if (child->GetExtentsRelativeToAtkCoordinateType(coord_type)
+ .Contains(gfx::Point(x, y))) {
+ result = child->GetAtkObject();
+ break;
+ }
+ }
+#else
AtkObject* result = obj->HitTestSync(x, y, coord_type);
+#endif
if (result)
g_object_ref(result);
return result;
return obj->GrabFocus();
}
+#if defined(TIZEN_ATK_SUPPORT)
+static gboolean GrabHighlight(AtkComponent* atk_component) {
+ if (IsMobileProfile())
+ return FALSE;
+
+ g_return_val_if_fail(ATK_IS_COMPONENT(atk_component), FALSE);
+ AtkObject* atk_object = ATK_OBJECT(atk_component);
+ AXPlatformNodeAuraLinux* obj =
+ AXPlatformNodeAuraLinux::FromAtkObject(atk_object);
+ if (!obj)
+ return FALSE;
+
+ return obj->SetHighlighted(atk_object);
+}
+
+static gboolean ClearHighlight(AtkComponent* atk_component) {
+ if (!IsMobileProfile())
+ return FALSE;
+
+ g_return_val_if_fail(ATK_IS_COMPONENT(atk_component), FALSE);
+ AtkObject* atk_object = ATK_OBJECT(atk_component);
+ AXPlatformNodeAuraLinux* obj =
+ AXPlatformNodeAuraLinux::FromAtkObject(atk_object);
+ if (!obj)
+ return FALSE;
+
+ return obj->MaybeInvalidateHighlighted(atk_object);
+}
+#endif
+
#if defined(ATK_230)
gboolean ScrollTo(AtkComponent* atk_component, AtkScrollType scroll_type) {
g_return_val_if_fail(ATK_IS_COMPONENT(atk_component), FALSE);
if (!obj)
return FALSE;
+#if defined(TIZEN_ATK_SUPPORT)
+ if (AXPlatformNodeEfl::GetPreferredAXCoordinateSystem() ==
+ AXCoordinateSystem::kScreenDIPs) {
+ int converted_x, converted_y;
+ obj->GetDelegate()->EvasToBlinkCords(x, y, &converted_x, &converted_y);
+ x = converted_x;
+ y = converted_y;
+ }
+#endif
obj->ScrollToPoint(atk_coord_type, x, y);
return TRUE;
}
iface->get_size = GetSize;
iface->ref_accessible_at_point = RefAccesibleAtPoint;
iface->grab_focus = GrabFocus;
+#if defined(TIZEN_ATK_SUPPORT)
+ if (IsMobileProfile()) {
+ iface->grab_highlight = GrabHighlight;
+ iface->clear_highlight = ClearHighlight;
+ }
+#endif
#if defined(ATK_230)
if (SupportsAtkComponentScrollingInterface()) {
iface->scroll_to = ScrollTo;
if (!obj)
return nullptr;
+#if defined(TIZEN_ATK_SUPPORT)
+ return kActivateActionName;
+#endif
const std::vector<ax::mojom::Action> actions =
obj->GetDelegate()->GetSupportedActions();
g_return_val_if_fail(index < static_cast<gint>(actions.size()), nullptr);
if (!obj)
return -1;
+#if defined(TIZEN_ATK_SUPPORT)
+ // root object so return index 0.
+ if (!obj->GetParent())
+ return 0;
+#endif
+
auto index_in_parent = obj->GetIndexInParent();
return index_in_parent.has_value()
? static_cast<gint>(index_in_parent.value())
if (!obj)
return nullptr;
+#if defined(TIZEN_ATK_SUPPORT)
+ // The root atk object is created in EwebAccessibility and set to
+ // BrowserAccessibilityAuraLinux after initialization. If the parent
+ // is null here, it means this is the document web node, so set the
+ // root atk object as parent of document web node's atk object.
+ if (!obj->GetParent())
+ return obj->GetDelegate()->GetRootAtkObject();
+#endif
+
return obj->GetParent();
}
AXPlatformNodeAuraLinux::FromAtkObject(atk_object);
if (!obj)
return ATK_ROLE_INVALID;
+#if defined(TIZEN_ATK_SUPPORT)
+ std::string text;
+ if (obj->GetData().GetHtmlAttribute("role", &text) && text.empty() &&
+ obj->HasStringAttribute(ax::mojom::StringAttribute::kRole))
+ return ATK_ROLE_INVALID;
+
+ AtkRole role = obj->GetAtkRole();
+ if (role == ATK_ROLE_UNKNOWN)
+ role = ATK_ROLE_INVALID;
+ return role;
+#endif
return obj->GetAtkRole();
}
GType GetType() {
AXPlatformNodeAuraLinux::EnsureGTypeInit();
+#if defined(TIZEN_ATK_SUPPORT)
+ static gsize type_volatile = 0;
+#else
static volatile gsize type_volatile = 0;
+#endif
if (g_once_init_enter(&type_volatile)) {
static const GTypeInfo type_info = {
sizeof(AXPlatformNodeAuraLinuxClass), // class_size
&atk_table_cell::Info);
}
}
+#if defined(TIZEN_ATK_SUPPORT)
+ // FIXME ATK_EDITABLE_TEXT_INTERFACE is removed
+#if !defined(EWK_BRINGUP)
+ if (interface_mask_ & (1 << ATK_EDITABLE_TEXT_INTERFACE)) {
+ g_type_add_interface_static(type, ATK_TYPE_EDITABLE_TEXT,
+ &atk_action::Info);
+ }
+#endif
+ ToAXPlatformNodeEfl(this)->SetInterfaceFromObject(type, interface_mask_);
+#endif
return type;
}
return nullptr;
EnsureGTypeInit();
interface_mask_ = GetGTypeInterfaceMask(GetData());
+#if defined(TIZEN_ATK_SUPPORT)
+ ToAXPlatformNodeEfl(this)->SetInterfaceMaskFromObject(interface_mask_);
+#endif
GType type = GetAccessibilityGType();
AtkObject* atk_object = static_cast<AtkObject*>(g_object_new(type, nullptr));
}
}
+#if !defined(TIZEN_ATK_SUPPORT)
// static
AXPlatformNode* AXPlatformNode::Create(AXPlatformNodeDelegate* delegate) {
AXPlatformNodeAuraLinux* node = new AXPlatformNodeAuraLinux();
node->Init(delegate);
return node;
}
+#endif
// static
AXPlatformNode* AXPlatformNode::FromNativeViewAccessible(
case ax::mojom::Role::kGrid:
return ATK_ROLE_TABLE;
case ax::mojom::Role::kGroup:
+#if !defined(TIZEN_ATK_FEATURE_VD)
+ return ATK_ROLE_INVALID;
+#else
return ATK_ROLE_PANEL;
+#endif
case ax::mojom::Role::kHeading:
return ATK_ROLE_HEADING;
case ax::mojom::Role::kIframe:
atk_state_set_add_state(atk_state_set, ATK_STATE_HORIZONTAL);
if (!IsInvisibleOrIgnored()) {
atk_state_set_add_state(atk_state_set, ATK_STATE_VISIBLE);
+#if !defined(TIZEN_ATK_SUPPORT)
if (!delegate_->IsOffscreen() && !is_minimized)
atk_state_set_add_state(atk_state_set, ATK_STATE_SHOWING);
+#endif
}
if (HasState(ax::mojom::State::kMultiselectable))
atk_state_set_add_state(atk_state_set, ATK_STATE_MULTISELECTABLE);
if (!atk_object)
return;
+#if defined(TIZEN_ATK_SUPPORT)
+ if (IsMobileProfile()) {
+ ToAXPlatformNodeEfl(this)->RecalculateHighlightableSingle();
+ if (ToAXPlatformNodeEfl(this)->Ishighlightable()) {
+ atk_state_set_add_state(atk_state_set, ATK_STATE_HIGHLIGHTABLE);
+ }
+ atk_state_set_add_state(atk_state_set, ATK_STATE_SHOWING);
+
+ if (atk_object_ && IsHighlighted(atk_object_))
+ atk_state_set_add_state(atk_state_set, ATK_STATE_HIGHLIGHTED);
+ }
+#endif
+
// It is insufficient to compare with g_current_activedescendant due to both
// timing and event ordering for objects which implement AtkSelection and also
// have an active descendant. For instance, if we check the state set of a
if (!GetFloatAttribute(ax::mojom::FloatAttribute::kValueForRange, &float_val))
return;
+#if defined(TIZEN_ATK_SUPPORT)
+ // The progress bar of youtube.com continuously update its value,
+ // that interrupt the output of other events; so only emit value
+ // changed event for focus node or its active descendant
+ if (delegate_->GetFocus() != GetNativeViewAccessible() &&
+ delegate_->GetActiveDescendant() != GetNativeViewAccessible())
+ return;
+#endif
+
AtkObject* atk_object = GetOrCreateAtkObject();
if (!atk_object)
return;
gfx::Rect AXPlatformNodeAuraLinux::GetExtentsRelativeToAtkCoordinateType(
AtkCoordType coord_type) const {
+#if defined(TIZEN_ATK_SUPPORT)
+ gfx::Rect extents = delegate_->GetBoundsRect(
+ AXPlatformNodeEfl::GetPreferredAXCoordinateSystem(),
+#else
gfx::Rect extents = delegate_->GetBoundsRect(AXCoordinateSystem::kScreenDIPs,
- AXClippingBehavior::kUnclipped);
+#endif
+ AXClippingBehavior::kUnclipped);
switch (coord_type) {
case ATK_XY_SCREEN:
break;
return selection;
}
+#if defined(TIZEN_ATK_SUPPORT)
+bool AXPlatformNodeAuraLinux::SetHighlighted(AtkObject* obj) {
+ if (g_current_focused == obj)
+ return false;
+
+ GetDelegate()->CheckFocusOnEwebview();
+ InvalidateHighlighted(false);
+
+ auto focused_obj = AXPlatformNodeAuraLinux::FromAtkObject(obj);
+ if (focused_obj) {
+ focused_obj->ScrollToNode(AXPlatformNodeBase::ScrollType::Anywhere);
+ focused_obj->GrabFocus();
+ g_current_focused = obj;
+
+ atk_object_notify_state_change(g_current_focused, ATK_STATE_HIGHLIGHTED,
+ true);
+ return true;
+ }
+ return false;
+}
+
+bool AXPlatformNodeAuraLinux::IsHighlighted(AtkObject* obj) const {
+ return g_current_focused == obj;
+}
+
+bool AXPlatformNodeAuraLinux::MaybeInvalidateHighlighted(AtkObject* obj) {
+ if (!IsHighlighted(obj))
+ return false;
+
+ InvalidateHighlighted(false);
+ return true;
+}
+
+void AXPlatformNodeAuraLinux::InvalidateHighlighted(bool focus_root) {
+ if (!g_current_focused)
+ return;
+
+ // highlighted_obj_ needs to be nullptr before notification as during it
+ // states are obtained. ATK_STATE_HIGHLIGHTED depends on highlighted_obj_
+ // itself
+ auto highlighted_obj = g_current_focused;
+ g_current_focused = nullptr;
+
+ if (focus_root) {
+ auto root = GetDelegate()->GetRoot();
+ if (root)
+ (static_cast<AXPlatformNodeAuraLinux*>(root))->GrabFocus();
+ }
+
+ if (highlighted_obj) {
+ atk_object_notify_state_change(highlighted_obj, ATK_STATE_HIGHLIGHTED,
+ false);
+ }
+}
+#endif
+
} // namespace ui
int y);
#endif // defined(ATK_CHECK_VERSION) && ATK_CHECK_VERSION(2, 32, 0)
+#if defined(TIZEN_ATK_SUPPORT)
+ bool SetHighlighted(AtkObject* obj);
+ bool IsHighlighted(AtkObject* obj) const;
+ bool MaybeInvalidateHighlighted(AtkObject* obj);
+ void InvalidateHighlighted(bool focus_root);
+#endif
// Misc helpers
void GetFloatAttributeInGValue(ax::mojom::FloatAttribute attr, GValue* value);
// nullopt.
absl::optional<std::pair<int, int>> GetEmbeddedObjectIndices();
+#if defined(TIZEN_ATK_SUPPORT)
+ AtkObject* GetAtkObject() { return atk_object_; }
+ // We own a reference to these ref-counted objects.
+ AtkObject* atk_object_ = nullptr;
+
+ // Keep information of latest ImplementedAtkInterfaces mask to rebuild the
+ // ATK object accordingly when the platform node changes.
+ ImplementedAtkInterfaces interface_mask_;
+#endif
std::string accessible_name_;
-
+
protected:
AXPlatformNodeAuraLinux();
gfx::Point ConvertPointToScreenCoordinates(const gfx::Point& point,
AtkCoordType atk_coord_type);
+#if !defined(TIZEN_ATK_SUPPORT)
// Keep information of latest ImplementedAtkInterfaces mask to rebuild the
// ATK object accordingly when the platform node changes.
ImplementedAtkInterfaces interface_mask_;
// We own a reference to these ref-counted objects.
AtkObject* atk_object_ = nullptr;
+#endif
AtkHyperlink* atk_hyperlink_ = nullptr;
// A weak pointers which help us track the ATK embeds relation.
// document through its ancestry chain.
virtual gfx::NativeViewAccessible GetFocus() const = 0;
+#if defined(TIZEN_ATK_SUPPORT)
+ // Return the node within this node's subtree (inclusive) that currently
+ // is the active descendant of focus or is the focus itself.
+ virtual gfx::NativeViewAccessible GetActiveDescendant() = 0;
+ virtual void EvasToBlinkCords(int x, int y, int* view_x, int* view_y) = 0;
+ virtual AXPlatformNode* GetRoot() = 0;
+ virtual void CheckFocusOnEwebview() = 0;
+ virtual gfx::NativeViewAccessible GetRootAtkObject() = 0;
+#endif
+
// Get whether this node is offscreen.
virtual bool IsOffscreen() const = 0;
return nullptr;
}
+#if defined(TIZEN_ATK_SUPPORT)
+gfx::NativeViewAccessible AXPlatformNodeDelegateBase::GetActiveDescendant() {
+ return nullptr;
+}
+void AXPlatformNodeDelegateBase::EvasToBlinkCords(int x,
+ int y,
+ int* view_x,
+ int* view_y) {}
+
+AXPlatformNode* AXPlatformNodeDelegateBase::GetRoot() {
+ return nullptr;
+}
+
+void AXPlatformNodeDelegateBase::CheckFocusOnEwebview() {}
+#endif
+
AXPlatformNode* AXPlatformNodeDelegateBase::GetFromNodeID(int32_t id) {
return nullptr;
}
// has focus.
gfx::NativeViewAccessible GetFocus() const override;
+#if defined(TIZEN_ATK_SUPPORT)
+ // Return the node within this node's subtree (inclusive) that currently
+ // is the active descendant of focus or is the focus itself.
+ gfx::NativeViewAccessible GetActiveDescendant() override;
+ void EvasToBlinkCords(int x, int y, int* view_x, int* view_y) override;
+ AXPlatformNode* GetRoot() override;
+ void CheckFocusOnEwebview() override;
+ gfx::NativeViewAccessible GetRootAtkObject() override { return nullptr; }
+#endif
+
// Get whether this node is offscreen.
bool IsOffscreen() const override;
# Whether the platform provides a native accessibility toolkit, in other words
# the platform has a C/C++ interface for accessibility that Chrome
# implements/subclasses in some way - win, mac, linux.
- has_native_accessibility = use_atk || is_win || is_mac
+ has_native_accessibility = use_atk || is_win || is_mac || is_tizen
# Whether the platform provide platform-specific accessibility implementation,
# i.e. there an accessibility API of some kind on this platform that's
// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
// of lacros-chrome is complete.
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) || \
+ defined(TIZEN_ATK_SUPPORT)
extern "C" {
struct _AtkObject;
typedef struct _AtkObject AtkObject;
typedef id NativeViewAccessible;
// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
// of lacros-chrome is complete.
-#elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) || \
+ defined(TIZEN_ATK_SUPPORT)
// Linux doesn't have a native font type.
typedef AtkObject* NativeViewAccessible;
#else