mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 1886709
part 2: Implement the UIA Invoke pattern. r=nlapre
Differential Revision: https://phabricator.services.mozilla.com/D205432
This commit is contained in:
parent
116d79df30
commit
bf353f3ed5
@ -13,4 +13,6 @@ support-files = ["head.js"]
|
||||
["browser_focus.js"]
|
||||
["browser_generalProps.js"]
|
||||
|
||||
["browser_simplePatterns.js"]
|
||||
|
||||
["browser_tree.js"]
|
||||
|
@ -0,0 +1,41 @@
|
||||
/* 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 the Invoke pattern.
|
||||
*/
|
||||
addUiaTask(
|
||||
`
|
||||
<button id="button">button</button>
|
||||
<p id="p">p</p>
|
||||
`,
|
||||
async function testInvoke() {
|
||||
await definePyVar("doc", `getDocUia()`);
|
||||
await assignPyVarToUiaWithId("button");
|
||||
await definePyVar("pattern", `getUiaPattern(button, "Invoke")`);
|
||||
ok(await runPython(`bool(pattern)`), "button has Invoke pattern");
|
||||
info("Calling Invoke on button");
|
||||
// The button will get focus when it is clicked.
|
||||
let focused = waitForEvent(EVENT_FOCUS, "button");
|
||||
// The UIA -> IA2 proxy doesn't fire the Invoked event.
|
||||
if (gIsUiaEnabled) {
|
||||
await setUpWaitForUiaEvent("Invoke_Invoked", "button");
|
||||
}
|
||||
await runPython(`pattern.Invoke()`);
|
||||
await focused;
|
||||
ok(true, "button got focus");
|
||||
if (gIsUiaEnabled) {
|
||||
await waitForUiaEvent();
|
||||
ok(true, "button got Invoked event");
|
||||
}
|
||||
|
||||
let hasPattern = await runPython(`
|
||||
p = findUiaByDomId(doc, "p")
|
||||
return bool(getUiaPattern(p, "Invoke"))
|
||||
`);
|
||||
ok(!hasPattern, "p doesn't have Invoke pattern");
|
||||
}
|
||||
);
|
@ -146,6 +146,10 @@ class MsaaAccessible : public ia2Accessible,
|
||||
EXCEPINFO* pExcepInfo,
|
||||
UINT* puArgErr) override;
|
||||
|
||||
// UIA's IInvokeProvider has a method called Invoke too, but it's fine because
|
||||
// it accepts very different parameters.
|
||||
using uiaRawElmProvider::Invoke;
|
||||
|
||||
protected:
|
||||
explicit MsaaAccessible(Accessible* aAcc);
|
||||
virtual ~MsaaAccessible();
|
||||
|
@ -73,6 +73,8 @@ uiaRawElmProvider::QueryInterface(REFIID aIid, void** aInterface) {
|
||||
*aInterface = static_cast<IRawElementProviderSimple*>(this);
|
||||
} else if (aIid == IID_IRawElementProviderFragment) {
|
||||
*aInterface = static_cast<IRawElementProviderFragment*>(this);
|
||||
} else if (aIid == IID_IInvokeProvider) {
|
||||
*aInterface = static_cast<IInvokeProvider*>(this);
|
||||
} else {
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
@ -164,8 +166,19 @@ STDMETHODIMP
|
||||
uiaRawElmProvider::GetPatternProvider(
|
||||
PATTERNID aPatternId, __RPC__deref_out_opt IUnknown** aPatternProvider) {
|
||||
if (!aPatternProvider) return E_INVALIDARG;
|
||||
|
||||
*aPatternProvider = nullptr;
|
||||
Accessible* acc = Acc();
|
||||
if (!acc) {
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
}
|
||||
switch (aPatternId) {
|
||||
case UIA_InvokePatternId:
|
||||
if (acc->ActionCount() > 0) {
|
||||
RefPtr<IInvokeProvider> invoke = this;
|
||||
invoke.forget(aPatternProvider);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@ -453,6 +466,23 @@ uiaRawElmProvider::get_FragmentRoot(
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// IInvokeProvider methods
|
||||
|
||||
STDMETHODIMP
|
||||
uiaRawElmProvider::Invoke() {
|
||||
Accessible* acc = Acc();
|
||||
if (!acc) {
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
}
|
||||
if (acc->DoAction(0)) {
|
||||
// We don't currently have a way to notify when the action was actually
|
||||
// handled. The UIA documentation says it's okay to fire this immediately if
|
||||
// it "is not possible or practical to wait until the action is complete".
|
||||
::UiaRaiseAutomationEvent(this, UIA_Invoke_InvokedEventId);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Private methods
|
||||
|
||||
bool uiaRawElmProvider::IsControl() {
|
||||
|
@ -21,7 +21,8 @@ class Accessible;
|
||||
*/
|
||||
class uiaRawElmProvider : public IAccessibleEx,
|
||||
public IRawElementProviderSimple,
|
||||
public IRawElementProviderFragment {
|
||||
public IRawElementProviderFragment,
|
||||
public IInvokeProvider {
|
||||
public:
|
||||
static void RaiseUiaEventForGeckoEvent(Accessible* aAcc,
|
||||
uint32_t aGeckoEvent);
|
||||
@ -81,6 +82,9 @@ class uiaRawElmProvider : public IAccessibleEx,
|
||||
/* [retval][out] */ __RPC__deref_out_opt IRawElementProviderFragmentRoot**
|
||||
aRetVal);
|
||||
|
||||
// IInvokeProvider
|
||||
virtual HRESULT STDMETHODCALLTYPE Invoke(void);
|
||||
|
||||
private:
|
||||
Accessible* Acc() const;
|
||||
bool IsControl();
|
||||
|
Loading…
Reference in New Issue
Block a user