summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-31 05:04:03 +0000
committerdmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-31 05:04:03 +0000
commit4003e72945f0faa549d21c90558d0dce96056806 (patch)
tree1652595a18682f2d260da2baad74339c7c874166
parenta5cc4ffe04d83f0fbdaaf988bf21ac562c06cfae (diff)
downloadchromium_src-4003e72945f0faa549d21c90558d0dce96056806.zip
chromium_src-4003e72945f0faa549d21c90558d0dce96056806.tar.gz
chromium_src-4003e72945f0faa549d21c90558d0dce96056806.tar.bz2
Improve omnibox accessibility on Windows.
This refactors and improves a bunch of views accessibility code on Windows and has the result of enabling NVDA to announce the text selection in the omnibox. The AutocompleteAccessibility class is removed; its functionality is rolled into NativeViewAccessibilityWin. NativeViewAccessibilityWin adds IAccessible2 and IAccessibleText interfaces, allowing it to directly expose the caret and selection to compatible assistive technology. In addition, this gives each accessible object an unique id. Finally, the reference from a View to its NativeViewAccessibilityWin is changed from a scoped_refptr to a ScopedComPtr, because another process may still have a reference to the accessible COM object when the View is deleted. BUG=53380 TEST=Manually test the omnibox with NVDA on Windows. It should announce text that's selected, including autocompletions. Review URL: http://codereview.chromium.org/8391010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@107924 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/autocomplete/autocomplete_accessibility.cc261
-rw-r--r--chrome/browser/autocomplete/autocomplete_accessibility.h116
-rw-r--r--chrome/browser/autocomplete/autocomplete_edit_unittest.cc2
-rw-r--r--chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h2
-rw-r--r--chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm2
-rw-r--r--chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.cc2
-rw-r--r--chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.h2
-rw-r--r--chrome/browser/ui/omnibox/omnibox_view.h2
-rw-r--r--chrome/browser/ui/views/omnibox/omnibox_view_views.cc2
-rw-r--r--chrome/browser/ui/views/omnibox/omnibox_view_views.h2
-rw-r--r--chrome/browser/ui/views/omnibox/omnibox_view_win.cc91
-rw-r--r--chrome/browser/ui/views/omnibox/omnibox_view_win.h11
-rw-r--r--chrome/chrome_browser.gypi3
-rw-r--r--ui/base/accessibility/accessibility_types.h33
-rw-r--r--views/DEPS1
-rw-r--r--views/accessibility/native_view_accessibility_win.cc348
-rw-r--r--views/accessibility/native_view_accessibility_win.h190
-rw-r--r--views/view.h10
-rw-r--r--views/views.gyp4
19 files changed, 566 insertions, 518 deletions
diff --git a/chrome/browser/autocomplete/autocomplete_accessibility.cc b/chrome/browser/autocomplete/autocomplete_accessibility.cc
deleted file mode 100644
index 8966f94..0000000
--- a/chrome/browser/autocomplete/autocomplete_accessibility.cc
+++ /dev/null
@@ -1,261 +0,0 @@
-// Copyright (c) 2011 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 "chrome/browser/autocomplete/autocomplete_accessibility.h"
-
-#include "chrome/browser/autocomplete/autocomplete_edit.h"
-#include "chrome/browser/ui/views/omnibox/omnibox_view_win.h"
-#include "grit/generated_resources.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "views/accessibility/native_view_accessibility_win.h"
-#include "views/view.h"
-
-HRESULT AutocompleteAccessibility::Initialize(
- const OmniboxViewWin* omnibox_view) {
- if (omnibox_view == NULL) {
- return E_INVALIDARG;
- }
-
- omnibox_view_ = omnibox_view;
-
- // Create a default accessible object for this instance.
- return CreateStdAccessibleObject(omnibox_view_->m_hWnd, OBJID_CLIENT,
- IID_IAccessible,
- reinterpret_cast<void **>(default_accessibility_server_.Receive()));
-}
-
-STDMETHODIMP AutocompleteAccessibility::get_accChildCount(LONG* child_count) {
- if (!child_count) {
- return E_INVALIDARG;
- }
-
- DCHECK(default_accessibility_server_);
- return default_accessibility_server_->get_accChildCount(child_count);
-}
-
-STDMETHODIMP AutocompleteAccessibility::get_accChild(VARIANT var_child,
- IDispatch** disp_child) {
- if (var_child.vt != VT_I4 || !disp_child) {
- return E_INVALIDARG;
- }
-
- // If var_child is the parent, remain with the same IDispatch
- if (var_child.lVal == CHILDID_SELF)
- return S_OK;
-
- *disp_child = NULL;
- return S_FALSE;
-}
-
-STDMETHODIMP AutocompleteAccessibility::get_accParent(IDispatch** disp_parent) {
- if (!disp_parent) {
- return E_INVALIDARG;
- }
-
- if (omnibox_view_->parent_view() == NULL) {
- *disp_parent = NULL;
- return S_FALSE;
- }
-
- // Retrieve the IDispatch interface for the parent view.
- *disp_parent = omnibox_view_->parent_view()->GetNativeViewAccessible();
- // Increment the reference count for the retrieved interface.
- (*disp_parent)->AddRef();
- return S_OK;
-}
-
-STDMETHODIMP AutocompleteAccessibility::accNavigate(LONG nav_dir, VARIANT start,
- VARIANT* end) {
- if (start.vt != VT_I4 || !end) {
- return E_INVALIDARG;
- }
-
- DCHECK(default_accessibility_server_);
- return default_accessibility_server_->accNavigate(nav_dir, start, end);
-}
-
-STDMETHODIMP AutocompleteAccessibility::get_accFocus(VARIANT* focus_child) {
- if (!focus_child) {
- return E_INVALIDARG;
- }
-
- DCHECK(default_accessibility_server_);
- return default_accessibility_server_->get_accFocus(focus_child);
-}
-
-STDMETHODIMP AutocompleteAccessibility::get_accName(VARIANT var_id,
- BSTR* name) {
- if (var_id.vt != VT_I4 || !name) {
- return E_INVALIDARG;
- }
-
- string16 temp_name = l10n_util::GetStringUTF16(IDS_ACCNAME_LOCATION);
-
- if (!temp_name.empty()) {
- // Return name retrieved.
- *name = SysAllocString(temp_name.c_str());
- } else {
- // If no name is found, return S_FALSE.
- return S_FALSE;
- }
- DCHECK(*name);
-
- return S_OK;
-}
-
-STDMETHODIMP AutocompleteAccessibility::get_accDescription(VARIANT var_id,
- BSTR* desc) {
- if (var_id.vt != VT_I4 || !desc) {
- return E_INVALIDARG;
- }
-
- return S_FALSE;
-}
-
-STDMETHODIMP AutocompleteAccessibility::get_accValue(VARIANT var_id,
- BSTR* value) {
- if (var_id.vt != VT_I4 || !value) {
- return E_INVALIDARG;
- }
-
- string16 temp_value;
-
- if (var_id.lVal != CHILDID_SELF)
- return E_INVALIDARG;
-
- // Edit box has no children, only handle self.
- temp_value = omnibox_view_->GetText();
- if (temp_value.empty())
- return S_FALSE;
-
- // Return value retrieved.
- *value = SysAllocString(temp_value.c_str());
-
- DCHECK(*value);
-
- return S_OK;
-}
-
-STDMETHODIMP AutocompleteAccessibility::get_accState(VARIANT var_id,
- VARIANT* state) {
- if (var_id.vt != VT_I4 || !state) {
- return E_INVALIDARG;
- }
-
- DCHECK(default_accessibility_server_);
- HRESULT hr = default_accessibility_server_->get_accState(var_id, state);
-
- if (hr != S_OK)
- return hr;
-
- // Adding on state to convey the fact that there is a dropdown.
- state->lVal |= STATE_SYSTEM_HASPOPUP;
- return S_OK;
-}
-
-STDMETHODIMP AutocompleteAccessibility::get_accRole(VARIANT var_id,
- VARIANT* role) {
- if (var_id.vt != VT_I4 || !role) {
- return E_INVALIDARG;
- }
-
- role->vt = VT_I4;
-
- // Need to override the default role, which is ROLE_SYSTEM_CLIENT.
- if (var_id.lVal == CHILDID_SELF) {
- role->lVal = ROLE_SYSTEM_TEXT;
- } else {
- return S_FALSE;
- }
-
- return S_OK;
-}
-
-STDMETHODIMP AutocompleteAccessibility::get_accDefaultAction(VARIANT var_id,
- BSTR* def_action) {
- if (var_id.vt != VT_I4 || !def_action) {
- return E_INVALIDARG;
- }
-
- return S_FALSE;
-}
-
-STDMETHODIMP AutocompleteAccessibility::accLocation(LONG* x_left, LONG* y_top,
- LONG* width, LONG* height,
- VARIANT var_id) {
- if (var_id.vt != VT_I4 || !x_left || !y_top || !width || !height) {
- return E_INVALIDARG;
- }
-
- DCHECK(default_accessibility_server_);
- return default_accessibility_server_->accLocation(x_left, y_top, width,
- height, var_id);
-}
-
-STDMETHODIMP AutocompleteAccessibility::accHitTest(LONG x_left, LONG y_top,
- VARIANT* child) {
- if (!child) {
- return E_INVALIDARG;
- }
-
- DCHECK(default_accessibility_server_);
- return default_accessibility_server_->accHitTest(x_left, y_top, child);
-}
-
-STDMETHODIMP AutocompleteAccessibility::get_accKeyboardShortcut(VARIANT var_id,
- BSTR* acc_key) {
- if (var_id.vt != VT_I4 || !acc_key) {
- return E_INVALIDARG;
- }
-
- return S_FALSE;
-}
-
-// IAccessible functions not supported.
-
-HRESULT AutocompleteAccessibility::accDoDefaultAction(VARIANT var_id) {
- return DISP_E_MEMBERNOTFOUND;
-}
-
-STDMETHODIMP AutocompleteAccessibility::get_accSelection(VARIANT* selected) {
- if (selected)
- selected->vt = VT_EMPTY;
- return DISP_E_MEMBERNOTFOUND;
-}
-
-STDMETHODIMP AutocompleteAccessibility::accSelect(LONG flagsSelect,
- VARIANT var_id) {
- return DISP_E_MEMBERNOTFOUND;
-}
-
-STDMETHODIMP AutocompleteAccessibility::get_accHelp(VARIANT var_id,
- BSTR* help) {
- if (help)
- *help = NULL;
- return DISP_E_MEMBERNOTFOUND;
-}
-
-STDMETHODIMP AutocompleteAccessibility::get_accHelpTopic(BSTR* help_file,
- VARIANT var_id,
- LONG* topic_id) {
- if (help_file) {
- *help_file = NULL;
- }
- if (topic_id) {
- *topic_id = static_cast<LONG>(-1);
- }
- return DISP_E_MEMBERNOTFOUND;
-}
-
-STDMETHODIMP AutocompleteAccessibility::put_accName(VARIANT var_id,
- BSTR put_name) {
- // Deprecated.
- return DISP_E_MEMBERNOTFOUND;
-}
-
-STDMETHODIMP AutocompleteAccessibility::put_accValue(VARIANT var_id,
- BSTR put_val) {
- // Deprecated.
- return DISP_E_MEMBERNOTFOUND;
-}
diff --git a/chrome/browser/autocomplete/autocomplete_accessibility.h b/chrome/browser/autocomplete/autocomplete_accessibility.h
deleted file mode 100644
index abc6535..0000000
--- a/chrome/browser/autocomplete/autocomplete_accessibility.h
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright (c) 2011 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.
-
-#ifndef CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_ACCESSIBILITY_H_
-#define CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_ACCESSIBILITY_H_
-#pragma once
-
-#include <atlbase.h>
-#include <atlcom.h>
-#include <oleacc.h>
-
-#include "base/basictypes.h"
-#include "base/win/scoped_comptr.h"
-
-class OmniboxViewWin;
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// AutocompleteAccessibility
-//
-// Class implementing the MSAA IAccessible COM interface for
-// OmniboxViewWin, providing accessibility to be used by screen
-// readers and other assistive technology (AT).
-//
-////////////////////////////////////////////////////////////////////////////////
-class ATL_NO_VTABLE AutocompleteAccessibility
- : public CComObjectRootEx<CComMultiThreadModel>,
- public IDispatchImpl<IAccessible, &IID_IAccessible, &LIBID_Accessibility> {
- public:
- BEGIN_COM_MAP(AutocompleteAccessibility)
- COM_INTERFACE_ENTRY2(IDispatch, IAccessible)
- COM_INTERFACE_ENTRY(IAccessible)
- END_COM_MAP()
-
- AutocompleteAccessibility() {}
- ~AutocompleteAccessibility() {}
-
- HRESULT Initialize(const OmniboxViewWin* omnibox_view);
-
- // Supported IAccessible methods.
-
- // Retrieves the number of accessible children.
- STDMETHODIMP get_accChildCount(LONG* child_count);
-
- // Retrieves an IDispatch interface pointer for the specified child.
- STDMETHODIMP get_accChild(VARIANT var_child, IDispatch** disp_child);
-
- // Retrieves the IDispatch interface of the object's parent.
- STDMETHODIMP get_accParent(IDispatch** disp_parent);
-
- // Traverses to another UI element and retrieves the object.
- STDMETHODIMP accNavigate(LONG nav_dir, VARIANT start, VARIANT* end);
-
- // Retrieves the object that has the keyboard focus.
- STDMETHODIMP get_accFocus(VARIANT* focus_child);
-
- // Retrieves the name of the specified object.
- STDMETHODIMP get_accName(VARIANT var_id, BSTR* name);
-
- // Retrieves the tooltip description.
- STDMETHODIMP get_accDescription(VARIANT var_id, BSTR* desc);
-
- // Returns the current value of the edit box.
- STDMETHODIMP get_accValue(VARIANT var_id, BSTR* value);
-
- // Retrieves the current state of the specified object.
- STDMETHODIMP get_accState(VARIANT var_id, VARIANT* state);
-
- // Retrieves information describing the role of the specified object.
- STDMETHODIMP get_accRole(VARIANT var_id, VARIANT* role);
-
- // Retrieves a string that describes the object's default action.
- STDMETHODIMP get_accDefaultAction(VARIANT var_id, BSTR* default_action);
-
- // Retrieves the specified object's current screen location.
- STDMETHODIMP accLocation(LONG* x_left, LONG* y_top, LONG* width, LONG* height,
- VARIANT var_id);
-
- // Retrieves the child element or child object at a given point on the screen.
- STDMETHODIMP accHitTest(LONG x_left, LONG y_top, VARIANT* child);
-
- // Retrieves the specified object's shortcut.
- STDMETHODIMP get_accKeyboardShortcut(VARIANT var_id, BSTR* access_key);
-
- // Non-supported IAccessible methods.
-
- // Out-dated and can be safely said to be very rarely used.
- STDMETHODIMP accDoDefaultAction(VARIANT var_id);
-
- // Selections not applicable to views.
- STDMETHODIMP get_accSelection(VARIANT* selected);
- STDMETHODIMP accSelect(LONG flags_sel, VARIANT var_id);
-
- // Help functions not supported.
- STDMETHODIMP get_accHelp(VARIANT var_id, BSTR* help);
- STDMETHODIMP get_accHelpTopic(BSTR* help_file, VARIANT var_id,
- LONG* topic_id);
-
- // Deprecated functions, not implemented here.
- STDMETHODIMP put_accName(VARIANT var_id, BSTR put_name);
- STDMETHODIMP put_accValue(VARIANT var_id, BSTR put_val);
-
- protected:
- // A pointer containing the Windows' default IAccessible implementation for
- // this object. Used where it is acceptable to return default MSAA
- // information.
- base::win::ScopedComPtr<IAccessible> default_accessibility_server_;
-
- private:
- const OmniboxViewWin* omnibox_view_;
-
- DISALLOW_COPY_AND_ASSIGN(AutocompleteAccessibility);
-};
-
-#endif // CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_ACCESSIBILITY_H_
diff --git a/chrome/browser/autocomplete/autocomplete_edit_unittest.cc b/chrome/browser/autocomplete/autocomplete_edit_unittest.cc
index 7c44cf5..07531da 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_unittest.cc
+++ b/chrome/browser/autocomplete/autocomplete_edit_unittest.cc
@@ -37,7 +37,7 @@ class TestingOmniboxView : public OmniboxView {
virtual void SetForcedQuery() {}
virtual bool IsSelectAll() { return false; }
virtual bool DeleteAtEndPressed() { return false; }
- virtual void GetSelectionBounds(size_t* start, size_t* end) {}
+ virtual void GetSelectionBounds(size_t* start, size_t* end) const {}
virtual void SelectAll(bool reversed) {}
virtual void RevertAll() {}
virtual void UpdatePopup() {}
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h
index 80c2ce1..aed6ec3 100644
--- a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h
@@ -66,7 +66,7 @@ class OmniboxViewMac : public OmniboxView,
virtual bool IsSelectAll() OVERRIDE;
virtual bool DeleteAtEndPressed() OVERRIDE;
virtual void GetSelectionBounds(string16::size_type* start,
- string16::size_type* end) OVERRIDE;
+ string16::size_type* end) const OVERRIDE;
virtual void SelectAll(bool reversed) OVERRIDE;
virtual void RevertAll() OVERRIDE;
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm
index 162ec85..46051c6 100644
--- a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm
@@ -391,7 +391,7 @@ bool OmniboxViewMac::DeleteAtEndPressed() {
}
void OmniboxViewMac::GetSelectionBounds(string16::size_type* start,
- string16::size_type* end) {
+ string16::size_type* end) const {
if (![field_ currentEditor]) {
*start = *end = 0;
return;
diff --git a/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.cc b/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.cc
index 9f201d1..9e62c5c 100644
--- a/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.cc
+++ b/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.cc
@@ -591,7 +591,7 @@ bool OmniboxViewGtk::DeleteAtEndPressed() {
}
void OmniboxViewGtk::GetSelectionBounds(string16::size_type* start,
- string16::size_type* end) {
+ string16::size_type* end) const {
CharRange selection = GetSelection();
*start = static_cast<size_t>(selection.cp_min);
*end = static_cast<size_t>(selection.cp_max);
diff --git a/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.h b/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.h
index aaf240f..fc9ca4a 100644
--- a/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.h
+++ b/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.h
@@ -120,7 +120,7 @@ class OmniboxViewGtk : public OmniboxView,
virtual bool IsSelectAll() OVERRIDE;
virtual bool DeleteAtEndPressed() OVERRIDE;
virtual void GetSelectionBounds(string16::size_type* start,
- string16::size_type* end) OVERRIDE;
+ string16::size_type* end) const OVERRIDE;
virtual void SelectAll(bool reversed) OVERRIDE;
virtual void RevertAll() OVERRIDE;
diff --git a/chrome/browser/ui/omnibox/omnibox_view.h b/chrome/browser/ui/omnibox/omnibox_view.h
index dd5d792..5563e9c 100644
--- a/chrome/browser/ui/omnibox/omnibox_view.h
+++ b/chrome/browser/ui/omnibox/omnibox_view.h
@@ -109,7 +109,7 @@ class OmniboxView {
// It is not guaranteed that |*start < *end|, as the selection can be
// directed. If there is no selection, |start| and |end| will both be equal
// to the current cursor position.
- virtual void GetSelectionBounds(size_t* start, size_t* end) = 0;
+ virtual void GetSelectionBounds(size_t* start, size_t* end) const = 0;
// Selects all the text in the edit. Use this in place of SetSelAll() to
// avoid selecting the "phantom newline" at the end of the edit.
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
index f958484..56a72dc 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -428,7 +428,7 @@ bool OmniboxViewViews::DeleteAtEndPressed() {
}
void OmniboxViewViews::GetSelectionBounds(string16::size_type* start,
- string16::size_type* end) {
+ string16::size_type* end) const {
ui::Range range;
textfield_->GetSelectedRange(&range);
*start = static_cast<size_t>(range.end());
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.h b/chrome/browser/ui/views/omnibox/omnibox_view_views.h
index 2db5ed3..0be13c1 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views.h
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.h
@@ -99,7 +99,7 @@ class OmniboxViewViews : public views::View,
virtual bool IsSelectAll() OVERRIDE;
virtual bool DeleteAtEndPressed() OVERRIDE;
virtual void GetSelectionBounds(string16::size_type* start,
- string16::size_type* end) OVERRIDE;
+ string16::size_type* end) const OVERRIDE;
virtual void SelectAll(bool reversed) OVERRIDE;
virtual void RevertAll() OVERRIDE;
virtual void UpdatePopup() OVERRIDE;
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_win.cc b/chrome/browser/ui/views/omnibox/omnibox_view_win.cc
index 089503d..af656c3 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_win.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_win.cc
@@ -20,7 +20,6 @@
#include "base/utf_string_conversions.h"
#include "base/win/iat_patch_function.h"
#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/autocomplete/autocomplete_accessibility.h"
#include "chrome/browser/autocomplete/autocomplete_match.h"
#include "chrome/browser/autocomplete/autocomplete_popup_model.h"
#include "chrome/browser/autocomplete/keyword_provider.h"
@@ -37,6 +36,7 @@
#include "grit/generated_resources.h"
#include "net/base/escape.h"
#include "skia/ext/skia_utils_win.h"
+#include "ui/base/accessibility/accessible_view_state.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/base/dragdrop/drag_drop_types.h"
@@ -306,6 +306,39 @@ OmniboxViewWin::ScopedSuspendUndo::~ScopedSuspendUndo() {
text_object_model_->Undo(tomResume, NULL);
}
+// A subclass of NativeViewHost that provides accessibility info for the
+// underlying Omnibox view.
+class OmniboxViewWrapper : public views::NativeViewHost {
+ public:
+ explicit OmniboxViewWrapper(OmniboxViewWin* omnibox_view_win)
+ : omnibox_view_win_(omnibox_view_win) {}
+
+ gfx::NativeViewAccessible GetNativeViewAccessible() {
+ // This forces it to use NativeViewAccessibilityWin rather than
+ // any accessibility provided natively by the HWND.
+ return View::GetNativeViewAccessible();
+ }
+
+ // views::View
+ virtual void GetAccessibleState(ui::AccessibleViewState* state) {
+ views::NativeViewHost::GetAccessibleState(state);
+ state->name = l10n_util::GetStringUTF16(IDS_ACCNAME_LOCATION);
+ state->role = ui::AccessibilityTypes::ROLE_TEXT;
+ state->value = omnibox_view_win_->GetText();
+ state->state = ui::AccessibilityTypes::STATE_EDITABLE;
+ size_t sel_start;
+ size_t sel_end;
+ omnibox_view_win_->GetSelectionBounds(&sel_start, &sel_end);
+ state->selection_start = sel_start;
+ state->selection_end = sel_end;
+ }
+
+ private:
+ OmniboxViewWin* omnibox_view_win_;
+
+ DISALLOW_COPY_AND_ASSIGN(OmniboxViewWrapper);
+};
+
///////////////////////////////////////////////////////////////////////////////
// OmniboxViewWin
@@ -671,7 +704,7 @@ bool OmniboxViewWin::DeleteAtEndPressed() {
}
void OmniboxViewWin::GetSelectionBounds(string16::size_type* start,
- string16::size_type* end) {
+ string16::size_type* end) const {
CHARRANGE selection;
GetSel(selection);
*start = static_cast<size_t>(selection.cpMin);
@@ -733,27 +766,6 @@ void OmniboxViewWin::SetFocus() {
::SetFocus(m_hWnd);
}
-IAccessible* OmniboxViewWin::GetIAccessible() {
- if (!autocomplete_accessibility_) {
- CComObject<AutocompleteAccessibility>* accessibility = NULL;
- if (!SUCCEEDED(CComObject<AutocompleteAccessibility>::CreateInstance(
- &accessibility)) || !accessibility)
- return NULL;
-
- // Wrap the created object in a smart pointer so it won't leak.
- base::win::ScopedComPtr<IAccessible> accessibility_comptr(accessibility);
- if (!SUCCEEDED(accessibility->Initialize(this)))
- return NULL;
-
- // Copy to the class smart pointer, and notify that an instance of
- // IAccessible was allocated for m_hWnd.
- autocomplete_accessibility_ = accessibility_comptr;
- NotifyWinEvent(EVENT_OBJECT_CREATE, m_hWnd, OBJID_CLIENT, CHILDID_SELF);
- }
- // Detach to leave ref counting to the caller.
- return autocomplete_accessibility_.Detach();
-}
-
void OmniboxViewWin::SetDropHighlightPosition(int position) {
if (drop_highlight_position_ != position) {
RepaintDropHighlight(drop_highlight_position_);
@@ -894,12 +906,14 @@ bool OmniboxViewWin::OnAfterPossibleChangeInternal(bool force_text_changed) {
if (text_differs) {
// Note that a TEXT_CHANGED event implies that the cursor/selection
// probably changed too, so we don't need to send both.
- parent_view_->GetWidget()->NotifyAccessibilityEvent(
- parent_view_, ui::AccessibilityTypes::EVENT_TEXT_CHANGED, true);
+ native_view_host_->GetWidget()->NotifyAccessibilityEvent(
+ native_view_host_, ui::AccessibilityTypes::EVENT_TEXT_CHANGED, true);
} else if (selection_differs) {
// Notify assistive technology that the cursor or selection changed.
- parent_view_->GetWidget()->NotifyAccessibilityEvent(
- parent_view_, ui::AccessibilityTypes::EVENT_SELECTION_CHANGED, true);
+ native_view_host_->GetWidget()->NotifyAccessibilityEvent(
+ native_view_host_,
+ ui::AccessibilityTypes::EVENT_SELECTION_CHANGED,
+ true);
} else if (delete_at_end_pressed_) {
model_->OnChanged();
}
@@ -956,11 +970,11 @@ bool OmniboxViewWin::IsImeComposing() const {
}
views::View* OmniboxViewWin::AddToView(views::View* parent) {
- views::NativeViewHost* host = new views::NativeViewHost;
- parent->AddChildView(host);
- host->set_focus_view(parent);
- host->Attach(GetNativeView());
- return host;
+ native_view_host_ = new OmniboxViewWrapper(this);
+ parent->AddChildView(native_view_host_);
+ native_view_host_->set_focus_view(parent);
+ native_view_host_->Attach(GetNativeView());
+ return native_view_host_;
}
int OmniboxViewWin::OnPerformDrop(const views::DropTargetEvent& event) {
@@ -1339,18 +1353,13 @@ void OmniboxViewWin::OnCut() {
ReplaceSel(L"", true);
}
-LRESULT OmniboxViewWin::OnGetObject(UINT uMsg,
+LRESULT OmniboxViewWin::OnGetObject(UINT message,
WPARAM wparam,
LPARAM lparam) {
- // Accessibility readers will send an OBJID_CLIENT message.
+ // This is a request for the native accessibility object.
if (lparam == OBJID_CLIENT) {
- // Re-attach for internal re-usage of accessibility pointer.
- autocomplete_accessibility_.Attach(GetIAccessible());
-
- if (autocomplete_accessibility_) {
- return LresultFromObject(IID_IAccessible, wparam,
- autocomplete_accessibility_);
- }
+ return LresultFromObject(IID_IAccessible, wparam,
+ native_view_host_->GetNativeViewAccessible());
}
return 0;
}
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_win.h b/chrome/browser/ui/views/omnibox/omnibox_view_win.h
index 5e9ea28..cf0e302 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_win.h
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_win.h
@@ -31,6 +31,7 @@ class LocationBarView;
class TabContents;
namespace views {
+class NativeViewHost;
class View;
}
@@ -117,7 +118,7 @@ class OmniboxViewWin
virtual bool IsSelectAll() OVERRIDE;
virtual bool DeleteAtEndPressed() OVERRIDE;
virtual void GetSelectionBounds(string16::size_type* start,
- string16::size_type* end) OVERRIDE;
+ string16::size_type* end) const OVERRIDE;
virtual void SelectAll(bool reversed) OVERRIDE;
virtual void RevertAll() OVERRIDE;
@@ -148,9 +149,6 @@ class OmniboxViewWin
int GetPopupMaxYCoordinate();
- // Exposes custom IAccessible implementation to the overall MSAA hierarchy.
- IAccessible* GetIAccessible();
-
void SetDropHighlightPosition(int position);
int drop_highlight_position() const { return drop_highlight_position_; }
@@ -283,7 +281,7 @@ class OmniboxViewWin
void OnContextMenu(HWND window, const CPoint& point);
void OnCopy();
void OnCut();
- LRESULT OnGetObject(UINT uMsg, WPARAM wparam, LPARAM lparam);
+ LRESULT OnGetObject(UINT message, WPARAM wparam, LPARAM lparam);
LRESULT OnImeComposition(UINT message, WPARAM wparam, LPARAM lparam);
LRESULT OnImeNotify(UINT message, WPARAM wparam, LPARAM lparam);
void OnKeyDown(TCHAR key, UINT repeat_count, UINT flags);
@@ -550,6 +548,9 @@ class OmniboxViewWin
// Instance of accessibility information and handling.
mutable base::win::ScopedComPtr<IAccessible> autocomplete_accessibility_;
+ // The native view host.
+ views::NativeViewHost* native_view_host_;
+
DISALLOW_COPY_AND_ASSIGN(OmniboxViewWin);
};
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 0b93e23..94cee8b 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -89,8 +89,6 @@
'browser/app_icon_win.h',
'browser/autocomplete/autocomplete.cc',
'browser/autocomplete/autocomplete.h',
- 'browser/autocomplete/autocomplete_accessibility.cc',
- 'browser/autocomplete/autocomplete_accessibility.h',
'browser/autocomplete/autocomplete_classifier.cc',
'browser/autocomplete/autocomplete_classifier.h',
'browser/autocomplete/autocomplete_controller_delegate.h',
@@ -5100,7 +5098,6 @@
'browser/accessibility/browser_accessibility_win.cc',
'browser/accessibility/browser_accessibility_win.h',
'browser/aeropeek_manager.cc',
- 'browser/autocomplete/autocomplete_accessibility.cc',
'browser/extensions/extension_tts_api_win.cc',
'browser/google/google_update.cc',
'browser/importer/ie_importer.cc',
diff --git a/ui/base/accessibility/accessibility_types.h b/ui/base/accessibility/accessibility_types.h
index 2d11908..06e878e 100644
--- a/ui/base/accessibility/accessibility_types.h
+++ b/ui/base/accessibility/accessibility_types.h
@@ -22,32 +22,33 @@ class AccessibilityTypes {
public:
// This defines states of the supported accessibility roles in our
- // Views (e.g. used in View::GetAccessibleState). Any interface using roles
- // must provide a conversion to its own roles (see e.g.
- // ViewAccessibility::get_accState and ViewAccessibility::MSAAState).
+ // Views (e.g. used in View::GetAccessibleState). Any interface using states
+ // must provide a conversion to its own states (see e.g.
+ // NativeViewAccessibilityWin::get_accState).
typedef uint32 State;
enum StateFlag {
STATE_CHECKED = 1 << 0,
STATE_COLLAPSED = 1 << 1,
STATE_DEFAULT = 1 << 2,
- STATE_EXPANDED = 1 << 3,
- STATE_HASPOPUP = 1 << 4,
- STATE_HOTTRACKED = 1 << 5,
- STATE_INVISIBLE = 1 << 6,
- STATE_LINKED = 1 << 7,
- STATE_OFFSCREEN = 1 << 8,
- STATE_PRESSED = 1 << 9,
- STATE_PROTECTED = 1 << 10,
- STATE_READONLY = 1 << 11,
- STATE_SELECTED = 1 << 12,
- STATE_FOCUSED = 1 << 13,
- STATE_UNAVAILABLE = 1 << 14
+ STATE_EDITABLE = 1 << 3,
+ STATE_EXPANDED = 1 << 4,
+ STATE_FOCUSED = 1 << 5,
+ STATE_HASPOPUP = 1 << 6,
+ STATE_HOTTRACKED = 1 << 7,
+ STATE_INVISIBLE = 1 << 8,
+ STATE_LINKED = 1 << 9,
+ STATE_OFFSCREEN = 1 << 10,
+ STATE_PRESSED = 1 << 11,
+ STATE_PROTECTED = 1 << 12,
+ STATE_READONLY = 1 << 13,
+ STATE_SELECTED = 1 << 14,
+ STATE_UNAVAILABLE = 1 << 15
};
// This defines an enumeration of the supported accessibility roles in our
// Views (e.g. used in View::GetAccessibleRole). Any interface using roles
// must provide a conversion to its own roles (see e.g.
- // ViewAccessibility::get_accRole and ViewAccessibility::MSAARole).
+ // NativeViewAccessibilityWin::get_accRole).
enum Role {
ROLE_ALERT,
ROLE_APPLICATION,
diff --git a/views/DEPS b/views/DEPS
index 5811123..b0e0589 100644
--- a/views/DEPS
+++ b/views/DEPS
@@ -5,5 +5,6 @@ include_rules = [
"+grit/ui_strings.h",
"+skia/ext",
"+net",
+ "+third_party/iaccessible2",
"+ui",
]
diff --git a/views/accessibility/native_view_accessibility_win.cc b/views/accessibility/native_view_accessibility_win.cc
index 4342517..064f181 100644
--- a/views/accessibility/native_view_accessibility_win.cc
+++ b/views/accessibility/native_view_accessibility_win.cc
@@ -2,8 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <atlbase.h>
+#include <atlcom.h>
+
#include "views/accessibility/native_view_accessibility_win.h"
+#include "third_party/iaccessible2/ia2_api_all.h"
#include "ui/base/accessibility/accessible_view_state.h"
#include "ui/base/view_prop.h"
#include "views/widget/native_widget_win.h"
@@ -11,10 +15,8 @@
using ui::AccessibilityTypes;
-namespace views {
-const char kViewsNativeHostPropForAccessibility[] =
- "Views_NativeViewHostHWNDForAccessibility";
-}
+// static
+long NativeViewAccessibilityWin::next_unique_id_ = 1;
// static
scoped_refptr<NativeViewAccessibilityWin> NativeViewAccessibilityWin::Create(
@@ -27,7 +29,9 @@ scoped_refptr<NativeViewAccessibilityWin> NativeViewAccessibilityWin::Create(
return scoped_refptr<NativeViewAccessibilityWin>(instance);
}
-NativeViewAccessibilityWin::NativeViewAccessibilityWin() : view_(NULL) {
+NativeViewAccessibilityWin::NativeViewAccessibilityWin()
+ : view_(NULL),
+ unique_id_(next_unique_id_++) {
}
NativeViewAccessibilityWin::~NativeViewAccessibilityWin() {
@@ -417,6 +421,9 @@ STDMETHODIMP NativeViewAccessibilityWin::get_accRole(
STDMETHODIMP NativeViewAccessibilityWin::get_accState(
VARIANT var_id, VARIANT* state) {
+ // This returns MSAA states. See also the IAccessible2 interface
+ // get_states().
+
if (!IsValidId(var_id) || !state)
return E_INVALIDARG;
@@ -460,62 +467,6 @@ STDMETHODIMP NativeViewAccessibilityWin::get_accValue(
return S_OK;
}
-// Helper functions.
-
-bool NativeViewAccessibilityWin::IsNavDirNext(int nav_dir) const {
- if (nav_dir == NAVDIR_RIGHT || nav_dir == NAVDIR_DOWN ||
- nav_dir == NAVDIR_NEXT) {
- return true;
- }
- return false;
-}
-
-bool NativeViewAccessibilityWin::IsValidNav(
- int nav_dir, int start_id, int lower_bound, int upper_bound) const {
- if (IsNavDirNext(nav_dir)) {
- if ((start_id + 1) > upper_bound) {
- return false;
- }
- } else {
- if ((start_id - 1) <= lower_bound) {
- return false;
- }
- }
- return true;
-}
-
-bool NativeViewAccessibilityWin::IsValidId(const VARIANT& child) const {
- // View accessibility returns an IAccessible for each view so we only support
- // the CHILDID_SELF id.
- return (VT_I4 == child.vt) && (CHILDID_SELF == child.lVal);
-}
-
-void NativeViewAccessibilityWin::SetState(
- VARIANT* msaa_state, views::View* view) {
- // Ensure the output param is initialized to zero.
- msaa_state->lVal = 0;
-
- // Default state; all views can have accessibility focus.
- msaa_state->lVal |= STATE_SYSTEM_FOCUSABLE;
-
- if (!view)
- return;
-
- if (!view->IsEnabled())
- msaa_state->lVal |= STATE_SYSTEM_UNAVAILABLE;
- if (!view->IsVisible())
- msaa_state->lVal |= STATE_SYSTEM_INVISIBLE;
- if (view->IsHotTracked())
- msaa_state->lVal |= STATE_SYSTEM_HOTTRACKED;
- if (view->HasFocus())
- msaa_state->lVal |= STATE_SYSTEM_FOCUSED;
-
- // Add on any view-specific states.
- ui::AccessibleViewState view_state;
- view->GetAccessibleState(&view_state);
- msaa_state->lVal |= MSAAState(view_state.state);
-}
-
// IAccessible functions not supported.
STDMETHODIMP NativeViewAccessibilityWin::get_accSelection(VARIANT* selected) {
@@ -559,6 +510,211 @@ STDMETHODIMP NativeViewAccessibilityWin::put_accValue(
return E_NOTIMPL;
}
+//
+// IAccessible2
+//
+
+STDMETHODIMP NativeViewAccessibilityWin::role(LONG* role) {
+ if (!view_)
+ return E_FAIL;
+
+ if (!role)
+ return E_INVALIDARG;
+
+ ui::AccessibleViewState state;
+ view_->GetAccessibleState(&state);
+ *role = MSAARole(state.role);
+ return S_OK;
+}
+
+STDMETHODIMP NativeViewAccessibilityWin::get_states(AccessibleStates* states) {
+ // This returns IAccessible2 states, which supplement MSAA states.
+ // See also the MSAA interface get_accState.
+
+ if (!view_)
+ return E_FAIL;
+
+ if (!states)
+ return E_INVALIDARG;
+
+ ui::AccessibleViewState state;
+ view_->GetAccessibleState(&state);
+
+ // There are only a couple of states we need to support
+ // in IAccessible2. If any more are added, we may want to
+ // add a helper function like MSAAState.
+ *states = IA2_STATE_OPAQUE;
+ if (state.state & AccessibilityTypes::STATE_EDITABLE)
+ *states |= IA2_STATE_EDITABLE;
+
+ return S_OK;
+}
+
+STDMETHODIMP NativeViewAccessibilityWin::get_uniqueID(LONG* unique_id) {
+ if (!view_)
+ return E_FAIL;
+
+ if (!unique_id)
+ return E_INVALIDARG;
+
+ *unique_id = unique_id_;
+ return S_OK;
+}
+
+STDMETHODIMP NativeViewAccessibilityWin::get_windowHandle(HWND* window_handle) {
+ if (!view_)
+ return E_FAIL;
+
+ if (!window_handle)
+ return E_INVALIDARG;
+
+ *window_handle = view_->GetWidget()->GetNativeView();
+ return S_OK;
+}
+
+//
+// IAccessibleText
+//
+
+STDMETHODIMP NativeViewAccessibilityWin::get_nCharacters(LONG* n_characters) {
+ if (!view_)
+ return E_FAIL;
+
+ if (!n_characters)
+ return E_INVALIDARG;
+
+ string16 text = TextForIAccessibleText();
+ *n_characters = static_cast<LONG>(text.size());
+ return S_OK;
+}
+
+STDMETHODIMP NativeViewAccessibilityWin::get_caretOffset(LONG* offset) {
+ if (!view_)
+ return E_FAIL;
+
+ if (!offset)
+ return E_INVALIDARG;
+
+ ui::AccessibleViewState state;
+ view_->GetAccessibleState(&state);
+ *offset = static_cast<LONG>(state.selection_end);
+ return S_OK;
+}
+
+STDMETHODIMP NativeViewAccessibilityWin::get_nSelections(LONG* n_selections) {
+ if (!view_)
+ return E_FAIL;
+
+ if (!n_selections)
+ return E_INVALIDARG;
+
+ ui::AccessibleViewState state;
+ view_->GetAccessibleState(&state);
+ if (state.selection_start != state.selection_end)
+ *n_selections = 1;
+ else
+ *n_selections = 0;
+ return S_OK;
+}
+
+STDMETHODIMP NativeViewAccessibilityWin::get_selection(LONG selection_index,
+ LONG* start_offset,
+ LONG* end_offset) {
+ if (!view_)
+ return E_FAIL;
+
+ if (!start_offset || !end_offset || selection_index != 0)
+ return E_INVALIDARG;
+
+ ui::AccessibleViewState state;
+ view_->GetAccessibleState(&state);
+ *start_offset = static_cast<LONG>(state.selection_start);
+ *end_offset = static_cast<LONG>(state.selection_end);
+ return S_OK;
+}
+
+STDMETHODIMP NativeViewAccessibilityWin::get_text(LONG start_offset,
+ LONG end_offset,
+ BSTR* text) {
+ if (!view_)
+ return E_FAIL;
+
+ ui::AccessibleViewState state;
+ view_->GetAccessibleState(&state);
+ string16 text_str = TextForIAccessibleText();
+ LONG len = static_cast<LONG>(text_str.size());
+
+ if (start_offset == IA2_TEXT_OFFSET_LENGTH) {
+ start_offset = len;
+ } else if (start_offset == IA2_TEXT_OFFSET_CARET) {
+ start_offset = static_cast<LONG>(state.selection_end);
+ }
+ if (end_offset == IA2_TEXT_OFFSET_LENGTH) {
+ end_offset = static_cast<LONG>(text_str.size());
+ } else if (end_offset == IA2_TEXT_OFFSET_CARET) {
+ end_offset = static_cast<LONG>(state.selection_end);
+ }
+
+ // The spec allows the arguments to be reversed.
+ if (start_offset > end_offset) {
+ LONG tmp = start_offset;
+ start_offset = end_offset;
+ end_offset = tmp;
+ }
+
+ // The spec does not allow the start or end offsets to be out or range;
+ // we must return an error if so.
+ if (start_offset < 0)
+ return E_INVALIDARG;
+ if (end_offset > len)
+ return E_INVALIDARG;
+
+ string16 substr = text_str.substr(start_offset, end_offset - start_offset);
+ if (substr.empty())
+ return S_FALSE;
+
+ *text = SysAllocString(substr.c_str());
+ DCHECK(*text);
+ return S_OK;
+}
+
+STDMETHODIMP NativeViewAccessibilityWin::get_offsetAtPoint(
+ LONG x, LONG y, enum IA2CoordinateType coord_type, LONG* offset) {
+ if (!view_)
+ return E_FAIL;
+
+ if (!offset)
+ return E_INVALIDARG;
+
+ // We don't support this method, but we have to return something
+ // rather than E_NOTIMPL or screen readers will complain.
+ *offset = 0;
+ return S_OK;
+}
+
+//
+// IServiceProvider methods.
+//
+
+STDMETHODIMP NativeViewAccessibilityWin::QueryService(
+ REFGUID guidService, REFIID riid, void** object) {
+ if (!view_)
+ return E_FAIL;
+
+ if (guidService == IID_IAccessible ||
+ guidService == IID_IAccessible2 ||
+ guidService == IID_IAccessibleText) {
+ return QueryInterface(riid, object);
+ }
+
+ *object = NULL;
+ return E_FAIL;
+}
+
+//
+// Static methods.
+//
+
int32 NativeViewAccessibilityWin::MSAAEvent(AccessibilityTypes::Event event) {
switch (event) {
case AccessibilityTypes::EVENT_ALERT:
@@ -578,7 +734,7 @@ int32 NativeViewAccessibilityWin::MSAAEvent(AccessibilityTypes::Event event) {
case AccessibilityTypes::EVENT_TEXT_CHANGED:
return EVENT_OBJECT_VALUECHANGE;
case AccessibilityTypes::EVENT_SELECTION_CHANGED:
- return EVENT_OBJECT_TEXTSELECTIONCHANGED;
+ return IA2_EVENT_TEXT_CARET_MOVED;
case AccessibilityTypes::EVENT_VALUE_CHANGED:
return EVENT_OBJECT_VALUECHANGE;
default:
@@ -656,6 +812,9 @@ return ROLE_SYSTEM_ALERT;
}
int32 NativeViewAccessibilityWin::MSAAState(AccessibilityTypes::State state) {
+ // This maps MSAA states for get_accState(). See also the IAccessible2
+ // interface get_states().
+
int32 msaa_state = 0;
if (state & AccessibilityTypes::STATE_CHECKED)
msaa_state |= STATE_SYSTEM_CHECKED;
@@ -689,3 +848,68 @@ int32 NativeViewAccessibilityWin::MSAAState(AccessibilityTypes::State state) {
msaa_state |= STATE_SYSTEM_UNAVAILABLE;
return msaa_state;
}
+
+//
+// Private methods.
+//
+
+bool NativeViewAccessibilityWin::IsNavDirNext(int nav_dir) const {
+ return (nav_dir == NAVDIR_RIGHT ||
+ nav_dir == NAVDIR_DOWN ||
+ nav_dir == NAVDIR_NEXT);
+}
+
+bool NativeViewAccessibilityWin::IsValidNav(
+ int nav_dir, int start_id, int lower_bound, int upper_bound) const {
+ if (IsNavDirNext(nav_dir)) {
+ if ((start_id + 1) > upper_bound) {
+ return false;
+ }
+ } else {
+ if ((start_id - 1) <= lower_bound) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool NativeViewAccessibilityWin::IsValidId(const VARIANT& child) const {
+ // View accessibility returns an IAccessible for each view so we only support
+ // the CHILDID_SELF id.
+ return (VT_I4 == child.vt) && (CHILDID_SELF == child.lVal);
+}
+
+void NativeViewAccessibilityWin::SetState(
+ VARIANT* msaa_state, views::View* view) {
+ // Ensure the output param is initialized to zero.
+ msaa_state->lVal = 0;
+
+ // Default state; all views can have accessibility focus.
+ msaa_state->lVal |= STATE_SYSTEM_FOCUSABLE;
+
+ if (!view)
+ return;
+
+ if (!view->IsEnabled())
+ msaa_state->lVal |= STATE_SYSTEM_UNAVAILABLE;
+ if (!view->IsVisible())
+ msaa_state->lVal |= STATE_SYSTEM_INVISIBLE;
+ if (view->IsHotTracked())
+ msaa_state->lVal |= STATE_SYSTEM_HOTTRACKED;
+ if (view->HasFocus())
+ msaa_state->lVal |= STATE_SYSTEM_FOCUSED;
+
+ // Add on any view-specific states.
+ ui::AccessibleViewState view_state;
+ view->GetAccessibleState(&view_state);
+ msaa_state->lVal |= MSAAState(view_state.state);
+}
+
+string16 NativeViewAccessibilityWin::TextForIAccessibleText() {
+ ui::AccessibleViewState state;
+ view_->GetAccessibleState(&state);
+ if (state.role == AccessibilityTypes::ROLE_TEXT)
+ return state.value;
+ else
+ return state.name;
+}
diff --git a/views/accessibility/native_view_accessibility_win.h b/views/accessibility/native_view_accessibility_win.h
index 2736160..395ae5b 100644
--- a/views/accessibility/native_view_accessibility_win.h
+++ b/views/accessibility/native_view_accessibility_win.h
@@ -12,6 +12,7 @@
#include <oleacc.h>
#include "base/memory/scoped_ptr.h"
+#include "third_party/iaccessible2/ia2_api_all.h"
#include "ui/base/accessibility/accessible_view_state.h"
#include "views/controls/native/native_view_host.h"
#include "views/view.h"
@@ -28,13 +29,20 @@
// technology (AT).
//
////////////////////////////////////////////////////////////////////////////////
-class ATL_NO_VTABLE NativeViewAccessibilityWin
+class __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
+NativeViewAccessibilityWin
: public CComObjectRootEx<CComMultiThreadModel>,
- public IDispatchImpl<IAccessible, &IID_IAccessible, &LIBID_Accessibility> {
+ public IDispatchImpl<IAccessible2, &IID_IAccessible2,
+ &LIBID_IAccessible2Lib>,
+ public IAccessibleText,
+ public IServiceProvider {
public:
BEGIN_COM_MAP(NativeViewAccessibilityWin)
- COM_INTERFACE_ENTRY2(IDispatch, IAccessible)
- COM_INTERFACE_ENTRY(IAccessible)
+ COM_INTERFACE_ENTRY2(IDispatch, IAccessible2)
+ COM_INTERFACE_ENTRY2(IAccessible, IAccessible2)
+ COM_INTERFACE_ENTRY(IAccessible2)
+ COM_INTERFACE_ENTRY(IAccessibleText)
+ COM_INTERFACE_ENTRY(IServiceProvider)
END_COM_MAP()
// Create method for view accessibility.
@@ -111,6 +119,171 @@ class ATL_NO_VTABLE NativeViewAccessibilityWin
STDMETHODIMP put_accName(VARIANT var_id, BSTR put_name);
STDMETHODIMP put_accValue(VARIANT var_id, BSTR put_val);
+ //
+ // IAccessible2
+ //
+
+ STDMETHODIMP role(LONG* role);
+
+ STDMETHODIMP get_states(AccessibleStates* states);
+
+ STDMETHODIMP get_uniqueID(LONG* unique_id);
+
+ STDMETHODIMP get_windowHandle(HWND* window_handle);
+
+ //
+ // IAccessible2 methods not implemented.
+ //
+
+ STDMETHODIMP get_attributes(BSTR* attributes) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP get_indexInParent(LONG* index_in_parent) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP get_extendedRole(BSTR* extended_role) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP get_nRelations(LONG* n_relations) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP get_relation(LONG relation_index,
+ IAccessibleRelation** relation) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP get_relations(LONG max_relations,
+ IAccessibleRelation** relations,
+ LONG* n_relations) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP scrollTo(enum IA2ScrollType scroll_type) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP scrollToPoint(
+ enum IA2CoordinateType coordinate_type,
+ LONG x,
+ LONG y) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP get_groupPosition(LONG* group_level,
+ LONG* similar_items_in_group,
+ LONG* position_in_group) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP get_localizedExtendedRole(
+ BSTR* localized_extended_role) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP get_nExtendedStates(LONG* n_extended_states) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP get_extendedStates(LONG max_extended_states,
+ BSTR** extended_states,
+ LONG* n_extended_states) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP get_localizedExtendedStates(
+ LONG max_localized_extended_states,
+ BSTR** localized_extended_states,
+ LONG* n_localized_extended_states) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP get_locale(IA2Locale* locale) {
+ return E_NOTIMPL;
+ }
+
+ //
+ // IAccessibleText methods.
+ //
+
+ STDMETHODIMP get_nCharacters(LONG* n_characters);
+
+ STDMETHODIMP get_caretOffset(LONG* offset);
+
+ STDMETHODIMP get_nSelections(LONG* n_selections);
+
+ STDMETHODIMP get_selection(LONG selection_index,
+ LONG* start_offset,
+ LONG* end_offset);
+
+ STDMETHODIMP get_text(LONG start_offset, LONG end_offset, BSTR* text);
+
+ STDMETHODIMP get_offsetAtPoint(LONG x, LONG y,
+ enum IA2CoordinateType coord_type,
+ LONG* offset);
+
+ //
+ // IAccessibleText methods not implemented.
+ //
+
+ STDMETHODIMP get_textAtOffset(LONG offset,
+ enum IA2TextBoundaryType boundary_type,
+ LONG* start_offset, LONG* end_offset,
+ BSTR* text) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP get_textBeforeOffset(LONG offset,
+ enum IA2TextBoundaryType boundary_type,
+ LONG* start_offset, LONG* end_offset,
+ BSTR* text) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP get_textAfterOffset(LONG offset,
+ enum IA2TextBoundaryType boundary_type,
+ LONG* start_offset, LONG* end_offset,
+ BSTR* text) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP get_newText(IA2TextSegment* new_text) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP get_oldText(IA2TextSegment* old_text) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP addSelection(LONG start_offset, LONG end_offset) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP get_attributes(LONG offset,
+ LONG* start_offset,
+ LONG* end_offset,
+ BSTR* text_attributes) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP get_characterExtents(LONG offset,
+ enum IA2CoordinateType coord_type,
+ LONG* x, LONG* y,
+ LONG* width, LONG* height) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP removeSelection(LONG selection_index) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP setCaretOffset(LONG offset) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP setSelection(LONG selection_index,
+ LONG start_offset,
+ LONG end_offset) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP scrollSubstringTo(LONG start_index,
+ LONG end_index,
+ enum IA2ScrollType scroll_type) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP scrollSubstringToPoint(LONG start_index,
+ LONG end_index,
+ enum IA2CoordinateType coordinate_type,
+ LONG x, LONG y) {
+ return E_NOTIMPL;
+ }
+
+ //
+ // IServiceProvider methods.
+ //
+
+ STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void** object);
+
// Returns a conversion from the event (as defined in accessibility_types.h)
// to an MSAA event.
static int32 MSAAEvent(ui::AccessibilityTypes::Event event);
@@ -144,12 +317,21 @@ class ATL_NO_VTABLE NativeViewAccessibilityWin
// Helper function which sets applicable states of view.
void SetState(VARIANT* msaa_state, views::View* view);
+ // Return the text to use for IAccessibleText.
+ string16 TextForIAccessibleText();
+
// Give CComObject access to the class constructor.
template <class Base> friend class CComObject;
// Member View needed for view-specific calls.
views::View* view_;
+ // A unique id for each object, needed for IAccessible2.
+ long unique_id_;
+
+ // Next unique id to assign.
+ static long next_unique_id_;
+
DISALLOW_COPY_AND_ASSIGN(NativeViewAccessibilityWin);
};
diff --git a/views/view.h b/views/view.h
index 945e381..88855e2 100644
--- a/views/view.h
+++ b/views/view.h
@@ -24,6 +24,10 @@
#include "views/background.h"
#include "views/border.h"
+#if defined(OS_WIN)
+#include "base/win/scoped_comptr.h"
+#endif
+
using ui::OSExchangeData;
namespace gfx {
@@ -44,7 +48,8 @@ enum TouchStatus;
}
#if defined(OS_WIN)
-class NativeViewAccessibilityWin;
+class __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
+NativeViewAccessibilityWin;
#endif
namespace views {
@@ -1440,7 +1445,8 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// The Windows-specific accessibility implementation for this view.
#if defined(OS_WIN)
- scoped_refptr<NativeViewAccessibilityWin> native_view_accessibility_win_;
+ base::win::ScopedComPtr<NativeViewAccessibilityWin>
+ native_view_accessibility_win_;
#endif
DISALLOW_COPY_AND_ASSIGN(View);
diff --git a/views/views.gyp b/views/views.gyp
index f212cbf..09cadf9 100644
--- a/views/views.gyp
+++ b/views/views.gyp
@@ -529,6 +529,10 @@
],
}],
['OS=="win"', {
+ 'dependencies': [
+ # For accessibility
+ '../third_party/iaccessible2/iaccessible2.gyp:iaccessible2',
+ ],
'include_dirs': [
'../third_party/wtl/include',
],