From 9f0f0b2d593756e00640ec9753e047b8e60a860b Mon Sep 17 00:00:00 2001 From: Alexander Surkov Date: Mon, 22 Jul 2013 11:58:19 -0400 Subject: [PATCH] Bug 891338 - Popup accessibility broken, r=tbsaunde, roc, f=marcoz, jamie --- accessible/src/generic/DocAccessible.cpp | 26 +++++++++++++- accessible/src/generic/DocAccessible.h | 9 +++-- .../src/windows/msaa/AccessibleWrap.cpp | 28 +++++++-------- widget/windows/nsWindow.cpp | 34 +++++++++++-------- 4 files changed, 64 insertions(+), 33 deletions(-) diff --git a/accessible/src/generic/DocAccessible.cpp b/accessible/src/generic/DocAccessible.cpp index 6adc79927b04..afbb27d21cc0 100644 --- a/accessible/src/generic/DocAccessible.cpp +++ b/accessible/src/generic/DocAccessible.cpp @@ -1265,7 +1265,7 @@ DocAccessible::GetAccessibleByUniqueIDInSubtree(void* aUniqueID) } Accessible* -DocAccessible::GetAccessibleOrContainer(nsINode* aNode) +DocAccessible::GetAccessibleOrContainer(nsINode* aNode) const { if (!aNode || !aNode->IsInDoc()) return nullptr; @@ -1278,6 +1278,30 @@ DocAccessible::GetAccessibleOrContainer(nsINode* aNode) return accessible; } +Accessible* +DocAccessible::GetAccessibleOrDescendant(nsINode* aNode) const +{ + Accessible* acc = GetAccessible(aNode); + if (acc) + return acc; + + acc = GetContainerAccessible(aNode); + if (acc) { + uint32_t childCnt = acc->ChildCount(); + for (uint32_t idx = 0; idx < childCnt; idx++) { + Accessible* child = acc->GetChildAt(idx); + for (nsIContent* elm = child->GetContent(); + elm && elm != acc->GetContent(); + elm = elm->GetFlattenedTreeParent()) { + if (elm == aNode) + return child; + } + } + } + + return nullptr; +} + bool DocAccessible::BindToDocument(Accessible* aAccessible, nsRoleMapEntry* aRoleMapEntry) diff --git a/accessible/src/generic/DocAccessible.h b/accessible/src/generic/DocAccessible.h index d87bbe36c5b4..a4443b21ea1b 100644 --- a/accessible/src/generic/DocAccessible.h +++ b/accessible/src/generic/DocAccessible.h @@ -242,16 +242,21 @@ public: * Return an accessible for the given DOM node or container accessible if * the node is not accessible. */ - Accessible* GetAccessibleOrContainer(nsINode* aNode); + Accessible* GetAccessibleOrContainer(nsINode* aNode) const; /** * Return a container accessible for the given DOM node. */ - Accessible* GetContainerAccessible(nsINode* aNode) + Accessible* GetContainerAccessible(nsINode* aNode) const { return aNode ? GetAccessibleOrContainer(aNode->GetParentNode()) : nullptr; } + /** + * Return an accessible for the given node or its first accessible descendant. + */ + Accessible* GetAccessibleOrDescendant(nsINode* aNode) const; + /** * Return true if the given ID is referred by relation attribute. * diff --git a/accessible/src/windows/msaa/AccessibleWrap.cpp b/accessible/src/windows/msaa/AccessibleWrap.cpp index ac8a2d525309..27bc628b8d8f 100644 --- a/accessible/src/windows/msaa/AccessibleWrap.cpp +++ b/accessible/src/windows/msaa/AccessibleWrap.cpp @@ -1826,24 +1826,22 @@ AccessibleWrap::GetXPAccessibleFor(const VARIANT& aVarChild) // Convert child ID to unique ID. void* uniqueID = reinterpret_cast(-aVarChild.lVal); - // Document. + DocAccessible* document = Document(); + Accessible* child = + document->GetAccessibleByUniqueIDInSubtree(uniqueID); + + // If it is a document then just return an accessible. if (IsDoc()) - return AsDoc()->GetAccessibleByUniqueIDInSubtree(uniqueID); + return child; - // ARIA document and menu popups. - if (ARIARole() == roles::DOCUMENT || IsMenuPopup()) { - DocAccessible* document = Document(); - Accessible* child = - document->GetAccessibleByUniqueIDInSubtree(uniqueID); + // Otherwise check whether the accessible is a child (this path works for + // ARIA documents and popups). + Accessible* parent = child; + while (parent && parent != document) { + if (parent == this) + return child; - // Check whether the accessible for the given ID is a child. - Accessible* parent = child ? child->Parent() : nullptr; - while (parent && parent != document) { - if (parent == this) - return child; - - parent = parent->Parent(); - } + parent = parent->Parent(); } return nullptr; diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index e835d24e19c6..c552902e938b 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -141,6 +141,11 @@ #include #if defined(ACCESSIBILITY) + +#ifdef DEBUG +#include "mozilla/a11y/Logging.h" +#endif + #include "oleidl.h" #include #include "nsAccessibilityService.h" @@ -6639,20 +6644,19 @@ nsWindow::GetIMEUpdatePreference() } #ifdef ACCESSIBILITY - -#ifdef DEBUG_WMGETOBJECT +#ifdef DEBUG #define NS_LOG_WMGETOBJECT(aWnd, aHwnd, aAcc) \ - PR_LOG(gWindowsLog, PR_LOG_ALWAYS, \ - ("Get the window:\n {\n HWND: %d, parent HWND: %d, wndobj: %p,\n",\ - aHwnd, ::GetParent(aHwnd), aWnd)); \ - PR_LOG(gWindowsLog, PR_LOG_ALWAYS, (" acc: %p", aAcc)); \ - if (aAcc) { \ - nsAutoString name; \ - aAcc->Name(name); \ - PR_LOG(gWindowsLog, PR_LOG_ALWAYS, \ - (", accname: %s", NS_ConvertUTF16toUTF8(name).get())); \ - } \ - PR_LOG(gWindowsLog, PR_LOG_ALWAYS, ("\n }\n")); + if (a11y::logging::IsEnabled(a11y::logging::ePlatforms)) { \ + printf("Get the window:\n {\n HWND: %d, parent HWND: %d, wndobj: %p,\n",\ + aHwnd, ::GetParent(aHwnd), aWnd); \ + printf(" acc: %p", aAcc); \ + if (aAcc) { \ + nsAutoString name; \ + aAcc->Name(name); \ + printf(", accname: %s", NS_ConvertUTF16toUTF8(name).get()); \ + } \ + printf("\n }\n"); \ + } #else #define NS_LOG_WMGETOBJECT(aWnd, aHwnd, aAcc) @@ -6681,8 +6685,8 @@ nsWindow::GetAccessible() GetAccService()->GetDocAccessible(frame->PresContext()->PresShell()); if (docAcc) { NS_LOG_WMGETOBJECT(this, mWnd, - docAcc->GetAccessible(frame->GetContent())); - return docAcc->GetAccessible(frame->GetContent()); + docAcc->GetAccessibleOrDescendant(frame->GetContent())); + return docAcc->GetAccessibleOrDescendant(frame->GetContent()); } } }