summaryrefslogtreecommitdiffstats
path: root/accessible/windows
diff options
context:
space:
mode:
Diffstat (limited to 'accessible/windows')
-rw-r--r--accessible/windows/ia2/ia2Accessible.cpp2
-rw-r--r--accessible/windows/ia2/ia2AccessibleAction.cpp1
-rw-r--r--accessible/windows/ia2/ia2AccessibleComponent.cpp1
-rw-r--r--accessible/windows/ia2/ia2AccessibleHyperlink.cpp3
-rw-r--r--accessible/windows/ia2/ia2AccessibleValue.cpp1
-rw-r--r--accessible/windows/ia2/moz.build1
-rw-r--r--accessible/windows/msaa/AccessibleWrap.cpp43
-rw-r--r--accessible/windows/msaa/AccessibleWrap.h8
-rw-r--r--accessible/windows/msaa/ApplicationAccessibleWrap.cpp1
-rw-r--r--accessible/windows/msaa/Compatibility.cpp57
-rw-r--r--accessible/windows/msaa/Compatibility.h19
-rw-r--r--accessible/windows/msaa/LazyInstantiator.cpp6
-rw-r--r--accessible/windows/msaa/MsaaAccessible.cpp22
-rw-r--r--accessible/windows/msaa/MsaaAccessible.h6
-rw-r--r--accessible/windows/msaa/MsaaIdGenerator.cpp2
-rw-r--r--accessible/windows/msaa/Platform.cpp6
-rw-r--r--accessible/windows/msaa/ServiceProvider.cpp19
-rw-r--r--accessible/windows/msaa/moz.build2
-rw-r--r--accessible/windows/msaa/nsWinUtils.cpp1
-rw-r--r--accessible/windows/sdn/moz.build1
-rw-r--r--accessible/windows/uia/uiaRawElmProvider.cpp132
-rw-r--r--accessible/windows/uia/uiaRawElmProvider.h21
22 files changed, 254 insertions, 101 deletions
diff --git a/accessible/windows/ia2/ia2Accessible.cpp b/accessible/windows/ia2/ia2Accessible.cpp
index 2092730932..7318dd5e6f 100644
--- a/accessible/windows/ia2/ia2Accessible.cpp
+++ b/accessible/windows/ia2/ia2Accessible.cpp
@@ -156,7 +156,7 @@ ia2Accessible::role(long* aRole) {
if (!acc) return CO_E_OBJNOTCONNECTED;
#define ROLE(_geckoRole, stringRole, ariaRole, atkRole, macRole, macSubrole, \
- msaaRole, ia2Role, androidClass, nameRule) \
+ msaaRole, ia2Role, androidClass, iosIsElement, nameRule) \
case roles::_geckoRole: \
*aRole = ia2Role; \
break;
diff --git a/accessible/windows/ia2/ia2AccessibleAction.cpp b/accessible/windows/ia2/ia2AccessibleAction.cpp
index d89bd79ce1..1e1dbaea7b 100644
--- a/accessible/windows/ia2/ia2AccessibleAction.cpp
+++ b/accessible/windows/ia2/ia2AccessibleAction.cpp
@@ -11,6 +11,7 @@
#include "AccessibleWrap.h"
#include "IUnknownImpl.h"
+#include "MsaaAccessible.h"
using namespace mozilla::a11y;
diff --git a/accessible/windows/ia2/ia2AccessibleComponent.cpp b/accessible/windows/ia2/ia2AccessibleComponent.cpp
index 9c22a66cad..a0074bcaa1 100644
--- a/accessible/windows/ia2/ia2AccessibleComponent.cpp
+++ b/accessible/windows/ia2/ia2AccessibleComponent.cpp
@@ -12,6 +12,7 @@
#include "AccessibleWrap.h"
#include "States.h"
#include "IUnknownImpl.h"
+#include "MsaaAccessible.h"
#include "nsIFrame.h"
diff --git a/accessible/windows/ia2/ia2AccessibleHyperlink.cpp b/accessible/windows/ia2/ia2AccessibleHyperlink.cpp
index 9d71cfb411..40dff39131 100644
--- a/accessible/windows/ia2/ia2AccessibleHyperlink.cpp
+++ b/accessible/windows/ia2/ia2AccessibleHyperlink.cpp
@@ -5,11 +5,14 @@
* 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/. */
+#include "ia2AccessibleHyperlink.h"
+
#include "AccessibleHyperlink.h"
#include "AccessibleHyperlink_i.c"
#include "AccessibleWrap.h"
#include "IUnknownImpl.h"
+#include "MsaaAccessible.h"
#include "nsIURI.h"
using namespace mozilla::a11y;
diff --git a/accessible/windows/ia2/ia2AccessibleValue.cpp b/accessible/windows/ia2/ia2AccessibleValue.cpp
index b0b9a729e3..93640354c2 100644
--- a/accessible/windows/ia2/ia2AccessibleValue.cpp
+++ b/accessible/windows/ia2/ia2AccessibleValue.cpp
@@ -12,6 +12,7 @@
#include "AccessibleWrap.h"
#include "LocalAccessible-inl.h"
#include "IUnknownImpl.h"
+#include "MsaaAccessible.h"
#include "mozilla/FloatingPoint.h"
diff --git a/accessible/windows/ia2/moz.build b/accessible/windows/ia2/moz.build
index 53f930fd5a..4b566f5a5c 100644
--- a/accessible/windows/ia2/moz.build
+++ b/accessible/windows/ia2/moz.build
@@ -44,6 +44,7 @@ LOCAL_INCLUDES += [
"/accessible/html",
"/accessible/windows",
"/accessible/windows/msaa",
+ "/accessible/windows/uia",
"/accessible/xpcom",
"/accessible/xul",
]
diff --git a/accessible/windows/msaa/AccessibleWrap.cpp b/accessible/windows/msaa/AccessibleWrap.cpp
index abab007775..d681e8e658 100644
--- a/accessible/windows/msaa/AccessibleWrap.cpp
+++ b/accessible/windows/msaa/AccessibleWrap.cpp
@@ -31,6 +31,8 @@ using namespace mozilla::a11y;
AccessibleWrap::AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc)
: LocalAccessible(aContent, aDoc) {}
+AccessibleWrap::~AccessibleWrap() = default;
+
NS_IMPL_ISUPPORTS_INHERITED0(AccessibleWrap, LocalAccessible)
void AccessibleWrap::Shutdown() {
@@ -75,6 +77,24 @@ bool AccessibleWrap::IsRootForHWND() {
return thisHwnd != parentHwnd;
}
+static void UpdateSystemCaretForHwnd(HWND aCaretWnd,
+ const LayoutDeviceIntRect& aCaretRect) {
+ if (!aCaretWnd || aCaretRect.IsEmpty()) {
+ return;
+ }
+
+ // Create invisible bitmap for caret, otherwise its appearance interferes
+ // with Gecko caret
+ nsAutoBitmap caretBitMap(CreateBitmap(1, aCaretRect.Height(), 1, 1, nullptr));
+ if (::CreateCaret(aCaretWnd, caretBitMap, 1,
+ aCaretRect.Height())) { // Also destroys the last caret
+ ::ShowCaret(aCaretWnd);
+ POINT clientPoint{aCaretRect.X(), aCaretRect.Y()};
+ ::ScreenToClient(aCaretWnd, &clientPoint);
+ ::SetCaretPos(clientPoint.x, clientPoint.y);
+ }
+}
+
/* static */
void AccessibleWrap::UpdateSystemCaretFor(
Accessible* aAccessible, const LayoutDeviceIntRect& aCaretRect) {
@@ -106,7 +126,7 @@ void AccessibleWrap::UpdateSystemCaretFor(LocalAccessible* aAccessible) {
HWND caretWnd =
reinterpret_cast<HWND>(widget->GetNativeData(NS_NATIVE_WINDOW));
- UpdateSystemCaretFor(caretWnd, caretRect);
+ UpdateSystemCaretForHwnd(caretWnd, caretRect);
}
/* static */
@@ -117,24 +137,5 @@ void AccessibleWrap::UpdateSystemCaretFor(
// The HWND should be the real widget HWND, not an emulated HWND.
// We get the HWND from the proxy's outer doc to bypass window emulation.
LocalAccessible* outerDoc = aProxy->OuterDocOfRemoteBrowser();
- UpdateSystemCaretFor(MsaaAccessible::GetHWNDFor(outerDoc), aCaretRect);
-}
-
-/* static */
-void AccessibleWrap::UpdateSystemCaretFor(
- HWND aCaretWnd, const LayoutDeviceIntRect& aCaretRect) {
- if (!aCaretWnd || aCaretRect.IsEmpty()) {
- return;
- }
-
- // Create invisible bitmap for caret, otherwise its appearance interferes
- // with Gecko caret
- nsAutoBitmap caretBitMap(CreateBitmap(1, aCaretRect.Height(), 1, 1, nullptr));
- if (::CreateCaret(aCaretWnd, caretBitMap, 1,
- aCaretRect.Height())) { // Also destroys the last caret
- ::ShowCaret(aCaretWnd);
- POINT clientPoint{aCaretRect.X(), aCaretRect.Y()};
- ::ScreenToClient(aCaretWnd, &clientPoint);
- ::SetCaretPos(clientPoint.x, clientPoint.y);
- }
+ UpdateSystemCaretForHwnd(MsaaAccessible::GetHWNDFor(outerDoc), aCaretRect);
}
diff --git a/accessible/windows/msaa/AccessibleWrap.h b/accessible/windows/msaa/AccessibleWrap.h
index aeeea87e77..941ac06e40 100644
--- a/accessible/windows/msaa/AccessibleWrap.h
+++ b/accessible/windows/msaa/AccessibleWrap.h
@@ -9,7 +9,6 @@
#include "nsCOMPtr.h"
#include "LocalAccessible.h"
-#include "MsaaAccessible.h"
#include "mozilla/a11y/RemoteAccessible.h"
#include "mozilla/Attributes.h"
#include "mozilla/mscom/Utils.h"
@@ -20,6 +19,7 @@
namespace mozilla {
namespace a11y {
class DocRemoteAccessibleWrap;
+class MsaaAccessible;
/**
* Windows specific functionality for an accessibility tree node that originated
@@ -50,10 +50,6 @@ class AccessibleWrap : public LocalAccessible {
static void UpdateSystemCaretFor(RemoteAccessible* aProxy,
const LayoutDeviceIntRect& aCaretRect);
- private:
- static void UpdateSystemCaretFor(HWND aCaretWnd,
- const LayoutDeviceIntRect& aCaretRect);
-
public:
/**
* Determine whether this is the root accessible for its HWND.
@@ -64,7 +60,7 @@ class AccessibleWrap : public LocalAccessible {
virtual void GetNativeInterface(void** aOutAccessible) override;
protected:
- virtual ~AccessibleWrap() = default;
+ virtual ~AccessibleWrap();
RefPtr<MsaaAccessible> mMsaa;
};
diff --git a/accessible/windows/msaa/ApplicationAccessibleWrap.cpp b/accessible/windows/msaa/ApplicationAccessibleWrap.cpp
index 6a10a8bddc..ea0689a694 100644
--- a/accessible/windows/msaa/ApplicationAccessibleWrap.cpp
+++ b/accessible/windows/msaa/ApplicationAccessibleWrap.cpp
@@ -11,6 +11,7 @@
#include "AccAttributes.h"
#include "nsServiceManagerUtils.h"
#include "mozilla/Components.h"
+#include "MsaaAccessible.h"
using namespace mozilla;
using namespace mozilla::a11y;
diff --git a/accessible/windows/msaa/Compatibility.cpp b/accessible/windows/msaa/Compatibility.cpp
index 440f327520..42bc2386bb 100644
--- a/accessible/windows/msaa/Compatibility.cpp
+++ b/accessible/windows/msaa/Compatibility.cpp
@@ -103,7 +103,7 @@ void Compatibility::Init() {
// Note we collect some AT statistics/telemetry here for convenience.
InitConsumers();
- CrashReporter::AnnotateCrashReport(
+ CrashReporter::RecordAnnotationNSCString(
CrashReporter::Annotation::AccessibilityInProcClient,
nsPrintfCString("0x%X", sConsumers));
@@ -142,9 +142,20 @@ void Compatibility::GetHumanReadableConsumersStr(nsAString& aResult) {
}
}
-// Time when SuppressA11yForClipboardCopy() was called, as returned by
-// ::GetTickCount().
-static DWORD sA11yClipboardCopySuppressionStartTime = 0;
+struct SuppressionTimer {
+ constexpr SuppressionTimer() = default;
+ void Start() { mStart = ::GetTickCount(); }
+ bool IsActive(DWORD aTickCount) const {
+ return mStart && aTickCount - mStart < kSuppressTimeout;
+ }
+ // Last time Start() was called, as returned by ::GetTickCount().
+ DWORD mStart = 0;
+
+ static constexpr DWORD kSuppressTimeout = 1500; // ms
+};
+
+static SuppressionTimer sClipboardSuppressionTimer;
+static SuppressionTimer sSnapLayoutsSuppressionTimer;
/* static */
void Compatibility::SuppressA11yForClipboardCopy() {
@@ -166,16 +177,40 @@ void Compatibility::SuppressA11yForClipboardCopy() {
}();
if (doSuppress) {
- sA11yClipboardCopySuppressionStartTime = ::GetTickCount();
+ sClipboardSuppressionTimer.Start();
}
}
/* static */
-bool Compatibility::IsA11ySuppressedForClipboardCopy() {
- constexpr DWORD kSuppressTimeout = 1500; // ms
- if (!sA11yClipboardCopySuppressionStartTime) {
- return false;
+void Compatibility::SuppressA11yForSnapLayouts() {
+ // Bug 1883132: Snap Layouts might enable a11y to find the maximize button
+ // position.
+ bool doSuppress = [&] {
+ switch (StaticPrefs::accessibility_windows_suppress_for_snap_layout()) {
+ case 0:
+ return false;
+ case 1:
+ return true;
+ default:
+ // Our workaround for Snap Layouts is needed from Windows 11 22H2
+ return IsWin1122H2OrLater();
+ }
+ }();
+
+ if (doSuppress) {
+ sSnapLayoutsSuppressionTimer.Start();
+ }
+}
+
+/* static */
+SuppressionReasons Compatibility::A11ySuppressionReasons() {
+ const auto now = ::GetTickCount();
+ auto reasons = SuppressionReasons::None;
+ if (sClipboardSuppressionTimer.IsActive(now)) {
+ reasons |= SuppressionReasons::Clipboard;
+ }
+ if (sSnapLayoutsSuppressionTimer.IsActive(now)) {
+ reasons |= SuppressionReasons::SnapLayouts;
}
- return ::GetTickCount() - sA11yClipboardCopySuppressionStartTime <
- kSuppressTimeout;
+ return reasons;
}
diff --git a/accessible/windows/msaa/Compatibility.h b/accessible/windows/msaa/Compatibility.h
index d1e1b0e9ac..05d2e82400 100644
--- a/accessible/windows/msaa/Compatibility.h
+++ b/accessible/windows/msaa/Compatibility.h
@@ -13,8 +13,14 @@
#include <stdint.h>
-namespace mozilla {
-namespace a11y {
+namespace mozilla::a11y {
+
+enum class SuppressionReasons : uint8_t {
+ None = 0,
+ Clipboard = 1 << 0,
+ SnapLayouts = 1 << 1,
+};
+MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(SuppressionReasons);
/**
* Used to get compatibility modes. Note, modes are computed at accessibility
@@ -78,7 +84,11 @@ class Compatibility {
unsigned long long aVersion);
static void SuppressA11yForClipboardCopy();
- static bool IsA11ySuppressedForClipboardCopy();
+ static void SuppressA11yForSnapLayouts();
+ static bool IsA11ySuppressed() {
+ return A11ySuppressionReasons() != SuppressionReasons::None;
+ }
+ static SuppressionReasons A11ySuppressionReasons();
private:
Compatibility();
@@ -112,8 +122,7 @@ class Compatibility {
static uint32_t sConsumers;
};
-} // namespace a11y
-} // namespace mozilla
+} // namespace mozilla::a11y
// Convert the 4 (decimal) components of a DLL version number into a
// single unsigned long long, as needed by
diff --git a/accessible/windows/msaa/LazyInstantiator.cpp b/accessible/windows/msaa/LazyInstantiator.cpp
index 5f8ae9a8a4..61814d059a 100644
--- a/accessible/windows/msaa/LazyInstantiator.cpp
+++ b/accessible/windows/msaa/LazyInstantiator.cpp
@@ -249,11 +249,7 @@ bool LazyInstantiator::ShouldInstantiate(const DWORD aClientPid) {
* various different types of clients.
*/
bool LazyInstantiator::ShouldInstantiate() {
- if (Compatibility::IsA11ySuppressedForClipboardCopy()) {
- // Bug 1774285: Windows Suggested Actions (introduced in Windows 11 22H2)
- // walks the entire a11y tree using UIA whenever anything is copied to the
- // clipboard. This causes an unacceptable hang, particularly when the cache
- // is disabled. Don't allow a11y to be instantiated by this.
+ if (Compatibility::IsA11ySuppressed()) {
return false;
}
if (DWORD pid = GetRemoteMsaaClientPid()) {
diff --git a/accessible/windows/msaa/MsaaAccessible.cpp b/accessible/windows/msaa/MsaaAccessible.cpp
index 702f8341dc..3a0e8fc726 100644
--- a/accessible/windows/msaa/MsaaAccessible.cpp
+++ b/accessible/windows/msaa/MsaaAccessible.cpp
@@ -522,6 +522,10 @@ MsaaAccessible::QueryInterface(REFIID iid, void** ppv) {
if (SUCCEEDED(hr)) {
return hr;
}
+ hr = uiaRawElmProvider::QueryInterface(iid, ppv);
+ if (SUCCEEDED(hr)) {
+ return hr;
+ }
}
if (*ppv) {
(reinterpret_cast<IUnknown*>(*ppv))->AddRef();
@@ -604,16 +608,20 @@ MsaaAccessible::get_accChildCount(long __RPC_FAR* pcountChildren) {
if (!mAcc) return CO_E_OBJNOTCONNECTED;
- if (Compatibility::IsA11ySuppressedForClipboardCopy() && mAcc->IsRoot()) {
+ if ((Compatibility::A11ySuppressionReasons() &
+ SuppressionReasons::Clipboard) &&
+ mAcc->IsRoot()) {
// Bug 1798098: Windows Suggested Actions (introduced in Windows 11 22H2)
- // might walk the entire a11y tree using UIA whenever anything is copied to
- // the clipboard. This causes an unacceptable hang, particularly when the
- // cache is disabled. We prevent this tree walk by returning a 0 child count
- // for the root window, from which Windows might walk.
+ // might walk the entire a11y tree using UIA whenever anything is copied
+ // to the clipboard. This causes an unacceptable hang, particularly when
+ // the cache is disabled. We prevent this tree walk by returning a 0 child
+ // count for the root window, from which Windows might walk.
return S_OK;
}
- if (nsAccUtils::MustPrune(mAcc)) return S_OK;
+ if (nsAccUtils::MustPrune(mAcc)) {
+ return S_OK;
+ }
*pcountChildren = mAcc->ChildCount();
return S_OK;
@@ -761,7 +769,7 @@ MsaaAccessible::get_accRole(
uint32_t msaaRole = 0;
#define ROLE(_geckoRole, stringRole, ariaRole, atkRole, macRole, macSubrole, \
- _msaaRole, ia2Role, androidClass, nameRule) \
+ _msaaRole, ia2Role, androidClass, iosIsElement, nameRule) \
case roles::_geckoRole: \
msaaRole = _msaaRole; \
break;
diff --git a/accessible/windows/msaa/MsaaAccessible.h b/accessible/windows/msaa/MsaaAccessible.h
index 034db860ed..6d6582f010 100644
--- a/accessible/windows/msaa/MsaaAccessible.h
+++ b/accessible/windows/msaa/MsaaAccessible.h
@@ -12,8 +12,9 @@
#include "ia2AccessibleHyperlink.h"
#include "ia2AccessibleValue.h"
#include "IUnknownImpl.h"
-#include "mozilla/a11y/MsaaIdGenerator.h"
+#include "MsaaIdGenerator.h"
#include "nsXULAppAPI.h"
+#include "uiaRawElmProvider.h"
namespace mozilla {
namespace a11y {
@@ -25,7 +26,8 @@ class sdnAccessible;
class MsaaAccessible : public ia2Accessible,
public ia2AccessibleComponent,
public ia2AccessibleHyperlink,
- public ia2AccessibleValue {
+ public ia2AccessibleValue,
+ public uiaRawElmProvider {
public:
static MsaaAccessible* Create(Accessible* aAcc);
diff --git a/accessible/windows/msaa/MsaaIdGenerator.cpp b/accessible/windows/msaa/MsaaIdGenerator.cpp
index 9f220365e3..8f0040cf02 100644
--- a/accessible/windows/msaa/MsaaIdGenerator.cpp
+++ b/accessible/windows/msaa/MsaaIdGenerator.cpp
@@ -6,11 +6,11 @@
#include "MsaaIdGenerator.h"
-#include "mozilla/a11y/MsaaAccessible.h"
#include "mozilla/Assertions.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/Unused.h"
+#include "MsaaAccessible.h"
#include "nsAccessibilityService.h"
#include "sdnAccessible.h"
diff --git a/accessible/windows/msaa/Platform.cpp b/accessible/windows/msaa/Platform.cpp
index 40dddac215..018042c5d3 100644
--- a/accessible/windows/msaa/Platform.cpp
+++ b/accessible/windows/msaa/Platform.cpp
@@ -9,6 +9,7 @@
#include "AccEvent.h"
#include "Compatibility.h"
#include "HyperTextAccessible.h"
+#include "MsaaAccessible.h"
#include "nsWinUtils.h"
#include "mozilla/a11y/DocAccessibleParent.h"
#include "mozilla/a11y/RemoteAccessible.h"
@@ -196,9 +197,8 @@ static void AccumulateInstantiatorTelemetry(const nsAString& aValue) {
#if defined(MOZ_TELEMETRY_REPORTING)
Telemetry::ScalarSet(Telemetry::ScalarID::A11Y_INSTANTIATORS, aValue);
#endif // defined(MOZ_TELEMETRY_REPORTING)
- CrashReporter::AnnotateCrashReport(
- CrashReporter::Annotation::AccessibilityClient,
- NS_ConvertUTF16toUTF8(aValue));
+ CrashReporter::RecordAnnotationNSString(
+ CrashReporter::Annotation::AccessibilityClient, aValue);
}
}
diff --git a/accessible/windows/msaa/ServiceProvider.cpp b/accessible/windows/msaa/ServiceProvider.cpp
index b2b005f3b4..ba04d0ecde 100644
--- a/accessible/windows/msaa/ServiceProvider.cpp
+++ b/accessible/windows/msaa/ServiceProvider.cpp
@@ -16,7 +16,7 @@
#include "uiaRawElmProvider.h"
#include "mozilla/a11y/DocAccessibleChild.h"
-#include "mozilla/Preferences.h"
+#include "mozilla/StaticPrefs_accessibility.h"
#include "ISimpleDOM.h"
@@ -40,17 +40,6 @@ ServiceProvider::QueryService(REFGUID aGuidService, REFIID aIID,
if (!acc) {
return CO_E_OBJNOTCONNECTED;
}
- AccessibleWrap* localAcc = mMsaa->LocalAcc();
-
- // UIA IAccessibleEx
- if (aGuidService == IID_IAccessibleEx &&
- Preferences::GetBool("accessibility.uia.enable") && localAcc) {
- uiaRawElmProvider* accEx = new uiaRawElmProvider(localAcc);
- HRESULT hr = accEx->QueryInterface(aIID, aInstancePtr);
- if (FAILED(hr)) delete accEx;
-
- return hr;
- }
// Provide a special service ID for getting the accessible for the browser tab
// document that contains this accessible object. If this accessible object
@@ -96,8 +85,12 @@ ServiceProvider::QueryService(REFGUID aGuidService, REFIID aIID,
{0xb6, 0x61, 0x00, 0xaa, 0x00, 0x4c, 0xd6, 0xd8}};
if (aGuidService == IID_ISimpleDOMNode ||
aGuidService == IID_SimpleDOMDeprecated ||
- aGuidService == IID_IAccessible || aGuidService == IID_IAccessible2)
+ aGuidService == IID_IAccessible || aGuidService == IID_IAccessible2 ||
+ // UIA IAccessibleEx
+ (aGuidService == IID_IAccessibleEx &&
+ StaticPrefs::accessibility_uia_enable())) {
return mMsaa->QueryInterface(aIID, aInstancePtr);
+ }
return E_INVALIDARG;
}
diff --git a/accessible/windows/msaa/moz.build b/accessible/windows/msaa/moz.build
index 1b56c2eacf..ae5a036ec2 100644
--- a/accessible/windows/msaa/moz.build
+++ b/accessible/windows/msaa/moz.build
@@ -12,8 +12,6 @@ EXPORTS.mozilla.a11y += [
"AccessibleWrap.h",
"Compatibility.h",
"LazyInstantiator.h",
- "MsaaAccessible.h",
- "MsaaIdGenerator.h",
"nsWinUtils.h",
]
diff --git a/accessible/windows/msaa/nsWinUtils.cpp b/accessible/windows/msaa/nsWinUtils.cpp
index 6eb7d290dd..42d3d374f7 100644
--- a/accessible/windows/msaa/nsWinUtils.cpp
+++ b/accessible/windows/msaa/nsWinUtils.cpp
@@ -9,6 +9,7 @@
#include "Compatibility.h"
#include "DocAccessible.h"
+#include "MsaaAccessible.h"
#include "nsAccessibilityService.h"
#include "nsCoreUtils.h"
diff --git a/accessible/windows/sdn/moz.build b/accessible/windows/sdn/moz.build
index 8d76b7482e..4f7b77efad 100644
--- a/accessible/windows/sdn/moz.build
+++ b/accessible/windows/sdn/moz.build
@@ -15,6 +15,7 @@ LOCAL_INCLUDES += [
"/accessible/generic",
"/accessible/html",
"/accessible/windows/msaa",
+ "/accessible/windows/uia",
"/accessible/xpcom",
"/accessible/xul",
]
diff --git a/accessible/windows/uia/uiaRawElmProvider.cpp b/accessible/windows/uia/uiaRawElmProvider.cpp
index c78dbca7fe..881ed22277 100644
--- a/accessible/windows/uia/uiaRawElmProvider.cpp
+++ b/accessible/windows/uia/uiaRawElmProvider.cpp
@@ -10,6 +10,9 @@
#include "AccessibleWrap.h"
#include "ARIAMap.h"
#include "LocalAccessible-inl.h"
+#include "mozilla/a11y/RemoteAccessible.h"
+#include "MsaaAccessible.h"
+#include "nsTextEquivUtils.h"
using namespace mozilla;
using namespace mozilla::a11y;
@@ -18,6 +21,23 @@ using namespace mozilla::a11y;
// uiaRawElmProvider
////////////////////////////////////////////////////////////////////////////////
+Accessible* uiaRawElmProvider::Acc() {
+ return static_cast<MsaaAccessible*>(this)->Acc();
+}
+
+// IUnknown
+
+// Because uiaRawElmProvider inherits multiple COM interfaces (and thus multiple
+// IUnknowns), we need to explicitly implement AddRef and Release to make
+// our QueryInterface implementation (IMPL_IUNKNOWN2) happy.
+ULONG STDMETHODCALLTYPE uiaRawElmProvider::AddRef() {
+ return static_cast<MsaaAccessible*>(this)->AddRef();
+}
+
+ULONG STDMETHODCALLTYPE uiaRawElmProvider::Release() {
+ return static_cast<MsaaAccessible*>(this)->Release();
+}
+
IMPL_IUNKNOWN2(uiaRawElmProvider, IAccessibleEx, IRawElementProviderSimple)
////////////////////////////////////////////////////////////////////////////////
@@ -30,7 +50,7 @@ uiaRawElmProvider::GetObjectForChild(
*aAccEx = nullptr;
- return mAcc->IsDefunct() ? CO_E_OBJNOTCONNECTED : S_OK;
+ return Acc() ? S_OK : CO_E_OBJNOTCONNECTED;
}
STDMETHODIMP
@@ -41,11 +61,12 @@ uiaRawElmProvider::GetIAccessiblePair(__RPC__deref_out_opt IAccessible** aAcc,
*aAcc = nullptr;
*aIdChild = 0;
- if (mAcc->IsDefunct()) return CO_E_OBJNOTCONNECTED;
+ if (!Acc()) {
+ return CO_E_OBJNOTCONNECTED;
+ }
*aIdChild = CHILDID_SELF;
- RefPtr<IAccessible> copy;
- mAcc->GetNativeInterface(getter_AddRefs(copy));
+ RefPtr<IAccessible> copy = static_cast<MsaaAccessible*>(this);
copy.forget(aAcc);
return S_OK;
@@ -54,9 +75,12 @@ uiaRawElmProvider::GetIAccessiblePair(__RPC__deref_out_opt IAccessible** aAcc,
STDMETHODIMP
uiaRawElmProvider::GetRuntimeId(__RPC__deref_out_opt SAFEARRAY** aRuntimeIds) {
if (!aRuntimeIds) return E_INVALIDARG;
+ Accessible* acc = Acc();
+ if (!acc) {
+ return CO_E_OBJNOTCONNECTED;
+ }
- int ids[] = {UiaAppendRuntimeId,
- static_cast<int>(reinterpret_cast<intptr_t>(mAcc->UniqueID()))};
+ int ids[] = {UiaAppendRuntimeId, MsaaAccessible::GetChildIDFor(acc)};
*aRuntimeIds = SafeArrayCreateVector(VT_I4, 0, 2);
if (!*aRuntimeIds) return E_OUTOFMEMORY;
@@ -108,16 +132,24 @@ uiaRawElmProvider::GetPropertyValue(PROPERTYID aPropertyId,
__RPC__out VARIANT* aPropertyValue) {
if (!aPropertyValue) return E_INVALIDARG;
- if (mAcc->IsDefunct()) return CO_E_OBJNOTCONNECTED;
+ Accessible* acc = Acc();
+ if (!acc) {
+ return CO_E_OBJNOTCONNECTED;
+ }
+ LocalAccessible* localAcc = acc->AsLocal();
aPropertyValue->vt = VT_EMPTY;
switch (aPropertyId) {
// Accelerator Key / shortcut.
case UIA_AcceleratorKeyPropertyId: {
+ if (!localAcc) {
+ // KeyboardShortcut is only currently relevant for LocalAccessible.
+ break;
+ }
nsAutoString keyString;
- mAcc->KeyboardShortcut().ToString(keyString);
+ localAcc->KeyboardShortcut().ToString(keyString);
if (!keyString.IsEmpty()) {
aPropertyValue->vt = VT_BSTR;
@@ -132,7 +164,7 @@ uiaRawElmProvider::GetPropertyValue(PROPERTYID aPropertyId,
case UIA_AccessKeyPropertyId: {
nsAutoString keyString;
- mAcc->AccessKey().ToString(keyString);
+ acc->AccessKey().ToString(keyString);
if (!keyString.IsEmpty()) {
aPropertyValue->vt = VT_BSTR;
@@ -147,7 +179,7 @@ uiaRawElmProvider::GetPropertyValue(PROPERTYID aPropertyId,
case UIA_AriaRolePropertyId: {
nsAutoString xmlRoles;
- RefPtr<AccAttributes> attributes = mAcc->Attributes();
+ RefPtr<AccAttributes> attributes = acc->Attributes();
attributes->GetAttribute(nsGkAtoms::xmlroles, xmlRoles);
if (!xmlRoles.IsEmpty()) {
@@ -161,9 +193,16 @@ uiaRawElmProvider::GetPropertyValue(PROPERTYID aPropertyId,
// ARIA Properties
case UIA_AriaPropertiesPropertyId: {
+ if (!localAcc) {
+ // XXX Implement a unified version of this. We don't cache explicit
+ // values for many ARIA attributes in RemoteAccessible; e.g. we use the
+ // checked state rather than caching aria-checked:true. Thus, a unified
+ // implementation will need to work with State(), etc.
+ break;
+ }
nsAutoString ariaProperties;
- aria::AttrIterator attribIter(mAcc->GetContent());
+ aria::AttrIterator attribIter(localAcc->GetContent());
while (attribIter.Next()) {
nsAutoString attribName, attribValue;
nsAutoString value;
@@ -190,6 +229,12 @@ uiaRawElmProvider::GetPropertyValue(PROPERTYID aPropertyId,
break;
}
+
+ case UIA_IsControlElementPropertyId:
+ case UIA_IsContentElementPropertyId:
+ aPropertyValue->vt = VT_BOOL;
+ aPropertyValue->boolVal = IsControl() ? VARIANT_TRUE : VARIANT_FALSE;
+ return S_OK;
}
return S_OK;
@@ -204,3 +249,68 @@ uiaRawElmProvider::get_HostRawElementProvider(
*aRawElmProvider = nullptr;
return S_OK;
}
+
+// Private methods
+
+bool uiaRawElmProvider::IsControl() {
+ // UIA provides multiple views of the tree: raw, control and content. The
+ // control and content views should only contain elements which a user cares
+ // about when navigating.
+ Accessible* acc = Acc();
+ MOZ_ASSERT(acc);
+ if (acc->IsTextLeaf()) {
+ // If an ancestor control allows the name to be generated from content, do
+ // not expose this text leaf as a control. Otherwise, the user will see the
+ // text twice: once as the label of the control and once for the text leaf.
+ for (Accessible* ancestor = acc->Parent(); ancestor && !ancestor->IsDoc();
+ ancestor = ancestor->Parent()) {
+ if (nsTextEquivUtils::HasNameRule(ancestor, eNameFromSubtreeRule)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ if (acc->HasNumericValue() || acc->ActionCount() > 0) {
+ return true;
+ }
+ uint64_t state = acc->State();
+ if (state & states::FOCUSABLE) {
+ return true;
+ }
+ if (state & states::EDITABLE) {
+ Accessible* parent = acc->Parent();
+ if (parent && !(parent->State() & states::EDITABLE)) {
+ // This is the root of a rich editable control.
+ return true;
+ }
+ }
+
+ // Don't treat generic or text containers as controls unless they have a name
+ // or description.
+ switch (acc->Role()) {
+ case roles::EMPHASIS:
+ case roles::MARK:
+ case roles::PARAGRAPH:
+ case roles::SECTION:
+ case roles::STRONG:
+ case roles::SUBSCRIPT:
+ case roles::SUPERSCRIPT:
+ case roles::TEXT:
+ case roles::TEXT_CONTAINER: {
+ if (!acc->NameIsEmpty()) {
+ return true;
+ }
+ nsAutoString text;
+ acc->Description(text);
+ if (!text.IsEmpty()) {
+ return true;
+ }
+ return false;
+ }
+ default:
+ break;
+ }
+
+ return true;
+}
diff --git a/accessible/windows/uia/uiaRawElmProvider.h b/accessible/windows/uia/uiaRawElmProvider.h
index 4a4aecdbe2..0e5172c805 100644
--- a/accessible/windows/uia/uiaRawElmProvider.h
+++ b/accessible/windows/uia/uiaRawElmProvider.h
@@ -8,25 +8,24 @@
#define mozilla_a11y_uiaRawElmProvider_h__
#include "objbase.h"
-#include "AccessibleWrap.h"
#include "IUnknownImpl.h"
#include "uiautomation.h"
namespace mozilla {
namespace a11y {
-class AccessibleWrap;
+class Accessible;
/**
* IRawElementProviderSimple implementation (maintains IAccessibleEx approach).
*/
-class uiaRawElmProvider final : public IAccessibleEx,
- public IRawElementProviderSimple {
+class uiaRawElmProvider : public IAccessibleEx,
+ public IRawElementProviderSimple {
public:
- explicit uiaRawElmProvider(AccessibleWrap* aAcc) : mAcc(aAcc) {}
-
// IUnknown
- DECL_IUNKNOWN
+ DECL_IUNKNOWN_INHERITED
+ ULONG STDMETHODCALLTYPE AddRef() override;
+ ULONG STDMETHODCALLTYPE Release() override;
// IAccessibleEx
virtual HRESULT STDMETHODCALLTYPE GetObjectForChild(
@@ -61,12 +60,8 @@ class uiaRawElmProvider final : public IAccessibleEx,
aRawElmProvider);
private:
- uiaRawElmProvider() = delete;
- uiaRawElmProvider& operator=(const uiaRawElmProvider&) = delete;
- uiaRawElmProvider(const uiaRawElmProvider&) = delete;
-
- protected:
- RefPtr<AccessibleWrap> mAcc;
+ Accessible* Acc();
+ bool IsControl();
};
} // namespace a11y