Bug 961696 - Accessible object:state-changed:focused events for imagemap links are broken. r=tbsaunde

This commit is contained in:
Jonathan Wei 2014-02-10 15:52:34 -05:00
parent 4351b345d8
commit d158dd58a6
5 changed files with 87 additions and 6 deletions

View File

@ -7,9 +7,11 @@
#include "Accessible-inl.h"
#include "AccIterator.h"
#include "DocAccessible-inl.h"
#include "HTMLImageMapAccessible.h"
#include "nsAccessibilityService.h"
#include "nsAccUtils.h"
#include "nsEventShell.h"
#include "nsImageFrame.h"
#include "Role.h"
#include "nsEventStateManager.h"
@ -37,7 +39,7 @@ FocusManager::FocusedAccessible() const
if (focusedNode) {
DocAccessible* doc =
GetAccService()->GetDocAccessible(focusedNode->OwnerDoc());
return doc ? doc->GetAccessibleOrContainer(focusedNode) : nullptr;
return doc ? GetFocusableAccessibleFor(focusedNode, doc) : nullptr;
}
return nullptr;
@ -61,7 +63,7 @@ FocusManager::IsFocused(const Accessible* aAccessible) const
DocAccessible* doc =
GetAccService()->GetDocAccessible(focusedNode->OwnerDoc());
return aAccessible ==
(doc ? doc->GetAccessibleOrContainer(focusedNode) : nullptr);
(doc ? GetFocusableAccessibleFor(focusedNode, doc) : nullptr);
}
}
return false;
@ -241,12 +243,15 @@ FocusManager::ProcessDOMFocus(nsINode* aTarget)
DocAccessible* document =
GetAccService()->GetDocAccessible(aTarget->OwnerDoc());
Accessible* target = document->GetAccessibleOrContainer(aTarget);
Accessible* target = GetFocusableAccessibleFor(aTarget, document);
if (target && document) {
// Check if still focused. Otherwise we can end up with storing the active
// item for control that isn't focused anymore.
Accessible* DOMFocus =
document->GetAccessibleOrContainer(FocusedDOMNode());
nsINode* focusedNode = FocusedDOMNode();
if (!focusedNode)
return;
Accessible* DOMFocus = GetFocusableAccessibleFor(focusedNode, document);
if (target != DOMFocus)
return;
@ -274,8 +279,11 @@ FocusManager::ProcessFocusEvent(AccEvent* aEvent)
// Check if still focused. Otherwise we can end up with storing the active
// item for control that isn't focused anymore.
DocAccessible* document = aEvent->GetDocAccessible();
Accessible* DOMFocus = document->GetAccessibleOrContainer(FocusedDOMNode());
nsINode* focusedNode = FocusedDOMNode();
if (!focusedNode)
return;
Accessible* DOMFocus = GetFocusableAccessibleFor(focusedNode, document);
if (target != DOMFocus)
return;
@ -394,3 +402,28 @@ FocusManager::FocusedDOMDocument() const
nsINode* focusedNode = FocusedDOMNode();
return focusedNode ? focusedNode->OwnerDoc() : nullptr;
}
Accessible*
FocusManager::GetFocusableAccessibleFor(nsINode* aNode,
DocAccessible* aDoc) const
{
if (!aNode->IsContent() || !aNode->AsContent()->IsHTML(nsGkAtoms::area))
return aDoc->GetAccessibleOrContainer(aNode);
// XXX Bug 135040, incorrect when multiple images use the same map.
nsIFrame* frame = aNode->AsContent()->GetPrimaryFrame();
nsImageFrame* imageFrame = do_QueryFrame(frame);
if (imageFrame) {
Accessible* parent = aDoc->GetAccessible(imageFrame->GetContent());
if (parent) {
Accessible* area =
parent->AsImageMap()->GetChildAccessibleFor(aNode);
if (area)
return area;
return nullptr;
}
}
return aDoc->GetAccessibleOrContainer(aNode);
}

View File

@ -123,6 +123,12 @@ private:
*/
nsIDocument* FocusedDOMDocument() const;
/**
* Return accessible for a focusable node.
*/
Accessible* GetFocusableAccessibleFor(nsINode* aNode,
DocAccessible* aDoc) const;
private:
nsRefPtr<Accessible> mActiveItem;
nsRefPtr<Accessible> mActiveARIAMenubar;

View File

@ -133,6 +133,19 @@ HTMLImageMapAccessible::UpdateChildAreas(bool aDoFireEvents)
mDoc->FireDelayedEvent(reorderEvent);
}
Accessible*
HTMLImageMapAccessible::GetChildAccessibleFor(const nsINode* aNode) const
{
uint32_t length = mChildren.Length();
for (uint32_t i = 0; i < length; i++) {
Accessible* area = mChildren[i];
if (area->GetContent() == aNode)
return area;
}
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
// HTMLImageMapAccessible: Accessible protected

View File

@ -38,6 +38,11 @@ public:
*/
void UpdateChildAreas(bool aDoFireEvents = true);
/**
* Return accessible of child node.
*/
Accessible* GetChildAccessibleFor(const nsINode* aNode) const;
protected:
// Accessible

View File

@ -44,6 +44,16 @@
}
}
function imageMapChecker(aID)
{
var node = getNode(aID);
this.type = EVENT_FOCUS;
this.match = function imageMapChecker_match(aEvent)
{
return aEvent.DOMNode == node;
}
}
function topMenuChecker()
{
this.type = EVENT_FOCUS;
@ -115,6 +125,9 @@
gQueue.push(new synthShiftTab("link", new focusChecker("link")));
} // ! SEAMONKEY
gQueue.push(new synthFocus("a", new imageMapChecker("a")));
gQueue.push(new synthFocus("b", new imageMapChecker("b")));
gQueue.invoke(); // Will call SimpleTest.finish();
}
@ -139,6 +152,11 @@
title="Rework accessible focus handling">
Mozilla Bug 673958
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=961696"
title="Accessible object:state-changed:focused events for imagemap links are broken">
Mozilla Bug 961696
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
@ -150,6 +168,12 @@
<a id="link" href="">link</a>
<iframe id="editabledoc" src="about:blank"></iframe>
<map name="atoz_map">
<area id="a" coords="0,0,13,14" shape="rect">
<area id="b" coords="17,0,30,14" shape="rect">
</map>
<img width="447" height="15" usemap="#atoz_map" src="../letters.gif">
<div id="eventdump"></div>
</body>
</html>