| Index: webkit/glue/glue_accessibility_object.cc
|
| ===================================================================
|
| --- webkit/glue/glue_accessibility_object.cc (revision 0)
|
| +++ webkit/glue/glue_accessibility_object.cc (revision 0)
|
| @@ -0,0 +1,445 @@
|
| +// Copyright (c) 2006-2009 The Chromium 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 "config.h"
|
| +
|
| +#include "AccessibilityObject.h"
|
| +#include "EventHandler.h"
|
| +#include "FrameView.h"
|
| +#include "PlatformKeyboardEvent.h"
|
| +
|
| +#include "webkit/glue/glue_accessibility_object.h"
|
| +
|
| +using WebCore::AccessibilityObject;
|
| +using WebCore::String;
|
| +using webkit_glue::WebAccessibility;
|
| +
|
| +GlueAccessibilityObject::GlueAccessibilityObject(AccessibilityObject* obj)
|
| + : AccessibilityObjectWrapper(obj) {
|
| + m_object->setWrapper(this);
|
| +}
|
| +
|
| +GlueAccessibilityObject* GlueAccessibilityObject::CreateInstance(
|
| + AccessibilityObject* obj) {
|
| + if (!obj)
|
| + return NULL;
|
| +
|
| + return new GlueAccessibilityObject(obj);
|
| +}
|
| +
|
| +bool GlueAccessibilityObject::DoDefaultAction(int child_id) {
|
| + AccessibilityObject* child_obj;
|
| +
|
| + if (!GetAccessibilityObjectForChild(child_id, child_obj) ||
|
| + !child_obj->performDefaultAction()) {
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +GlueAccessibilityObject* GlueAccessibilityObject::HitTest(long x, long y) {
|
| + if (!m_object)
|
| + return NULL;
|
| +
|
| + // x, y - coordinates are passed in as window coordinates, to maintain
|
| + // sandbox functionality.
|
| + WebCore::IntPoint point =
|
| + m_object->documentFrameView()->windowToContents(WebCore::IntPoint(x, y));
|
| + AccessibilityObject* child_obj = m_object->doAccessibilityHitTest(point);
|
| +
|
| + if (!child_obj) {
|
| + // If we did not hit any child objects, test whether the point hit us, and
|
| + // report that.
|
| + if (!m_object->boundingBoxRect().contains(point))
|
| + return NULL;
|
| + child_obj = m_object;
|
| + }
|
| + // TODO(klink): simple object child?
|
| + ToWrapper(child_obj)->ref();
|
| + return ToWrapper(child_obj);
|
| +}
|
| +
|
| +bool GlueAccessibilityObject::Location(long* left, long* top, long* width,
|
| + long* height, int child_id) {
|
| + if (!left || !top || !width || !height)
|
| + return false;
|
| +
|
| + *left = *top = *width = *height = 0;
|
| +
|
| + AccessibilityObject* child_obj;
|
| + if (!GetAccessibilityObjectForChild(child_id, child_obj))
|
| + return false;
|
| +
|
| + // Returning window coordinates, to be handled and converted appropriately by
|
| + // the client.
|
| + WebCore::IntRect window_rect(child_obj->documentFrameView()->contentsToWindow(
|
| + child_obj->boundingBoxRect()));
|
| + *left = window_rect.x();
|
| + *top = window_rect.y();
|
| + *width = window_rect.width();
|
| + *height = window_rect.height();
|
| + return true;
|
| +}
|
| +
|
| +GlueAccessibilityObject* GlueAccessibilityObject::Navigate(
|
| + WebAccessibility::Direction dir, int start_child_id) {
|
| + AccessibilityObject* child_obj = 0;
|
| +
|
| + switch (dir) {
|
| + case WebAccessibility::DIRECTION_DOWN:
|
| + case WebAccessibility::DIRECTION_UP:
|
| + case WebAccessibility::DIRECTION_LEFT:
|
| + case WebAccessibility::DIRECTION_RIGHT:
|
| + // These directions are not implemented, matching Mozilla and IE.
|
| + return NULL;
|
| + case WebAccessibility::DIRECTION_LASTCHILD:
|
| + case WebAccessibility::DIRECTION_FIRSTCHILD:
|
| + // MSDN states that navigating to first/last child can only be from self.
|
| + if (start_child_id != 0 || !m_object)
|
| + return NULL;
|
| +
|
| + if (dir == WebAccessibility::DIRECTION_FIRSTCHILD) {
|
| + child_obj = m_object->firstChild();
|
| + } else {
|
| + child_obj = m_object->lastChild();
|
| + }
|
| + break;
|
| + case WebAccessibility::DIRECTION_NEXT:
|
| + case WebAccessibility::DIRECTION_PREVIOUS: {
|
| + // Navigating to next and previous is allowed from self or any of our
|
| + // children.
|
| + if (!GetAccessibilityObjectForChild(start_child_id, child_obj))
|
| + return NULL;
|
| +
|
| + if (dir == WebAccessibility::DIRECTION_NEXT) {
|
| + child_obj = child_obj->nextSibling();
|
| + } else {
|
| + child_obj = child_obj->previousSibling();
|
| + }
|
| + break;
|
| + }
|
| + default:
|
| + return NULL;
|
| + }
|
| +
|
| + if (!child_obj)
|
| + return NULL;
|
| +
|
| + // TODO(klink): simple object child?
|
| + ToWrapper(child_obj)->ref();
|
| + return ToWrapper(child_obj);
|
| +}
|
| +
|
| +GlueAccessibilityObject* GlueAccessibilityObject::GetChild(int child_id) {
|
| + AccessibilityObject* child_obj;
|
| + if (!GetAccessibilityObjectForChild(child_id, child_obj))
|
| + return false;
|
| +
|
| + // TODO(klink): simple object child?
|
| + ToWrapper(child_obj)->ref();
|
| + return ToWrapper(child_obj);
|
| +}
|
| +
|
| +bool GlueAccessibilityObject::ChildCount(long* count) {
|
| + if (!m_object || !count)
|
| + return false;
|
| +
|
| + *count = static_cast<long>(m_object->children().size());
|
| + return true;
|
| +}
|
| +
|
| +bool GlueAccessibilityObject::DefaultAction(int child_id, String* action) {
|
| + if (!action)
|
| + return false;
|
| +
|
| + AccessibilityObject* child_obj;
|
| + if (!GetAccessibilityObjectForChild(child_id, child_obj))
|
| + return false;
|
| +
|
| + *action = child_obj->actionVerb();
|
| + return !action->isEmpty();
|
| +}
|
| +
|
| +bool GlueAccessibilityObject::Description(int child_id, String* description) {
|
| + if (!description)
|
| + return false;
|
| +
|
| + AccessibilityObject* child_obj;
|
| + if (!GetAccessibilityObjectForChild(child_id, child_obj))
|
| + return false;
|
| +
|
| + // TODO(klink): Description, for SELECT subitems, should be a string
|
| + // describing the position of the item in its group and of the group in the
|
| + // list (see Firefox).
|
| + *description = ToWrapper(child_obj)->description();
|
| + return !description->isEmpty();
|
| +}
|
| +
|
| +GlueAccessibilityObject* GlueAccessibilityObject::GetFocusedChild() {
|
| + if (!m_object)
|
| + return NULL;
|
| +
|
| + AccessibilityObject* focused_obj = m_object->focusedUIElement();
|
| + if (!focused_obj)
|
| + return NULL;
|
| +
|
| + // Only return the focused child if it's us or a child of us.
|
| + if (focused_obj == m_object || focused_obj->parentObject() == m_object) {
|
| + ToWrapper(focused_obj)->ref();
|
| + return ToWrapper(focused_obj);
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| +bool GlueAccessibilityObject::HelpText(int child_id, String* help) {
|
| + if (!help)
|
| + return false;
|
| +
|
| + AccessibilityObject* child_obj;
|
| + if (!GetAccessibilityObjectForChild(child_id, child_obj))
|
| + return false;
|
| +
|
| + *help = child_obj->helpText();
|
| + return !help->isEmpty();
|
| +}
|
| +
|
| +bool GlueAccessibilityObject::KeyboardShortcut(int child_id, String* shortcut) {
|
| + if (!shortcut)
|
| + return false;
|
| +
|
| + AccessibilityObject* child_obj;
|
| + if (!GetAccessibilityObjectForChild(child_id, child_obj))
|
| + return false;
|
| +
|
| + String access_key = child_obj->accessKey();
|
| + if (access_key.isNull())
|
| + return false;
|
| +
|
| + static String access_key_modifiers;
|
| + if (access_key_modifiers.isNull()) {
|
| + unsigned modifiers = WebCore::EventHandler::accessKeyModifiers();
|
| + // Follow the same order as Mozilla MSAA implementation:
|
| + // Ctrl+Alt+Shift+Meta+key. MSDN states that keyboard shortcut strings
|
| + // should not be localized and defines the separator as "+".
|
| + if (modifiers & WebCore::PlatformKeyboardEvent::CtrlKey)
|
| + access_key_modifiers += "Ctrl+";
|
| + if (modifiers & WebCore::PlatformKeyboardEvent::AltKey)
|
| + access_key_modifiers += "Alt+";
|
| + if (modifiers & WebCore::PlatformKeyboardEvent::ShiftKey)
|
| + access_key_modifiers += "Shift+";
|
| + if (modifiers & WebCore::PlatformKeyboardEvent::MetaKey)
|
| + access_key_modifiers += "Win+";
|
| + }
|
| + *shortcut = access_key_modifiers + access_key;
|
| + return !shortcut->isEmpty();
|
| +}
|
| +
|
| +bool GlueAccessibilityObject::Name(int child_id, String* name) {
|
| + if (!name)
|
| + return false;
|
| +
|
| + AccessibilityObject* child_obj;
|
| + if (!GetAccessibilityObjectForChild(child_id, child_obj))
|
| + return false;
|
| +
|
| + *name = ToWrapper(child_obj)->name();
|
| + return !name->isEmpty();
|
| +}
|
| +
|
| +GlueAccessibilityObject* GlueAccessibilityObject::GetParent() {
|
| + if (!m_object)
|
| + return NULL;
|
| +
|
| + AccessibilityObject* parent_obj = m_object->parentObject();
|
| +
|
| + if (parent_obj) {
|
| + ToWrapper(parent_obj)->ref();
|
| + return ToWrapper(parent_obj);
|
| + }
|
| + // No valid parent, or parent is the containing window.
|
| + return NULL;
|
| +}
|
| +
|
| +bool GlueAccessibilityObject::Role(int child_id, long* role) {
|
| + if (!role)
|
| + return false;
|
| +
|
| + AccessibilityObject* child_obj;
|
| + if (!GetAccessibilityObjectForChild(child_id, child_obj))
|
| + return false;
|
| +
|
| + *role = ToWrapper(child_obj)->role();
|
| + return true;
|
| +}
|
| +
|
| +bool GlueAccessibilityObject::Value(int child_id, String* value) {
|
| + if (!value)
|
| + return false;
|
| +
|
| + AccessibilityObject* child_obj;
|
| + if (!GetAccessibilityObjectForChild(child_id, child_obj))
|
| + return false;
|
| +
|
| + *value = ToWrapper(child_obj)->value();
|
| + return !value->isEmpty();
|
| +}
|
| +
|
| +bool GlueAccessibilityObject::State(int child_id, long* state) {
|
| + if (!state)
|
| + return false;
|
| +
|
| + *state = 0;
|
| + AccessibilityObject* child_obj;
|
| + if (!GetAccessibilityObjectForChild(child_id, child_obj))
|
| + return false;
|
| +
|
| + if (child_obj->isAnchor())
|
| + *state |= static_cast<long>(1 << WebAccessibility::STATE_LINKED);
|
| +
|
| + if (child_obj->isHovered())
|
| + *state |= static_cast<long>(1 << WebAccessibility::STATE_HOTTRACKED);
|
| +
|
| + if (!child_obj->isEnabled())
|
| + *state |= static_cast<long>(1 << WebAccessibility::STATE_UNAVAILABLE);
|
| +
|
| + if (child_obj->isReadOnly())
|
| + *state |= static_cast<long>(1 << WebAccessibility::STATE_READONLY);
|
| +
|
| + if (child_obj->isOffScreen())
|
| + *state |= static_cast<long>(1 << WebAccessibility::STATE_OFFSCREEN);
|
| +
|
| + if (child_obj->isMultiSelect())
|
| + *state |= static_cast<long>(1 << WebAccessibility::STATE_MULTISELECTABLE);
|
| +
|
| + if (child_obj->isPasswordField())
|
| + *state |= static_cast<long>(1 << WebAccessibility::STATE_PROTECTED);
|
| +
|
| + if (child_obj->isIndeterminate())
|
| + *state |= static_cast<long>(1 << WebAccessibility::STATE_INDETERMINATE);
|
| +
|
| + if (child_obj->isChecked())
|
| + *state |= static_cast<long>(1 << WebAccessibility::STATE_CHECKED);
|
| +
|
| + if (child_obj->isPressed())
|
| + *state |= static_cast<long>(1 << WebAccessibility::STATE_PRESSED);
|
| +
|
| + if (child_obj->isFocused())
|
| + *state |= static_cast<long>(1 << WebAccessibility::STATE_FOCUSED);
|
| +
|
| + if (child_obj->isVisited())
|
| + *state |= static_cast<long>(1 << WebAccessibility::STATE_TRAVERSED);
|
| +
|
| + if (child_obj->canSetFocusAttribute())
|
| + *state |= static_cast<long>(1 << WebAccessibility::STATE_FOCUSABLE);
|
| +
|
| + // TODO(klink): Add selected and selectable states.
|
| +
|
| + return true;
|
| +}
|
| +
|
| +// Helper functions
|
| +String GlueAccessibilityObject::name() const {
|
| + return m_object->title();
|
| +}
|
| +
|
| +String GlueAccessibilityObject::value() const {
|
| + return m_object->stringValue();
|
| +}
|
| +
|
| +String GlueAccessibilityObject::description() const {
|
| + String desc = m_object->accessibilityDescription();
|
| + if (desc.isNull())
|
| + return desc;
|
| +
|
| + // From the Mozilla MSAA implementation:
|
| + // "Signal to screen readers that this description is speakable and is not
|
| + // a formatted positional information description. Don't localize the
|
| + // 'Description: ' part of this string, it will be parsed out by assistive
|
| + // technologies."
|
| + return "Description: " + desc;
|
| +}
|
| +
|
| +// Provides a conversion between the WebCore::AccessibilityRole and a
|
| +// role supported on the Browser side. Static function.
|
| +static WebAccessibility::Role SupportedRole(WebCore::AccessibilityRole role) {
|
| + switch (role) {
|
| + case WebCore::ButtonRole:
|
| + return WebAccessibility::ROLE_PUSHBUTTON;
|
| + case WebCore::RadioButtonRole:
|
| + return WebAccessibility::ROLE_RADIOBUTTON;
|
| + case WebCore::CheckBoxRole:
|
| + return WebAccessibility::ROLE_CHECKBUTTON;
|
| + case WebCore::SliderRole:
|
| + return WebAccessibility::ROLE_SLIDER;
|
| + case WebCore::TabGroupRole:
|
| + return WebAccessibility::ROLE_PAGETABLIST;
|
| + case WebCore::TextFieldRole:
|
| + case WebCore::TextAreaRole:
|
| + case WebCore::ListMarkerRole:
|
| + return WebAccessibility::ROLE_TEXT;
|
| + case WebCore::StaticTextRole:
|
| + return WebAccessibility::ROLE_STATICTEXT;
|
| + case WebCore::OutlineRole:
|
| + return WebAccessibility::ROLE_OUTLINE;
|
| + case WebCore::ColumnRole:
|
| + return WebAccessibility::ROLE_COLUMN;
|
| + case WebCore::RowRole:
|
| + return WebAccessibility::ROLE_ROW;
|
| + case WebCore::GroupRole:
|
| + return WebAccessibility::ROLE_GROUPING;
|
| + case WebCore::ListRole:
|
| + return WebAccessibility::ROLE_LIST;
|
| + case WebCore::TableRole:
|
| + return WebAccessibility::ROLE_TABLE;
|
| + case WebCore::LinkRole:
|
| + case WebCore::WebCoreLinkRole:
|
| + return WebAccessibility::ROLE_LINK;
|
| + case WebCore::ImageMapRole:
|
| + case WebCore::ImageRole:
|
| + return WebAccessibility::ROLE_GRAPHIC;
|
| + default:
|
| + // This is the default role.
|
| + return WebAccessibility::ROLE_CLIENT;
|
| + }
|
| +}
|
| +
|
| +WebAccessibility::Role GlueAccessibilityObject::role() const {
|
| + return SupportedRole(m_object->roleValue());
|
| +}
|
| +
|
| +bool GlueAccessibilityObject::GetAccessibilityObjectForChild(int child_id,
|
| + AccessibilityObject*& child_obj) const {
|
| + child_obj = 0;
|
| +
|
| + if (!m_object || child_id < 0)
|
| + return false;
|
| +
|
| + if (child_id == 0) {
|
| + child_obj = m_object;
|
| + } else {
|
| + size_t child_index = static_cast<size_t>(child_id - 1);
|
| +
|
| + if (child_index >= m_object->children().size())
|
| + return false;
|
| + child_obj = m_object->children().at(child_index).get();
|
| + }
|
| +
|
| + if (!child_obj)
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +GlueAccessibilityObject* GlueAccessibilityObject::ToWrapper(
|
| + AccessibilityObject* obj) {
|
| + if (!obj)
|
| + return NULL;
|
| +
|
| + GlueAccessibilityObject* result =
|
| + static_cast<GlueAccessibilityObject*>(obj->wrapper());
|
| + if (!result)
|
| + result = CreateInstance(obj);
|
| +
|
| + return result;
|
| +}
|
|
|
| Property changes on: webkit\glue\glue_accessibility_object.cc
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|