Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(492)

Unified Diff: ui/views/accessibility/native_view_accessibility_win.cc

Issue 23506027: Implement web content hit testing in win aura. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Fix compile error Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/views/accessibility/native_view_accessibility.cc ('k') | ui/views/controls/webview/webview.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/views/accessibility/native_view_accessibility_win.cc
diff --git a/ui/views/accessibility/native_view_accessibility_win.cc b/ui/views/accessibility/native_view_accessibility_win.cc
index a0367fe1f1e32fa930a4799b3149ea597cd05e84..1f29ee9c0c3ca6cb44c4034c66f21bd55fec9171 100644
--- a/ui/views/accessibility/native_view_accessibility_win.cc
+++ b/ui/views/accessibility/native_view_accessibility_win.cc
@@ -11,6 +11,7 @@
#include <vector>
#include "base/memory/singleton.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/win/windows_version.h"
#include "third_party/iaccessible2/ia2_api_all.h"
#include "ui/base/accessibility/accessible_text_utils.h"
@@ -32,9 +33,9 @@ class AccessibleWebViewRegistry {
public:
static AccessibleWebViewRegistry* GetInstance();
- void RegisterWebView(AccessibleWebView* web_view);
+ void RegisterWebView(View* web_view);
- void UnregisterWebView(AccessibleWebView* web_view);
+ void UnregisterWebView(View* web_view);
// Given the view that received the request for the accessible
// id in |top_view|, and the child id requested, return the native
@@ -47,16 +48,18 @@ class AccessibleWebViewRegistry {
AccessibleWebViewRegistry();
~AccessibleWebViewRegistry() {}
+ IAccessible* AccessibleObjectFromChildId(View* web_view, long child_id);
+
// Set of all web views. We check whether each one is contained in a
// top view dynamically rather than keeping track of a map.
- std::set<AccessibleWebView*> web_views_;
+ std::set<View*> web_views_;
// The most recent top view used in a call to GetAccessibleFromWebView.
View* last_top_view_;
// The most recent web view where an accessible object was found,
// corresponding to |last_top_view_|.
- AccessibleWebView* last_web_view_;
+ View* last_web_view_;
DISALLOW_COPY_AND_ASSIGN(AccessibleWebViewRegistry);
};
@@ -70,12 +73,12 @@ AccessibleWebViewRegistry* AccessibleWebViewRegistry::GetInstance() {
return Singleton<AccessibleWebViewRegistry>::get();
}
-void AccessibleWebViewRegistry::RegisterWebView(AccessibleWebView* web_view) {
+void AccessibleWebViewRegistry::RegisterWebView(View* web_view) {
DCHECK(web_views_.find(web_view) == web_views_.end());
web_views_.insert(web_view);
}
-void AccessibleWebViewRegistry::UnregisterWebView(AccessibleWebView* web_view) {
+void AccessibleWebViewRegistry::UnregisterWebView(View* web_view) {
DCHECK(web_views_.find(web_view) != web_views_.end());
web_views_.erase(web_view);
if (last_web_view_ == web_view) {
@@ -91,7 +94,7 @@ IAccessible* AccessibleWebViewRegistry::GetAccessibleFromWebView(
// sent the last one.
if (last_top_view_ == top_view) {
IAccessible* accessible =
- last_web_view_->AccessibleObjectFromChildId(child_id);
+ AccessibleObjectFromChildId(last_web_view_, child_id);
if (accessible)
return accessible;
}
@@ -100,18 +103,38 @@ IAccessible* AccessibleWebViewRegistry::GetAccessibleFromWebView(
// of this view where the event was posted - and if so, see if it owns
// an accessible object with that child id. If so, save the view to speed
// up the next notification.
- for (std::set<AccessibleWebView*>::iterator iter = web_views_.begin();
+ for (std::set<View*>::iterator iter = web_views_.begin();
iter != web_views_.end(); ++iter) {
- AccessibleWebView* web_view = *iter;
- if (!top_view->Contains(web_view->AsView()))
+ View* web_view = *iter;
+ if (!top_view->Contains(web_view))
continue;
- IAccessible* accessible = web_view->AccessibleObjectFromChildId(child_id);
+ IAccessible* accessible = AccessibleObjectFromChildId(web_view, child_id);
if (accessible) {
last_top_view_ = top_view;
last_web_view_ = web_view;
return accessible;
}
}
+
+ return NULL;
+}
+
+IAccessible* AccessibleWebViewRegistry::AccessibleObjectFromChildId(
+ View* web_view,
+ long child_id) {
+ IAccessible* web_view_accessible = web_view->GetNativeViewAccessible();
+ if (web_view_accessible == NULL)
+ return NULL;
+
+ VARIANT var_child;
+ var_child.vt = VT_I4;
+ var_child.lVal = child_id;
+ IAccessible* result = NULL;
+ if (S_OK == web_view_accessible->get_accChild(
+ var_child, reinterpret_cast<IDispatch**>(&result))) {
+ return result;
+ }
+
return NULL;
}
@@ -179,7 +202,6 @@ void NativeViewAccessibilityWin::Destroy() {
Release();
}
-// TODO(ctguil): Handle case where child View is not contained by parent.
STDMETHODIMP NativeViewAccessibilityWin::accHitTest(
LONG x_left, LONG y_top, VARIANT* child) {
if (!child)
@@ -191,22 +213,53 @@ STDMETHODIMP NativeViewAccessibilityWin::accHitTest(
gfx::Point point(x_left, y_top);
View::ConvertPointToTarget(NULL, view_, &point);
+ // If the point is not inside this view, return false.
if (!view_->HitTestPoint(point)) {
- // If containing parent is not hit, return with failure.
child->vt = VT_EMPTY;
return S_FALSE;
}
- View* view = view_->GetEventHandlerForPoint(point);
- if (view == view_) {
- // No child hit, return parent id.
- child->vt = VT_I4;
- child->lVal = CHILDID_SELF;
- } else {
- child->vt = VT_DISPATCH;
- child->pdispVal = view->GetNativeViewAccessible();
- child->pdispVal->AddRef();
+ // Check if the point is within any of the immediate children of this
+ // view.
+ View* hit_child_view = NULL;
+ for (int i = view_->child_count() - 1; i >= 0; --i) {
+ View* child_view = view_->child_at(i);
+ if (!child_view->visible())
+ continue;
+
+ gfx::Point point_in_child_coords(point);
+ view_->ConvertPointToTarget(view_, child_view, &point_in_child_coords);
+ if (child_view->HitTestPoint(point_in_child_coords)) {
+ hit_child_view = child_view;
+ break;
+ }
+ }
+
+ // If the point was within one of this view's immediate children,
+ // call accHitTest recursively on that child's native view accessible -
+ // which may be a recursive call to this function or it may be overridden,
+ // for example in the case of a WebView.
+ if (hit_child_view) {
+ HRESULT result = hit_child_view->GetNativeViewAccessible()->accHitTest(
+ x_left, y_top, child);
+
+ // If the recursive call returned CHILDID_SELF, we have to convert that
+ // into a VT_DISPATCH for the return value to this call.
+ if (S_OK == result && child->vt == VT_I4 && child->lVal == CHILDID_SELF) {
+ child->vt = VT_DISPATCH;
+ child->pdispVal = hit_child_view->GetNativeViewAccessible();
+ // Always increment ref when returning a reference to a COM object.
+ child->pdispVal->AddRef();
+ }
+ return result;
}
+
+ // This object is the best match, so return CHILDID_SELF. It's tempting to
+ // simplify the logic and use VT_DISPATCH everywhere, but the Windows
+ // call AccessibleObjectFromPoint will keep calling accHitTest until some
+ // object returns CHILDID_SELF.
+ child->vt = VT_I4;
+ child->lVal = CHILDID_SELF;
return S_OK;
}
@@ -378,10 +431,8 @@ STDMETHODIMP NativeViewAccessibilityWin::get_accChild(VARIANT var_child,
} else {
*disp_child = AccessibleWebViewRegistry::GetInstance()->
GetAccessibleFromWebView(view_, child_id);
- if (*disp_child) {
- (*disp_child)->AddRef();
+ if (*disp_child)
return S_OK;
- }
}
}
@@ -984,11 +1035,11 @@ STDMETHODIMP NativeViewAccessibilityWin::GetPropertyValue(PROPERTYID id,
// Static methods.
//
-void NativeViewAccessibility::RegisterWebView(AccessibleWebView* web_view) {
+void NativeViewAccessibility::RegisterWebView(View* web_view) {
AccessibleWebViewRegistry::GetInstance()->RegisterWebView(web_view);
}
-void NativeViewAccessibility::UnregisterWebView(AccessibleWebView* web_view) {
+void NativeViewAccessibility::UnregisterWebView(View* web_view) {
AccessibleWebViewRegistry::GetInstance()->UnregisterWebView(web_view);
}
« no previous file with comments | « ui/views/accessibility/native_view_accessibility.cc ('k') | ui/views/controls/webview/webview.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698