Bug 300783. Fix unsafe firing of events and perf regression for multi select in HTML listboxes. r+sr=bz, a=mkaply

git-svn-id: svn://10.0.0.236/trunk@176567 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
aaronleventhal%moonset.net 2005-07-25 21:40:31 +00:00
parent c24bfbe595
commit 1fc846a154
4 changed files with 52 additions and 43 deletions

View File

@ -56,7 +56,9 @@
#include "nsIDOMNSHTMLDocument.h"
#include "nsIDOMWindow.h"
#include "nsIEditingSession.h"
#include "nsIEventStateManager.h"
#include "nsIFrame.h"
#include "nsHTMLSelectAccessible.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsINameSpaceManager.h"
#include "nsIObserverService.h"
@ -713,7 +715,6 @@ NS_IMETHODIMP nsDocAccessible::Observe(nsISupports *aSubject, const char *aTopic
NS_IMPL_NSIDOCUMENTOBSERVER_CORE_STUB(nsDocAccessible)
NS_IMPL_NSIDOCUMENTOBSERVER_LOAD_STUB(nsDocAccessible)
NS_IMPL_NSIDOCUMENTOBSERVER_REFLOW_STUB(nsDocAccessible)
NS_IMPL_NSIDOCUMENTOBSERVER_STATE_STUB(nsDocAccessible)
NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(nsDocAccessible)
void
@ -837,12 +838,25 @@ void nsDocAccessible::ContentAppended(nsIDocument *aDocument,
// can't do unless the node is visible. The right thing happens there so
// no need for an extra visibility check here.
PRUint32 childCount = aContainer->GetChildCount();
for (PRInt32 index = aNewIndexInContainer; index < childCount; index ++) {
for (PRUint32 index = aNewIndexInContainer; index < childCount; index ++) {
InvalidateCacheSubtree(aContainer->GetChildAt(index),
nsIAccessibleEvent::EVENT_SHOW);
}
}
void nsDocAccessible::ContentStatesChanged(nsIDocument* aDocument,
nsIContent* aContent1,
nsIContent* aContent2,
PRInt32 aStateMask)
{
if (0 == (aStateMask & NS_EVENT_STATE_CHECKED)) {
return;
}
nsHTMLSelectOptionAccessible::SelectionChangedIfOption(aContent1);
nsHTMLSelectOptionAccessible::SelectionChangedIfOption(aContent2);
}
void nsDocAccessible::CharacterDataChanged(nsIDocument *aDocument,
nsIContent* aContent,
PRBool aAppend)

View File

@ -39,6 +39,7 @@
#include "nsCOMPtr.h"
#include "nsHTMLSelectAccessible.h"
#include "nsIAccessibilityService.h"
#include "nsIAccessibleEvent.h"
#include "nsIFrame.h"
#include "nsIComboboxControlFrame.h"
#include "nsIDocument.h"
@ -716,6 +717,40 @@ nsresult nsHTMLSelectOptionAccessible::GetFocusedOptionNode(nsIDOMNode *aListNod
return rv;
}
void nsHTMLSelectOptionAccessible::SelectionChangedIfOption(nsIContent *aPossibleOption)
{
if (!aPossibleOption || aPossibleOption->Tag() != nsAccessibilityAtoms::option ||
!aPossibleOption->IsContentOfType(nsIContent::eHTML)) {
return;
}
nsCOMPtr<nsIDOMNode> optionNode(do_QueryInterface(aPossibleOption));
NS_ASSERTION(optionNode, "No option node for nsIContent with option tag!");
nsCOMPtr<nsIAccessible> multiSelect = GetMultiSelectFor(optionNode);
nsCOMPtr<nsPIAccessible> privateMultiSelect = do_QueryInterface(multiSelect);
if (!privateMultiSelect) {
return;
}
nsCOMPtr<nsIAccessibilityService> accService =
do_GetService("@mozilla.org/accessibilityService;1");
nsCOMPtr<nsIAccessible> optionAccessible;
accService->GetAccessibleFor(optionNode, getter_AddRefs(optionAccessible));
if (!optionAccessible) {
return;
}
privateMultiSelect->FireToolkitEvent(nsIAccessibleEvent::EVENT_SELECTION_WITHIN,
multiSelect, nsnull);
PRUint32 state;
optionAccessible->GetFinalState(&state);
PRUint32 eventType = (state & STATE_SELECTED) ?
nsIAccessibleEvent::EVENT_SELECTION_ADD :
nsIAccessibleEvent::EVENT_SELECTION_REMOVE;
privateMultiSelect->FireToolkitEvent(eventType, optionAccessible, nsnull);
}
/** ----- nsHTMLSelectOptGroupAccessible ----- */
/** Default Constructor */

View File

@ -161,6 +161,7 @@ public:
NS_IMETHOD GetName(nsAString& aName);
nsIFrame* GetBoundsFrame();
static nsresult GetFocusedOptionNode(nsIDOMNode *aListNode, nsIDOMNode **aFocusedOptionNode);
static void SelectionChangedIfOption(nsIContent *aPossibleOption);
};
/*

View File

@ -68,9 +68,6 @@
#include "nsLayoutAtoms.h"
#include "nsIEventStateManager.h"
#include "nsIDOMDocument.h"
#include "nsIDOMDocumentEvent.h"
#include "nsIDOMEvent.h"
#include "nsIPrivateDOMEvent.h"
/**
* Implementation of &lt;option&gt;
@ -131,11 +128,6 @@ protected:
*/
void GetSelect(nsIDOMHTMLSelectElement **aSelectElement) const;
/**
* Fire a DOM event for this option node
*/
void DispatchDOMEvent(const nsAString& aName);
PRPackedBool mIsInitialized;
PRPackedBool mIsSelected;
};
@ -213,31 +205,6 @@ nsHTMLOptionElement::GetForm(nsIDOMHTMLFormElement** aForm)
return NS_OK;
}
void
nsHTMLOptionElement::DispatchDOMEvent(const nsAString& aName)
{
nsCOMPtr<nsIDOMDocumentEvent> domDoc = do_QueryInterface(GetOwnerDoc());
if (domDoc) {
nsCOMPtr<nsIDOMEvent> selectEvent;
domDoc->CreateEvent(NS_LITERAL_STRING("Events"),
getter_AddRefs(selectEvent));
nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(selectEvent));
if (privateEvent) {
nsresult rv = selectEvent->InitEvent(aName, PR_TRUE, PR_TRUE);
if (NS_SUCCEEDED(rv)) {
privateEvent->SetTrusted(PR_TRUE);
nsCOMPtr<nsIDOMEventTarget> target =
do_QueryInterface(NS_STATIC_CAST(nsIDOMNode*, this));
PRBool defaultActionEnabled;
target->DispatchEvent(selectEvent, &defaultActionEnabled);
}
}
}
}
NS_IMETHODIMP
nsHTMLOptionElement::SetSelectedInternal(PRBool aValue, PRBool aNotify)
{
@ -252,14 +219,6 @@ nsHTMLOptionElement::SetSelectedInternal(PRBool aValue, PRBool aNotify)
}
}
// Dispatch an event to notify the subcontent that the selected item has changed
if (aValue) {
DispatchDOMEvent(NS_LITERAL_STRING("DOMItemSelected"));
}
else {
DispatchDOMEvent(NS_LITERAL_STRING("DOMItemUnselected"));
}
return NS_OK;
}