From a4c1ba2cb6107d8db0fe5cd2cf1b817fa33cf686 Mon Sep 17 00:00:00 2001 From: Bill Dengler Date: Thu, 5 Sep 2024 09:03:02 -0700 Subject: [PATCH] fix: Identify the root (desktop) element by UIA class name, not runtime ID (#1048) On Windows 11 24H2 (GE), the runtime ID of the desktop element changed from `[2A,10010]` to `[2A,1000C]`, causing live inspect in Accessibility Insights for Windows to break. This commit switches to identifying the desktop element by its UIA class name, which has been stable across all supported Windows versions. Addresses microsoft/accessibility-insights-windows#1837. --- src/Core/Misc/ExtensionMethods.cs | 26 +++++++------------ .../PropertyConditions/BoolPropertiesTests.cs | 4 +-- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/Core/Misc/ExtensionMethods.cs b/src/Core/Misc/ExtensionMethods.cs index 57dd14d24..7f0db8814 100644 --- a/src/Core/Misc/ExtensionMethods.cs +++ b/src/Core/Misc/ExtensionMethods.cs @@ -27,13 +27,14 @@ namespace Axe.Windows.Core.Misc public static class ExtensionMethods { /// - /// DesktopElement runtime Id. + /// UIA class name of the root (desktop) element /// - const string DesktopElementRuntimeId = "[2A,10010]"; + const string DesktopElementClassName = "#32769"; + /// /// WCOS runtime ID /// - const string WCOSElementRuntimeId = "[0,0]"; + const string WCOSDesktopElementRuntimeId = "[0,0]"; /// /// Get A11yElementData object out of A11yElement @@ -638,19 +639,12 @@ public static bool IsOffScreen(this A11yElement e) /// public static bool IsRootElement(this IA11yElement e) { - // on Desktop, RuntimeId is available with specific ID. - // however on WCOS, the desktop equivalent process is PID 0 and runtime ID is 0,0 - return e != null && (e.RuntimeId == DesktopElementRuntimeId || (e.ProcessId == 0 && e.RuntimeId == WCOSElementRuntimeId)); - } - - /// - /// Check whether string is matched with DesktopElment runtime Id. - /// - /// - /// - public static bool IsDesktopElementRuntimeId(string str) - { - return DesktopElementRuntimeId == str; + // On Windows, check for the desktop (root) element by class name. + // On WCOS, check for the desktop by process and runtime IDs. + return e != null && ( + e.ClassName == DesktopElementClassName + || (e.ProcessId == 0 && e.RuntimeId == WCOSDesktopElementRuntimeId) + ); } /// diff --git a/src/RulesTest/PropertyConditions/BoolPropertiesTests.cs b/src/RulesTest/PropertyConditions/BoolPropertiesTests.cs index ed29042ca..8bbf7e608 100644 --- a/src/RulesTest/PropertyConditions/BoolPropertiesTests.cs +++ b/src/RulesTest/PropertyConditions/BoolPropertiesTests.cs @@ -130,7 +130,7 @@ public void TestIsDesktopTrue() { using (var e = new MockA11yElement()) { - var property = new A11yProperty(PropertyType.UIA_RuntimeIdPropertyId, new int[] { 0x2A, 0x10010 }); + var property = new A11yProperty(PropertyType.UIA_ClassNamePropertyId, "#32769"); e.Properties.Add(property.Id, property); Assert.IsTrue(IsDesktop.Matches(e)); } // using @@ -159,7 +159,7 @@ public void TestIsNotDesktopFalse() { using (var e = new MockA11yElement()) { - var property = new A11yProperty(PropertyType.UIA_RuntimeIdPropertyId, new int[] { 0x2A, 0x10010 }); + var property = new A11yProperty(PropertyType.UIA_ClassNamePropertyId, "#32769"); e.Properties.Add(property.Id, property); Assert.IsFalse(IsNotDesktop.Matches(e)); } // using