Commit 4fc657cd authored by Josiah K's avatar Josiah K Committed by Commit Bot

Docked Magnifier Sends OnMagnifierBoundsChanged Events

AX-Relnotes: N/A
Bug: 1151216
Change-Id: I222ec5d29ae2fd06689d6d94876f4fa6973e4c2a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2552163
Commit-Queue: Josiah Krutz <josiahk@google.com>
Reviewed-by: default avatarAhmed Fakhry <afakhry@chromium.org>
Reviewed-by: default avatarDavid Tseng <dtseng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#830905}
parent 9b1ac60a
......@@ -235,8 +235,9 @@ void DockedMagnifierControllerImpl::CenterOnPoint(
// 1- Scale the layer by |scale|.
// 2- Translate the point of interest to the center point of the viewport
// widget.
const gfx::Point viewport_center_point =
GetViewportWidgetBoundsInRoot(current_source_root_window_).CenterPoint();
const gfx::Rect viewport_widget_bounds =
GetViewportWidgetBoundsInRoot(current_source_root_window_);
const gfx::Point viewport_center_point = viewport_widget_bounds.CenterPoint();
gfx::Transform transform;
transform.Translate(viewport_center_point.x() - point_in_pixels.x(),
viewport_center_point.y() - point_in_pixels.y());
......@@ -252,6 +253,29 @@ void DockedMagnifierControllerImpl::CenterOnPoint(
settings.SetTweenType(gfx::Tween::ZERO);
settings.SetPreemptionStrategy(ui::LayerAnimator::IMMEDIATELY_SET_NEW_TARGET);
viewport_magnifier_layer_->SetTransform(transform);
// Also make sure |point_of_interest|'s y-coordinate doesn't go below
// the minimum height.
if (point_of_interest.y() < minimum_point_of_interest_height_)
point_of_interest.set_y(minimum_point_of_interest_height_);
// Send changed magnified region bounds to accessibility controller,
// triggering accessibility manager to dispatch an accessibility private
// OnMagnifierBoundsChanged event, which will be listened for by magnifier.js,
// which keeps track of the last magnified region bounds, to help when
// deciding where to next move the magnified region.
// |viewport_widget_bounds| represents the full-width docked magnifier panel
// at the top of the screen. Shrink this by the current magnifier |scale| to
// get the actual zoomed-in width and height of the magnified area.
const int width = viewport_widget_bounds.width() / scale;
const int height = viewport_widget_bounds.height() / scale;
const int x = point_of_interest.x() - width / 2;
const int y = point_of_interest.y() - height / 2;
gfx::Rect magnified_region_bounds(x, y, width, height);
::wm::ConvertRectToScreen(root_window, &magnified_region_bounds);
Shell::Get()->accessibility_controller()->MagnifierBoundsChanged(
magnified_region_bounds);
}
int DockedMagnifierControllerImpl::GetMagnifierHeightForTesting() const {
......
......@@ -61,6 +61,7 @@ js2gtest("accessibility_common_extjs_tests") {
sources = [
"accessibility_common_test.js",
"autoclick/autoclick_test.js",
"magnifier/docked_magnifier_test.js",
"magnifier/magnifier_test.js",
]
gen_include_files = [
......@@ -68,6 +69,7 @@ js2gtest("accessibility_common_extjs_tests") {
"../common/testing/callback_helper.js",
"../common/testing/e2e_test_base.js",
"../common/testing/mock_accessibility_private.js",
"magnifier/magnifier_test_common.js",
]
# The test base classes generate C++ code with these deps.
......
// Copyright 2020 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.
GEN_INCLUDE(['../../common/testing/e2e_test_base.js']);
GEN_INCLUDE(['../../common/testing/mock_accessibility_private.js']);
GEN_INCLUDE(['../../common/rect_util.js']);
GEN_INCLUDE(['magnifier_test_common.js']);
/**
* Magnifier feature using accessibility common extension browser tests.
*/
DockedMagnifierE2ETest = class extends E2ETestBase {
constructor() {
super();
window.RoleType = chrome.automation.RoleType;
}
async getNextMagnifierBounds() {
return new Promise(resolve => {
const listener = (magnifierBounds) => {
chrome.accessibilityPrivate.onMagnifierBoundsChanged.removeListener(
listener);
resolve(magnifierBounds);
};
chrome.accessibilityPrivate.onMagnifierBoundsChanged.addListener(
listener);
});
}
/** @override */
testGenCppIncludes() {
super.testGenCppIncludes();
GEN(`
#include "chrome/browser/chromeos/accessibility/magnification_manager.h"
#include "chrome/common/extensions/extension_constants.h"
#include "content/public/test/browser_test.h"
`);
}
/** @override */
testGenPreamble() {
super.testGenPreamble();
GEN(`
base::Closure load_cb =
base::Bind(&chromeos::MagnificationManager::SetDockedMagnifierEnabled,
base::Unretained(chromeos::MagnificationManager::Get()),
true);
WaitForExtension(extension_misc::kAccessibilityCommonExtensionId, load_cb);
`);
}
};
TEST_F(
'DockedMagnifierE2ETest', 'MovesDockedMagnifierToActiveDescendant',
function() {
this.runWithLoadedTree(ActiveDescendantSite, async function(root) {
const top = root.find({attributes: {name: 'Top'}});
const banana = root.find({attributes: {name: 'Banana'}});
const group = root.find({role: RoleType.GROUP});
// Focus and move magnifier to top.
top.focus();
// Verify magnifier contain top and not banana.
let bounds = await this.getNextMagnifierBounds();
assertTrue(RectUtil.contains(bounds, top.location));
assertFalse(RectUtil.contains(bounds, banana.location));
// Click group to change active descendant to banana.
group.doDefault();
// Verify magnifier bounds contain banana.
bounds = await this.getNextMagnifierBounds();
assertFalse(RectUtil.contains(bounds, top.location));
assertTrue(RectUtil.contains(bounds, banana.location));
});
});
......@@ -5,6 +5,7 @@
GEN_INCLUDE(['../../common/testing/e2e_test_base.js']);
GEN_INCLUDE(['../../common/testing/mock_accessibility_private.js']);
GEN_INCLUDE(['../../common/rect_util.js']);
GEN_INCLUDE(['magnifier_test_common.js']);
/**
* Magnifier feature using accessibility common extension browser tests.
......@@ -77,64 +78,9 @@ TEST_F('MagnifierE2ETest', 'MovesScreenMagnifierToFocusedElement', function() {
});
});
// Disabled - flaky: https://crbug.com/1145612
TEST_F(
'MagnifierE2ETest', 'DISABLED_MovesDockedMagnifierToActiveDescendant', function() {
const site = `
<div role="group" id="parent" aria-activedescendant="apple">
<div id="apple" role="treeitem">Apple</div>
<div id="banana" role="treeitem">Banana</div>
</div>
<script>
const parent = document.getElementById('parent');
parent.addEventListener('click', function() {
parent.setAttribute('aria-activedescendant', 'banana');
});
</script>
`;
this.runWithLoadedTree(site, async function(root) {
// Enable docked magnifier.
await new Promise(resolve => {
chrome.accessibilityFeatures.dockedMagnifier.set(
{value: true}, resolve);
});
// Validate magnifier wants to move to root.
const rootLocation = await getNextMagnifierLocation();
assertTrue(RectUtil.equal(rootLocation, root.location));
// Click parent to change active descendant from apple to banana.
const parent = root.find({role: RoleType.GROUP});
parent.doDefault();
// Register and wait for rect from magnifier.
const rect = await getNextMagnifierLocation();
// Validate rect from magnifier is rect of banana.
const bananaNode =
root.find({role: RoleType.TREE_ITEM, attributes: {name: 'Banana'}});
assertTrue(RectUtil.equal(rect, bananaNode.location));
}, {returnPage: true});
});
TEST_F(
'MagnifierE2ETest', 'MovesScreenMagnifierToActiveDescendant', function() {
const site = `
<span tabindex="1">Top</span>
<div id="group" role="group" style="width: 200px"
aria-activedescendant="apple">
<div id="apple" role="treeitem">Apple</div>
<div id="banana" role="treeitem" style="margin-top: 400px">Banana</div>
</div>
<script>
const group = document.getElementById('group');
group.addEventListener('click', function() {
group.setAttribute('aria-activedescendant', 'banana');
});
</script>
`;
this.runWithLoadedTree(site, async function(root) {
this.runWithLoadedTree(ActiveDescendantSite, async function(root) {
const top = root.find({attributes: {name: 'Top'}});
const banana = root.find({attributes: {name: 'Banana'}});
const group = root.find({role: RoleType.GROUP});
......
// Copyright 2020 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.
const ActiveDescendantSite = `
<span tabindex="1">Top</span>
<div id="group" role="group" style="width: 200px"
aria-activedescendant="apple">
<div id="apple" role="treeitem">Apple</div>
<div id="banana" role="treeitem" style="margin-top: 400px">
Banana
</div>
</div>
<script>
const group = document.getElementById('group');
group.addEventListener('click', function() {
group.setAttribute('aria-activedescendant', 'banana');
});
</script>
`;
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment