Bug 1621519: Implement xpcAccessible::GetDeepestChildAtPoint for ProxyAccessibles on Windows. r=yzen
authorJames Teh <jteh@mozilla.com>
Wed, 11 Mar 2020 23:26:18 +0000
changeset 518283 e8984249397a68e0fbfc5ee5ae5fb43413f8f7dd
parent 518282 53ad80b0102201c7a9acab33347e74c7ca0e52aa
child 518284 e6e5816403d958a0bcaf427195ca7b113263d01f
push id37207
push useropoprus@mozilla.com
push dateThu, 12 Mar 2020 09:33:12 +0000
treeherdermozilla-central@ffd615bf92dd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersyzen
bugs1621519
milestone76.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1621519: Implement xpcAccessible::GetDeepestChildAtPoint for ProxyAccessibles on Windows. r=yzen Differential Revision: https://phabricator.services.mozilla.com/D66359
accessible/ipc/win/ProxyAccessible.cpp
accessible/xpcom/xpcAccessible.cpp
--- a/accessible/ipc/win/ProxyAccessible.cpp
+++ b/accessible/ipc/win/ProxyAccessible.cpp
@@ -733,10 +733,54 @@ void ProxyAccessible::DOMNodeID(nsString
 void ProxyAccessible::TakeFocus() {
   RefPtr<IAccessible> acc;
   if (!GetCOMInterface((void**)getter_AddRefs(acc))) {
     return;
   }
   acc->accSelect(SELFLAG_TAKEFOCUS, kChildIdSelf);
 }
 
+ProxyAccessible* ProxyAccessible::ChildAtPoint(
+    int32_t aX, int32_t aY, Accessible::EWhichChildAtPoint aWhichChild) {
+  RefPtr<IAccessible2_2> target = QueryInterface<IAccessible2_2>(this);
+  if (!target) {
+    return nullptr;
+  }
+  DocAccessibleParent* doc = Document();
+  ProxyAccessible* proxy = this;
+  // accHitTest only does direct children, but we might want the deepest child.
+  for (;;) {
+    VARIANT childVar;
+    if (FAILED(target->accHitTest(aX, aY, &childVar)) ||
+        childVar.vt == VT_EMPTY) {
+      return nullptr;
+    }
+    if (childVar.vt == VT_I4 && childVar.lVal == CHILDID_SELF) {
+      break;
+    }
+    MOZ_ASSERT(childVar.vt == VT_DISPATCH && childVar.pdispVal);
+    target = nullptr;
+    childVar.pdispVal->QueryInterface(IID_IAccessible2_2,
+                                      getter_AddRefs(target));
+    childVar.pdispVal->Release();
+    if (!target) {
+      return nullptr;
+    }
+    // We can't always use GetProxyFor because it can't cross document
+    // boundaries.
+    if (proxy->ChildrenCount() == 1) {
+      proxy = proxy->ChildAt(0);
+      if (proxy->IsDoc()) {
+        // We're crossing into a child document.
+        doc = proxy->AsDoc();
+      }
+    } else {
+      proxy = GetProxyFor(doc, target);
+    }
+    if (aWhichChild == Accessible::eDirectChild) {
+      break;
+    }
+  }
+  return proxy;
+}
+
 }  // namespace a11y
 }  // namespace mozilla
--- a/accessible/xpcom/xpcAccessible.cpp
+++ b/accessible/xpcom/xpcAccessible.cpp
@@ -585,22 +585,18 @@ NS_IMETHODIMP
 xpcAccessible::GetDeepestChildAtPoint(int32_t aX, int32_t aY,
                                       nsIAccessible** aAccessible) {
   NS_ENSURE_ARG_POINTER(aAccessible);
   *aAccessible = nullptr;
 
   if (IntlGeneric().IsNull()) return NS_ERROR_FAILURE;
 
   if (ProxyAccessible* proxy = IntlGeneric().AsProxy()) {
-#if defined(XP_WIN)
-    return NS_ERROR_NOT_IMPLEMENTED;
-#else
     NS_IF_ADDREF(*aAccessible = ToXPC(
                      proxy->ChildAtPoint(aX, aY, Accessible::eDeepestChild)));
-#endif
   } else {
     NS_IF_ADDREF(*aAccessible = ToXPC(
                      Intl()->ChildAtPoint(aX, aY, Accessible::eDeepestChild)));
   }
 
   return NS_OK;
 }