mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
Bug 112978. HTML select options need to generate Accessibility API focus events, so screen readers can track user's movements through options. r=jgaunt, sr=attinasi, a=asa
This commit is contained in:
parent
7fed76935a
commit
be88fe4c6a
@ -376,7 +376,7 @@ NS_IMETHODIMP nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent)
|
||||
// Check to see if it's a select element. If so, need the currently focused option
|
||||
nsCOMPtr<nsIDOMHTMLSelectElement> selectElement(do_QueryInterface(targetNode));
|
||||
if (selectElement) // ----- Target Node is an HTML <select> element ------
|
||||
nsHTMLSelectOptionAccessible::GetFocusedOptionNode(mPresShell, targetNode, optionTargetNode);
|
||||
nsHTMLSelectOptionAccessible::GetFocusedOptionNode(targetNode, optionTargetNode);
|
||||
|
||||
// for focus events on Radio Groups we give the focus to the selected button
|
||||
nsCOMPtr<nsIDOMXULSelectControlElement> selectControl(do_QueryInterface(targetNode));
|
||||
@ -393,7 +393,7 @@ NS_IMETHODIMP nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent)
|
||||
|
||||
if (NS_SUCCEEDED(mAccService->GetAccessibleFor(targetNode, getter_AddRefs(accessible)))) {
|
||||
if (eventType.EqualsIgnoreCase("focus") || eventType.EqualsIgnoreCase("DOMMenuItemActive")) {
|
||||
if (selectControl && optionTargetNode &&
|
||||
if (optionTargetNode &&
|
||||
NS_SUCCEEDED(mAccService->GetAccessibleFor(optionTargetNode, getter_AddRefs(accessible)))) {
|
||||
FireAccessibleFocusEvent(accessible, optionTargetNode);
|
||||
}
|
||||
@ -401,15 +401,10 @@ NS_IMETHODIMP nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent)
|
||||
FireAccessibleFocusEvent(accessible, targetNode);
|
||||
}
|
||||
else if (eventType.EqualsIgnoreCase("change")) {
|
||||
if (optionTargetNode) { // Set to current option only for HTML selects
|
||||
mListener->HandleEvent(nsIAccessibleEventListener::EVENT_SELECTION, accessible);
|
||||
if (NS_SUCCEEDED(mAccService->GetAccessibleFor(optionTargetNode, getter_AddRefs(accessible))))
|
||||
FireAccessibleFocusEvent(accessible, optionTargetNode);
|
||||
}
|
||||
else
|
||||
if (!selectControl) // Don't use onchange to fire EVENT_STATE_CHANGE events for selects
|
||||
mListener->HandleEvent(nsIAccessibleEventListener::EVENT_STATE_CHANGE, accessible);
|
||||
}
|
||||
else if (eventType.EqualsIgnoreCase("ListitemStateChange")){
|
||||
else if (eventType.EqualsIgnoreCase("ListitemStateChange")) {
|
||||
mListener->HandleEvent(nsIAccessibleEventListener::EVENT_STATE_CHANGE, accessible);
|
||||
mListener->HandleEvent(nsIAccessibleEventListener::EVENT_FOCUS, accessible);
|
||||
}
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "nsIListControlFrame.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "nsIDocument.h"
|
||||
|
||||
/**
|
||||
* Selects, Listboxes and Comboboxes, are made up of a number of different
|
||||
@ -200,7 +201,7 @@ NS_IMETHODIMP nsHTMLSelectOptionAccessible::GetAccState(PRUint32 *_retval)
|
||||
nsCOMPtr<nsIDOMNode> focusedOptionNode, parentNode;
|
||||
mParent->AccGetDOMNode(getter_AddRefs(parentNode));
|
||||
// find out if we are the focused node
|
||||
GetFocusedOptionNode(mPresShell, parentNode, focusedOptionNode);
|
||||
GetFocusedOptionNode(parentNode, focusedOptionNode);
|
||||
if (focusedOptionNode == mDOMNode)
|
||||
*_retval |= STATE_FOCUSED;
|
||||
|
||||
@ -223,34 +224,43 @@ NS_IMETHODIMP nsHTMLSelectOptionAccessible::GetAccState(PRUint32 *_retval)
|
||||
* need to use the frame to get the focused option because for some reason we
|
||||
* weren't getting the proper notification when the focus changed using the DOM
|
||||
*/
|
||||
nsresult nsHTMLSelectOptionAccessible::GetFocusedOptionNode(nsIWeakReference *aPresShell,
|
||||
nsIDOMNode *aListNode,
|
||||
nsresult nsHTMLSelectOptionAccessible::GetFocusedOptionNode(nsIDOMNode *aListNode,
|
||||
nsCOMPtr<nsIDOMNode>& aFocusedOptionNode)
|
||||
{
|
||||
NS_ASSERTION(aListNode, "Called GetFocusedOptionNode without a valid list node");
|
||||
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(aPresShell));
|
||||
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(aListNode));
|
||||
nsCOMPtr<nsIDocument> document;
|
||||
content->GetDocument(*getter_AddRefs(document));
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
if (document)
|
||||
document->GetShellAt(0,getter_AddRefs(shell));
|
||||
if (!shell)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsIFrame *frame = nsnull;
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(aListNode));
|
||||
shell->GetPrimaryFrameFor(content, &frame);
|
||||
|
||||
nsCOMPtr<nsIListControlFrame> listFrame(do_QueryInterface(frame));
|
||||
if (!listFrame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Get what's focused by asking frame for "selected item".
|
||||
PRInt32 focusedOptionIndex = 0;
|
||||
nsresult rv = listFrame->GetSelectedIndex(&focusedOptionIndex);
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLCollection> options;
|
||||
|
||||
// Get options
|
||||
nsCOMPtr<nsIDOMHTMLSelectElement> selectElement(do_QueryInterface(aListNode));
|
||||
NS_ASSERTION(selectElement, "No select element where it should be");
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLCollection> options;
|
||||
nsresult rv = selectElement->GetOptions(getter_AddRefs(options));
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIDOMHTMLSelectElement> selectElement(do_QueryInterface(aListNode));
|
||||
NS_ASSERTION(selectElement, "No select element where it should be");
|
||||
rv = selectElement->GetOptions(getter_AddRefs(options));
|
||||
nsCOMPtr<nsIListControlFrame> listFrame(do_QueryInterface(frame));
|
||||
if (listFrame) {
|
||||
// Get what's focused in listbox by asking frame for "selected item".
|
||||
// Can't use dom interface for this, because it will always return the first selected item
|
||||
// when there is more than 1 item selected. We need the focused item, not
|
||||
// the first selected item.
|
||||
rv = listFrame->GetSelectedIndex(&focusedOptionIndex);
|
||||
}
|
||||
else // Combo boxes can only have 1 selected option, so they can use the dom interface for this
|
||||
rv = selectElement->GetSelectedIndex(&focusedOptionIndex);
|
||||
}
|
||||
|
||||
// Either use options and focused index, or default to list node itself
|
||||
|
@ -102,7 +102,7 @@ public:
|
||||
NS_IMETHOD GetAccNextSibling(nsIAccessible **_retval);
|
||||
NS_IMETHOD GetAccPreviousSibling(nsIAccessible **_retval);
|
||||
|
||||
static nsresult GetFocusedOptionNode(nsIWeakReference *aPresShell, nsIDOMNode *aListNode, nsCOMPtr<nsIDOMNode>& aFocusedOptionNode);
|
||||
static nsresult GetFocusedOptionNode(nsIDOMNode *aListNode, nsCOMPtr<nsIDOMNode>& aFocusedOptionNode);
|
||||
|
||||
};
|
||||
|
||||
|
@ -63,6 +63,7 @@
|
||||
#include "nsHTMLParts.h"
|
||||
#include "nsIDOMEventReceiver.h"
|
||||
#include "nsIEventStateManager.h"
|
||||
#include "nsIEventListenerManager.h"
|
||||
#include "nsIDOMKeyEvent.h"
|
||||
#include "nsIDOMMouseEvent.h"
|
||||
#include "nsIPrivateDOMEvent.h"
|
||||
@ -1317,6 +1318,24 @@ nsListControlFrame::PerformSelection(PRInt32 aSelectedIndex,
|
||||
printf("mLastEndIndex: %d\n", mLastEndIndex);
|
||||
#endif
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
// Fire a custom DOM event for the change, so that accessibility can
|
||||
// fire a native focus event for accessibility
|
||||
// (Some 3rd party products need to track our focus)
|
||||
nsCOMPtr<nsIDOMEvent> event;
|
||||
nsCOMPtr<nsIEventListenerManager> manager;
|
||||
mContent->GetListenerManager(getter_AddRefs(manager));
|
||||
if (manager &&
|
||||
NS_SUCCEEDED(manager->CreateEvent(mPresContext, nsnull, NS_LITERAL_STRING("Events"), getter_AddRefs(event)))) {
|
||||
event->InitEvent(NS_LITERAL_STRING("DOMMenuItemActive"), PR_TRUE, PR_TRUE);
|
||||
PRBool noDefault;
|
||||
nsCOMPtr<nsIEventStateManager> esm;
|
||||
mPresContext->GetEventStateManager(getter_AddRefs(esm));
|
||||
if (esm)
|
||||
esm->DispatchNewEvent(mContent, event, &noDefault);
|
||||
}
|
||||
#endif
|
||||
|
||||
return wasChanged;
|
||||
}
|
||||
|
||||
|
@ -63,6 +63,7 @@
|
||||
#include "nsHTMLParts.h"
|
||||
#include "nsIDOMEventReceiver.h"
|
||||
#include "nsIEventStateManager.h"
|
||||
#include "nsIEventListenerManager.h"
|
||||
#include "nsIDOMKeyEvent.h"
|
||||
#include "nsIDOMMouseEvent.h"
|
||||
#include "nsIPrivateDOMEvent.h"
|
||||
@ -1317,6 +1318,24 @@ nsListControlFrame::PerformSelection(PRInt32 aSelectedIndex,
|
||||
printf("mLastEndIndex: %d\n", mLastEndIndex);
|
||||
#endif
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
// Fire a custom DOM event for the change, so that accessibility can
|
||||
// fire a native focus event for accessibility
|
||||
// (Some 3rd party products need to track our focus)
|
||||
nsCOMPtr<nsIDOMEvent> event;
|
||||
nsCOMPtr<nsIEventListenerManager> manager;
|
||||
mContent->GetListenerManager(getter_AddRefs(manager));
|
||||
if (manager &&
|
||||
NS_SUCCEEDED(manager->CreateEvent(mPresContext, nsnull, NS_LITERAL_STRING("Events"), getter_AddRefs(event)))) {
|
||||
event->InitEvent(NS_LITERAL_STRING("DOMMenuItemActive"), PR_TRUE, PR_TRUE);
|
||||
PRBool noDefault;
|
||||
nsCOMPtr<nsIEventStateManager> esm;
|
||||
mPresContext->GetEventStateManager(getter_AddRefs(esm));
|
||||
if (esm)
|
||||
esm->DispatchNewEvent(mContent, event, &noDefault);
|
||||
}
|
||||
#endif
|
||||
|
||||
return wasChanged;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user