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

Side by Side Diff: content/browser/accessibility/browser_accessibility_manager_android.cc

Issue 290633002: Implement Android accessible hit testing using an IPC to the renderer process. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@better_logging_2
Patch Set: Tweak to algorithm to find highest leaf ancestor Created 6 years, 7 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 unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/accessibility/browser_accessibility_manager_android.h" 5 #include "content/browser/accessibility/browser_accessibility_manager_android.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 8
9 #include "base/android/jni_android.h" 9 #include "base/android/jni_android.h"
10 #include "base/android/jni_string.h" 10 #include "base/android/jni_string.h"
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 ui::AXEvent event_type, 120 ui::AXEvent event_type,
121 BrowserAccessibility* node) { 121 BrowserAccessibility* node) {
122 JNIEnv* env = AttachCurrentThread(); 122 JNIEnv* env = AttachCurrentThread();
123 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 123 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
124 if (obj.is_null()) 124 if (obj.is_null())
125 return; 125 return;
126 126
127 if (event_type == ui::AX_EVENT_HIDE) 127 if (event_type == ui::AX_EVENT_HIDE)
128 return; 128 return;
129 129
130 if (event_type == ui::AX_EVENT_HOVER) {
131 HandleHoverEvent(node);
132 return;
133 }
134
130 // Always send AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED to notify 135 // Always send AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED to notify
131 // the Android system that the accessibility hierarchy rooted at this 136 // the Android system that the accessibility hierarchy rooted at this
132 // node has changed. 137 // node has changed.
133 Java_BrowserAccessibilityManager_handleContentChanged( 138 Java_BrowserAccessibilityManager_handleContentChanged(
134 env, obj.obj(), node->GetId()); 139 env, obj.obj(), node->GetId());
135 140
136 switch (event_type) { 141 switch (event_type) {
137 case ui::AX_EVENT_LOAD_COMPLETE: 142 case ui::AX_EVENT_LOAD_COMPLETE:
138 Java_BrowserAccessibilityManager_handlePageLoaded( 143 Java_BrowserAccessibilityManager_handlePageLoaded(
139 env, obj.obj(), focus_->id()); 144 env, obj.obj(), focus_->id());
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 194
190 jint BrowserAccessibilityManagerAndroid::GetRootId(JNIEnv* env, jobject obj) { 195 jint BrowserAccessibilityManagerAndroid::GetRootId(JNIEnv* env, jobject obj) {
191 return static_cast<jint>(GetRoot()->GetId()); 196 return static_cast<jint>(GetRoot()->GetId());
192 } 197 }
193 198
194 jboolean BrowserAccessibilityManagerAndroid::IsNodeValid( 199 jboolean BrowserAccessibilityManagerAndroid::IsNodeValid(
195 JNIEnv* env, jobject obj, jint id) { 200 JNIEnv* env, jobject obj, jint id) {
196 return GetFromID(id) != NULL; 201 return GetFromID(id) != NULL;
197 } 202 }
198 203
199 jint BrowserAccessibilityManagerAndroid::HitTest( 204 void BrowserAccessibilityManagerAndroid::HitTest(
200 JNIEnv* env, jobject obj, jint x, jint y) { 205 JNIEnv* env, jobject obj, jint x, jint y) {
201 BrowserAccessibilityAndroid* result = 206 if (delegate())
202 static_cast<BrowserAccessibilityAndroid*>( 207 delegate()->AccessibilityHitTest(gfx::Point(x, y));
203 GetRoot()->BrowserAccessibilityForPoint(gfx::Point(x, y)));
204
205 if (!result)
206 return GetRoot()->GetId();
207
208 if (result->IsFocusable())
209 return result->GetId();
210
211 // Examine the children of |result| to find the nearest accessibility focus
212 // candidate
213 BrowserAccessibility* nearest_node = FuzzyHitTest(x, y, result);
214 if (nearest_node)
215 return nearest_node->GetId();
216
217 return GetRoot()->GetId();
218 } 208 }
219 209
220 jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityNodeInfo( 210 jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityNodeInfo(
221 JNIEnv* env, jobject obj, jobject info, jint id) { 211 JNIEnv* env, jobject obj, jobject info, jint id) {
222 BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>( 212 BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
223 GetFromID(id)); 213 GetFromID(id));
224 if (!node) 214 if (!node)
225 return false; 215 return false;
226 216
227 if (node->GetParent()) { 217 if (node->GetParent()) {
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 SetFocus(GetRoot(), true); 399 SetFocus(GetRoot(), true);
410 } 400 }
411 401
412 void BrowserAccessibilityManagerAndroid::ScrollToMakeNodeVisible( 402 void BrowserAccessibilityManagerAndroid::ScrollToMakeNodeVisible(
413 JNIEnv* env, jobject obj, jint id) { 403 JNIEnv* env, jobject obj, jint id) {
414 BrowserAccessibility* node = GetFromID(id); 404 BrowserAccessibility* node = GetFromID(id);
415 if (node) 405 if (node)
416 ScrollToMakeVisible(*node, gfx::Rect(node->GetLocation().size())); 406 ScrollToMakeVisible(*node, gfx::Rect(node->GetLocation().size()));
417 } 407 }
418 408
419 BrowserAccessibility* BrowserAccessibilityManagerAndroid::FuzzyHitTest( 409 void BrowserAccessibilityManagerAndroid::HandleHoverEvent(
420 int x, int y, BrowserAccessibility* start_node) { 410 BrowserAccessibility* node) {
421 BrowserAccessibility* nearest_node = NULL; 411 JNIEnv* env = AttachCurrentThread();
422 int min_distance = INT_MAX; 412 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
423 FuzzyHitTestImpl(x, y, start_node, &nearest_node, &min_distance); 413 if (obj.is_null())
424 return nearest_node; 414 return;
425 }
426 415
427 // static 416 BrowserAccessibilityAndroid* ancestor =
428 void BrowserAccessibilityManagerAndroid::FuzzyHitTestImpl( 417 static_cast<BrowserAccessibilityAndroid*>(node->GetParent());
429 int x, int y, BrowserAccessibility* start_node, 418 while (ancestor) {
430 BrowserAccessibility** nearest_candidate, int* nearest_distance) { 419 if (ancestor->PlatformIsLeaf() ||
431 BrowserAccessibilityAndroid* node = 420 (ancestor->IsFocusable() && !ancestor->HasFocusableChild())) {
432 static_cast<BrowserAccessibilityAndroid*>(start_node); 421 node = ancestor;
433 int distance = CalculateDistanceSquared(x, y, node); 422 // Don't break - we want the highest ancestor that's focusable or a
434 423 // leaf node.
435 if (node->IsFocusable()) {
436 if (distance < *nearest_distance) {
437 *nearest_candidate = node;
438 *nearest_distance = distance;
439 } 424 }
440 // Don't examine any more children of focusable node 425 ancestor = static_cast<BrowserAccessibilityAndroid*>(ancestor->GetParent());
441 // TODO(aboxhall): what about focusable children?
442 return;
443 } 426 }
444 427
445 if (!node->GetText().empty()) { 428 Java_BrowserAccessibilityManager_handleHover(
446 if (distance < *nearest_distance) { 429 env, obj.obj(), node->GetId());
447 *nearest_candidate = node;
448 *nearest_distance = distance;
449 }
450 return;
451 }
452
453 for (uint32 i = 0; i < node->PlatformChildCount(); i++) {
454 BrowserAccessibility* child = node->PlatformGetChild(i);
455 FuzzyHitTestImpl(x, y, child, nearest_candidate, nearest_distance);
456 }
457 }
458
459 // static
460 int BrowserAccessibilityManagerAndroid::CalculateDistanceSquared(
461 int x, int y, BrowserAccessibility* node) {
462 gfx::Rect node_bounds = node->GetLocalBoundsRect();
463 int nearest_x = Clamp(x, node_bounds.x(), node_bounds.right());
464 int nearest_y = Clamp(y, node_bounds.y(), node_bounds.bottom());
465 int dx = std::abs(x - nearest_x);
466 int dy = std::abs(y - nearest_y);
467 return dx * dx + dy * dy;
468 } 430 }
469 431
470 jint BrowserAccessibilityManagerAndroid::FindElementType( 432 jint BrowserAccessibilityManagerAndroid::FindElementType(
471 JNIEnv* env, jobject obj, jint start_id, jstring element_type_str, 433 JNIEnv* env, jobject obj, jint start_id, jstring element_type_str,
472 jboolean forwards) { 434 jboolean forwards) {
473 BrowserAccessibility* node = GetFromID(start_id); 435 BrowserAccessibility* node = GetFromID(start_id);
474 if (!node) 436 if (!node)
475 return 0; 437 return 0;
476 438
477 AndroidHtmlElementType element_type = HtmlElementTypeFromString( 439 AndroidHtmlElementType element_type = HtmlElementTypeFromString(
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
537 BrowserAccessibilityManagerAndroid::UseRootScrollOffsetsWhenComputingBounds() { 499 BrowserAccessibilityManagerAndroid::UseRootScrollOffsetsWhenComputingBounds() {
538 // The Java layer handles the root scroll offset. 500 // The Java layer handles the root scroll offset.
539 return false; 501 return false;
540 } 502 }
541 503
542 bool RegisterBrowserAccessibilityManager(JNIEnv* env) { 504 bool RegisterBrowserAccessibilityManager(JNIEnv* env) {
543 return RegisterNativesImpl(env); 505 return RegisterNativesImpl(env);
544 } 506 }
545 507
546 } // namespace content 508 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698