Bug 1887782: Implement the UIA ScrollItem pattern. r=nlapre

Differential Revision: https://phabricator.services.mozilla.com/D205785
This commit is contained in:
James Teh 2024-04-03 03:40:39 +00:00
parent e1e4a33e82
commit e274b95ebd
3 changed files with 55 additions and 1 deletions

View File

@ -4,6 +4,13 @@
"use strict";
/* import-globals-from ../../../mochitest/role.js */
/* import-globals-from ../../../mochitest/states.js */
loadScripts(
{ name: "role.js", dir: MOCHITESTS_DIR },
{ name: "states.js", dir: MOCHITESTS_DIR }
);
/* eslint-disable camelcase */
const ExpandCollapseState_Collapsed = 0;
const ExpandCollapseState_Expanded = 1;
@ -260,3 +267,28 @@ addUiaTask(
await testPatternAbsent("button", "ExpandCollapse");
}
);
/**
* Test the ScrollItem pattern.
*/
addUiaTask(
`
<hr style="height: 100vh;">
<button id="button">button</button>
`,
async function testScrollItem(browser, docAcc) {
await definePyVar("doc", `getDocUia()`);
await assignPyVarToUiaWithId("button");
await definePyVar("pattern", `getUiaPattern(button, "ScrollItem")`);
ok(await runPython(`bool(pattern)`), "button has ScrollItem pattern");
const button = findAccessibleChildByID(docAcc, "button");
testStates(button, STATE_OFFSCREEN);
info("Calling ScrollIntoView on button");
// UIA doesn't have an event for this.
let scrolled = waitForEvent(EVENT_SCROLLING_END, docAcc);
await runPython(`pattern.ScrollIntoView()`);
await scrolled;
ok(true, "Document scrolled");
testStates(button, 0, 0, STATE_OFFSCREEN);
}
);

View File

@ -145,6 +145,8 @@ uiaRawElmProvider::QueryInterface(REFIID aIid, void** aInterface) {
*aInterface = static_cast<IExpandCollapseProvider*>(this);
} else if (aIid == IID_IInvokeProvider) {
*aInterface = static_cast<IInvokeProvider*>(this);
} else if (aIid == IID_IScrollItemProvider) {
*aInterface = static_cast<IScrollItemProvider*>(this);
} else if (aIid == IID_IToggleProvider) {
*aInterface = static_cast<IToggleProvider*>(this);
} else {
@ -260,6 +262,11 @@ uiaRawElmProvider::GetPatternProvider(
invoke.forget(aPatternProvider);
}
return S_OK;
case UIA_ScrollItemPatternId: {
RefPtr<IScrollItemProvider> scroll = this;
scroll.forget(aPatternProvider);
return S_OK;
}
case UIA_TogglePatternId:
if (HasTogglePattern()) {
RefPtr<IToggleProvider> toggle = this;
@ -649,6 +656,17 @@ uiaRawElmProvider::get_ExpandCollapseState(
return S_OK;
}
// IScrollItemProvider methods
MOZ_CAN_RUN_SCRIPT_BOUNDARY STDMETHODIMP uiaRawElmProvider::ScrollIntoView() {
Accessible* acc = Acc();
if (!acc) {
return CO_E_OBJNOTCONNECTED;
}
acc->ScrollTo(nsIAccessibleScrollType::SCROLL_TYPE_ANYWHERE);
return S_OK;
}
// Private methods
bool uiaRawElmProvider::IsControl() {

View File

@ -24,7 +24,8 @@ class uiaRawElmProvider : public IAccessibleEx,
public IRawElementProviderFragment,
public IInvokeProvider,
public IToggleProvider,
public IExpandCollapseProvider {
public IExpandCollapseProvider,
public IScrollItemProvider {
public:
static void RaiseUiaEventForGeckoEvent(Accessible* aAcc,
uint32_t aGeckoEvent);
@ -103,6 +104,9 @@ class uiaRawElmProvider : public IAccessibleEx,
virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_ExpandCollapseState(
/* [retval][out] */ __RPC__out enum ExpandCollapseState* aRetVal);
// IScrollItemProvider
virtual HRESULT STDMETHODCALLTYPE ScrollIntoView(void);
private:
Accessible* Acc() const;
bool IsControl();