Bug 1710493: Implement AXFrame for VoiceOver r=eeejay

Differential Revision: https://phabricator.services.mozilla.com/D113585
This commit is contained in:
Morgan Reschenberg 2021-05-10 21:32:19 +00:00
Родитель 752fb9ad29
Коммит 7c9fb4df94
5 изменённых файлов: 108 добавлений и 24 удалений

Просмотреть файл

@ -111,6 +111,9 @@
// AXWindow
- (id _Nullable)moxWindow;
// AXFrame
- (NSValue* _Nullable)moxFrame;
// AXTitleUIElement
- (id _Nullable)moxTitleUIElement;

Просмотреть файл

@ -193,6 +193,9 @@ inline mozAccessible* GetNativeFromGeckoAccessible(
// override
- (NSNumber*)moxSelected;
// override
- (NSValue*)moxFrame;
// override
- (NSString*)moxARIACurrent;

Просмотреть файл

@ -354,35 +354,16 @@ static const uint64_t kCacheInitialized = ((uint64_t)0x1) << 63;
}
- (NSValue*)moxPosition {
MOZ_ASSERT(!mGeckoAccessible.IsNull());
CGRect frame = [[self moxFrame] rectValue];
nsIntRect rect = mGeckoAccessible.IsAccessible()
? mGeckoAccessible.AsAccessible()->Bounds()
: mGeckoAccessible.AsProxy()->Bounds();
NSScreen* mainView = [[NSScreen screens] objectAtIndex:0];
CGFloat scaleFactor = nsCocoaUtils::GetBackingScaleFactor(mainView);
NSPoint p =
NSMakePoint(static_cast<CGFloat>(rect.x) / scaleFactor,
[mainView frame].size.height -
static_cast<CGFloat>(rect.y + rect.height) / scaleFactor);
return [NSValue valueWithPoint:p];
return [NSValue valueWithPoint:NSMakePoint(frame.origin.x, frame.origin.y)];
}
- (NSValue*)moxSize {
MOZ_ASSERT(!mGeckoAccessible.IsNull());
CGRect frame = [[self moxFrame] rectValue];
nsIntRect rect = mGeckoAccessible.IsAccessible()
? mGeckoAccessible.AsAccessible()->Bounds()
: mGeckoAccessible.AsProxy()->Bounds();
CGFloat scaleFactor =
nsCocoaUtils::GetBackingScaleFactor([[NSScreen screens] objectAtIndex:0]);
return [NSValue
valueWithSize:NSMakeSize(
static_cast<CGFloat>(rect.width) / scaleFactor,
static_cast<CGFloat>(rect.height) / scaleFactor)];
return
[NSValue valueWithSize:NSMakeSize(frame.size.width, frame.size.height)];
}
- (NSString*)moxRole {
@ -712,6 +693,25 @@ struct RoleDescrComparator {
return @NO;
}
- (NSValue*)moxFrame {
MOZ_ASSERT(!mGeckoAccessible.IsNull());
nsIntRect rect = mGeckoAccessible.IsAccessible()
? mGeckoAccessible.AsAccessible()->Bounds()
: mGeckoAccessible.AsProxy()->Bounds();
NSScreen* mainView = [[NSScreen screens] objectAtIndex:0];
CGFloat scaleFactor = nsCocoaUtils::GetBackingScaleFactor(mainView);
return [NSValue
valueWithRect:NSMakeRect(
static_cast<CGFloat>(rect.x) / scaleFactor,
[mainView frame].size.height -
static_cast<CGFloat>(rect.y + rect.height) /
scaleFactor,
static_cast<CGFloat>(rect.width) / scaleFactor,
static_cast<CGFloat>(rect.height) / scaleFactor)];
}
- (NSString*)moxARIACurrent {
if (![self stateWithMask:states::CURRENT]) {
return nil;

Просмотреть файл

@ -49,3 +49,4 @@ skip-if = os == 'mac' && debug # Bug 1664577
[browser_aria_busy.js]
[browser_aria_controls_flowto.js]
[browser_attributed_text.js]
[browser_bounds.js]

Просмотреть файл

@ -0,0 +1,77 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
/**
* Test position, size for onscreen content
*/
addAccessibleTask(
`I am some extra content<br>
<div id="hello" style="display:inline;">hello</div><br>
<div id="world" style="display:inline;">hello world<br>I am some text</div>`,
async (browser, accDoc) => {
const hello = getNativeInterface(accDoc, "hello");
const world = getNativeInterface(accDoc, "world");
ok(hello.getAttributeValue("AXFrame"), "Hello's frame attr is not null");
ok(world.getAttributeValue("AXFrame"), "World's frame attr is not null");
// AXSize and AXPosition are composed of AXFrame components, so we
// test them here instead of calling AXFrame directly.
const [helloWidth, helloHeight] = hello.getAttributeValue("AXSize");
const [worldWidth, worldHeight] = world.getAttributeValue("AXSize");
ok(helloWidth > 0, "Hello has a positive width");
ok(helloHeight > 0, "Hello has a positive height");
ok(worldWidth > 0, "World has a positive width");
ok(worldHeight > 0, "World has a positive height");
ok(helloHeight < worldHeight, "Hello has a smaller height than world");
ok(helloWidth < worldWidth, "Hello has a smaller width than world");
// Note: these are mac screen coords, so our origin is bottom left
const [helloX, helloY] = hello.getAttributeValue("AXPosition");
const [worldX, worldY] = world.getAttributeValue("AXPosition");
ok(helloX > 0, "Hello has a positive X");
ok(helloY > 0, "Hello has a positive Y");
ok(worldX > 0, "World has a positive X");
ok(worldY > 0, "World has a positive Y");
ok(helloY > worldY, "Hello has a larger Y than world");
ok(helloX == worldX, "Hello and world have the same X");
}
);
/**
* Test position, size for offscreen content
*/
addAccessibleTask(
`I am some extra content<br>
<div id="hello" style="display:inline; position:absolute; left:-2000px;">hello</div><br>
<div id="world" style="display:inline; position:absolute; left:-2000px;">hello world<br>I am some text</div>`,
async (browser, accDoc) => {
const hello = getNativeInterface(accDoc, "hello");
const world = getNativeInterface(accDoc, "world");
ok(hello.getAttributeValue("AXFrame"), "Hello's frame attr is not null");
ok(world.getAttributeValue("AXFrame"), "World's frame attr is not null");
// AXSize and AXPosition are composed of AXFrame components, so we
// test them here instead of calling AXFrame directly.
const [helloWidth, helloHeight] = hello.getAttributeValue("AXSize");
const [worldWidth, worldHeight] = world.getAttributeValue("AXSize");
ok(helloWidth > 0, "Hello has a positive width");
ok(helloHeight > 0, "Hello has a positive height");
ok(worldWidth > 0, "World has a positive width");
ok(worldHeight > 0, "World has a positive height");
ok(helloHeight < worldHeight, "Hello has a smaller height than world");
ok(helloWidth < worldWidth, "Hello has a smaller width than world");
// Note: these are mac screen coords, so our origin is bottom left
const [helloX, helloY] = hello.getAttributeValue("AXPosition");
const [worldX, worldY] = world.getAttributeValue("AXPosition");
ok(helloX < 0, "Hello has a negative X");
ok(helloY > 0, "Hello has a positive Y");
ok(worldX < 0, "World has a negative X");
ok(worldY > 0, "World has a positive Y");
ok(helloY > worldY, "Hello has a larger Y than world");
ok(helloX == worldX, "Hello and world have the same X");
}
);