summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--views/accessibility/accessibility_types.h12
-rw-r--r--views/accessibility/view_accessibility.cc38
-rw-r--r--views/accessibility/view_accessibility.h4
-rw-r--r--views/focus/focus_manager_win.cc3
-rw-r--r--views/view.h6
-rw-r--r--views/view_gtk.cc4
-rw-r--r--views/view_win.cc13
-rw-r--r--views/widget/widget_win.cc34
-rw-r--r--views/widget/widget_win.h30
9 files changed, 136 insertions, 8 deletions
diff --git a/views/accessibility/accessibility_types.h b/views/accessibility/accessibility_types.h
index 882b8a1..7dd991c 100644
--- a/views/accessibility/accessibility_types.h
+++ b/views/accessibility/accessibility_types.h
@@ -64,6 +64,18 @@ class AccessibilityTypes {
ROLE_WINDOW
};
+ // This defines an enumeration of the supported accessibility events in our
+ // Views (e.g. used in View::NotifyAccessibilityEvent). Any interface using
+ // events must provide a conversion to its own events (see e.g.
+ // ViewAccessibility::MSAAEvent).
+ enum Event {
+ EVENT_FOCUS,
+ EVENT_MENUSTART,
+ EVENT_MENUEND,
+ EVENT_MENUPOPUPSTART,
+ EVENT_MENUPOPUPEND
+ };
+
private:
// Do not instantiate this class.
AccessibilityTypes() {}
diff --git a/views/accessibility/view_accessibility.cc b/views/accessibility/view_accessibility.cc
index 67aaaf2..2dad53d 100644
--- a/views/accessibility/view_accessibility.cc
+++ b/views/accessibility/view_accessibility.cc
@@ -290,9 +290,24 @@ STDMETHODIMP ViewAccessibility::get_accChild(VARIANT var_child,
// Check to see if child is out-of-bounds.
if (IsValidChild((var_child.lVal - 1), view_)) {
child_view = view_->GetChildViewAt(var_child.lVal - 1);
+
+ // Parents handle leaf IAccessible's.
+ if (child_view && child_view->GetChildViewCount() == 0)
+ return S_FALSE;
} else {
- // Child is located elsewhere in the hierarchy, get ID and adjust for MSAA.
- child_view = view_->GetViewByID(static_cast<int>(var_child.lVal));
+ // Child is located elsewhere in this view's subtree.
+ // Positive child id's are 1-based indexes so you can iterate over all
+ // children, and negative values are direct references to objects.
+ // Note that we return full IAccessible's for leafs that have
+ // negative child id's.
+ if (var_child.lVal > 0) {
+ child_view = view_->GetViewByID(static_cast<int>(var_child.lVal));
+ } else {
+ // Retrieve it from our cache of views that have fired events.
+ views::WidgetWin* view_widget =
+ static_cast<views::WidgetWin*>(view_->GetWidget());
+ child_view = view_widget->GetAccessibilityViewEventAt(var_child.lVal);
+ }
}
if (!child_view) {
@@ -756,6 +771,25 @@ STDMETHODIMP ViewAccessibility::put_accValue(VARIANT var_id, BSTR put_val) {
return E_NOTIMPL;
}
+int32 ViewAccessibility::MSAAEvent(AccessibilityTypes::Event event) {
+ switch (event) {
+ case AccessibilityTypes::EVENT_FOCUS:
+ return EVENT_OBJECT_FOCUS;
+ case AccessibilityTypes::EVENT_MENUSTART:
+ return EVENT_SYSTEM_MENUSTART;
+ case AccessibilityTypes::EVENT_MENUEND:
+ return EVENT_SYSTEM_MENUEND;
+ case AccessibilityTypes::EVENT_MENUPOPUPSTART:
+ return EVENT_SYSTEM_MENUPOPUPSTART;
+ case AccessibilityTypes::EVENT_MENUPOPUPEND:
+ return EVENT_SYSTEM_MENUPOPUPEND;
+ default:
+ // Not supported or invalid event.
+ NOTREACHED();
+ return -1;
+ }
+}
+
int32 ViewAccessibility::MSAARole(AccessibilityTypes::Role role) {
switch (role) {
case AccessibilityTypes::ROLE_APPLICATION:
diff --git a/views/accessibility/view_accessibility.h b/views/accessibility/view_accessibility.h
index d2472fb..4bb168c 100644
--- a/views/accessibility/view_accessibility.h
+++ b/views/accessibility/view_accessibility.h
@@ -103,6 +103,10 @@ class ATL_NO_VTABLE ViewAccessibility
STDMETHODIMP put_accName(VARIANT var_id, BSTR put_name);
STDMETHODIMP put_accValue(VARIANT var_id, BSTR put_val);
+ // Returns a conversion from the event (as defined in accessibility_types.h)
+ // to an MSAA event.
+ static int32 MSAAEvent(AccessibilityTypes::Event event);
+
// Returns a conversion from the Role (as defined in accessibility_types.h)
// to an MSAA role.
static int32 MSAARole(AccessibilityTypes::Role role);
diff --git a/views/focus/focus_manager_win.cc b/views/focus/focus_manager_win.cc
index 4d897ac..b08bf15 100644
--- a/views/focus/focus_manager_win.cc
+++ b/views/focus/focus_manager_win.cc
@@ -16,8 +16,7 @@ void FocusManager::ClearNativeFocus() {
// We need to let assistive technologies know which child view got focus so
// they can obtain the proper accessibility object for that child view.
if (focused_view_) {
- ::NotifyWinEvent(EVENT_OBJECT_FOCUS, widget_->GetNativeView(), OBJID_CLIENT,
- static_cast<LONG>(focused_view_->GetID()));
+ focused_view_->NotifyAccessibilityEvent(AccessibilityTypes::EVENT_FOCUS);
}
}
diff --git a/views/view.h b/views/view.h
index f6d1efa..2b50f04 100644
--- a/views/view.h
+++ b/views/view.h
@@ -554,7 +554,11 @@ class View : public AcceleratorTarget {
// Accessibility support
// TODO(klink): Move all this out to a AccessibleInfo wrapper class.
- //
+
+ // Notify the platform specific accessibility client of changes in the user
+ // interface.
+ virtual void NotifyAccessibilityEvent(AccessibilityTypes::Event event_type);
+
// Returns the MSAA default action of the current view. The string returned
// describes the default action that will occur when executing
// IAccessible::DoDefaultAction. For instance, default action of a button is
diff --git a/views/view_gtk.cc b/views/view_gtk.cc
index 7621d0f..049dfe8 100644
--- a/views/view_gtk.cc
+++ b/views/view_gtk.cc
@@ -20,6 +20,10 @@ int View::GetMenuShowDelay() {
return kShowFolderDropMenuDelay;
}
+void View::NotifyAccessibilityEvent(AccessibilityTypes::Event event_type) {
+ // Not implemented on GTK.
+}
+
ViewAccessibilityWrapper* View::GetViewAccessibilityWrapper() {
NOTIMPLEMENTED();
return NULL;
diff --git a/views/view_win.cc b/views/view_win.cc
index bce8fa8..3079b5c 100644
--- a/views/view_win.cc
+++ b/views/view_win.cc
@@ -8,10 +8,12 @@
#include "base/string_util.h"
#include "gfx/canvas.h"
#include "gfx/path.h"
+#include "views/accessibility/view_accessibility.h"
#include "views/accessibility/view_accessibility_wrapper.h"
#include "views/border.h"
#include "views/widget/root_view.h"
#include "views/widget/widget.h"
+#include "views/widget/widget_win.h"
namespace views {
@@ -28,6 +30,17 @@ int View::GetMenuShowDelay() {
return delay;
}
+// Notifies accessibility clients of the event_type on this view.
+// Clients will call get_accChild found in ViewAccessibility with the supplied
+// child id we generate here to retrieve the IAccessible associated with this
+// view.
+void View::NotifyAccessibilityEvent(AccessibilityTypes::Event event_type) {
+ WidgetWin* view_widget = static_cast<WidgetWin*>(GetWidget());
+ int child_id = view_widget->AddAccessibilityViewEvent(this);
+ ::NotifyWinEvent(ViewAccessibility::MSAAEvent(event_type),
+ view_widget->GetNativeView(), OBJID_CLIENT, child_id);
+}
+
ViewAccessibilityWrapper* View::GetViewAccessibilityWrapper() {
if (accessibility_.get() == NULL) {
accessibility_.reset(new ViewAccessibilityWrapper(this));
diff --git a/views/widget/widget_win.cc b/views/widget/widget_win.cc
index 90cffe5..332365a 100644
--- a/views/widget/widget_win.cc
+++ b/views/widget/widget_win.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -57,7 +57,9 @@ WidgetWin::WidgetWin()
is_mouse_down_(false),
is_window_(false),
restore_focus_when_enabled_(false),
- delegate_(NULL) {
+ delegate_(NULL),
+ accessibility_view_events_index_(-1),
+ accessibility_view_events_(kMaxAccessibilityViewEvents) {
}
WidgetWin::~WidgetWin() {
@@ -112,6 +114,31 @@ void WidgetWin::SetUseLayeredBuffer(bool use_layered_buffer) {
contents_.reset(NULL);
}
+View* WidgetWin::GetAccessibilityViewEventAt(int id) {
+ // Convert from MSAA child id.
+ id = -(id + 1);
+ DCHECK(id >= 0 && id < kMaxAccessibilityViewEvents);
+ return accessibility_view_events_[id];
+}
+
+int WidgetWin::AddAccessibilityViewEvent(View* view) {
+ accessibility_view_events_index_ =
+ (accessibility_view_events_index_ + 1) % kMaxAccessibilityViewEvents;
+ accessibility_view_events_[accessibility_view_events_index_] = view;
+
+ // Convert to MSAA child id.
+ return -(accessibility_view_events_index_ + 1);
+}
+
+void WidgetWin::ClearAccessibilityViewEvent(View* view) {
+ for (std::vector<View*>::iterator it = accessibility_view_events_.begin();
+ it != accessibility_view_events_.end();
+ ++it) {
+ if (*it == view)
+ *it = NULL;
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
// Widget implementation:
@@ -428,6 +455,9 @@ void WidgetWin::ViewHierarchyChanged(bool is_add, View *parent,
View *child) {
if (drop_target_.get())
drop_target_->ResetTargetViewIfEquals(child);
+
+ if (!is_add)
+ ClearAccessibilityViewEvent(child);
}
diff --git a/views/widget/widget_win.h b/views/widget/widget_win.h
index 699d60e3..98da389 100644
--- a/views/widget/widget_win.h
+++ b/views/widget/widget_win.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -10,6 +10,8 @@
#include <atlcrack.h>
#include <atlmisc.h>
+#include <vector>
+
#include "app/win/window_impl.h"
#include "base/message_loop.h"
#include "base/scoped_comptr_win.h"
@@ -92,6 +94,21 @@ class WidgetWin : public app::WindowImpl,
can_update_layered_window_ = can_update_layered_window;
}
+ // Obtain the view event with the given MSAA child id. Used in
+ // ViewAccessibility::get_accChild to support requests for children of
+ // windowless controls. May return NULL (see ViewHierarchyChanged).
+ View* GetAccessibilityViewEventAt(int id);
+
+ // Add a view that has recently fired an accessibility event. Returns a MSAA
+ // child id which is generated by: -(index of view in vector + 1) which
+ // guarantees a negative child id. This distinguishes the view from
+ // positive MSAA child id's which are direct leaf children of views that have
+ // associated hWnd's (e.g. WidgetWin).
+ int AddAccessibilityViewEvent(View* view);
+
+ // Clear a view that has recently been removed on a hierarchy change.
+ void ClearAccessibilityViewEvent(View* view);
+
BEGIN_MSG_MAP_EX(WidgetWin)
// Range handlers must go first!
MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseRange)
@@ -549,6 +566,17 @@ class WidgetWin : public app::WindowImpl,
// Non owned pointer to optional delegate. May be NULL if no delegate is
// being used.
WidgetDelegate* delegate_;
+
+ // The maximum number of view events in our vector below.
+ static const int kMaxAccessibilityViewEvents = 20;
+
+ // A vector used to access views for which we have sent notifications to
+ // accessibility clients. It is used as a circular queue.
+ std::vector<View*> accessibility_view_events_;
+
+ // The current position of the view events vector. When incrementing,
+ // we always mod this value with the max view events above .
+ int accessibility_view_events_index_;
};
} // namespace views