Bug 352205. Swallow duplicate caret move events. r=ginn.chen

This commit is contained in:
aaronleventhal@moonset.net 2007-04-19 06:53:34 -07:00
parent ae81435dcb
commit 240f1e242c
2 changed files with 26 additions and 5 deletions

View File

@ -56,14 +56,16 @@
NS_IMPL_ISUPPORTS_INHERITED2(nsCaretAccessible, nsLeafAccessible, nsIAccessibleCaret, nsISelectionListener) NS_IMPL_ISUPPORTS_INHERITED2(nsCaretAccessible, nsLeafAccessible, nsIAccessibleCaret, nsISelectionListener)
nsCaretAccessible::nsCaretAccessible(nsIDOMNode* aDocumentNode, nsIWeakReference* aShell, nsRootAccessible *aRootAccessible): nsCaretAccessible::nsCaretAccessible(nsIDOMNode* aDocumentNode, nsIWeakReference* aShell, nsRootAccessible *aRootAccessible):
nsLeafAccessible(aDocumentNode, aShell), mVisible(PR_TRUE), mCurrentDOMNode(nsnull), mRootAccessible(aRootAccessible) nsLeafAccessible(aDocumentNode, aShell), mVisible(PR_TRUE), mLastCaretOffset(-1), mLastNodeWithCaret(nsnull),
mSelectionControllerNode(nsnull), mRootAccessible(aRootAccessible)
{ {
} }
NS_IMETHODIMP nsCaretAccessible::Shutdown() NS_IMETHODIMP nsCaretAccessible::Shutdown()
{ {
mDomSelectionWeak = nsnull; mDomSelectionWeak = nsnull;
mCurrentDOMNode = nsnull; mLastNodeWithCaret = nsnull;
mSelectionControllerNode = nsnull;
RemoveSelectionListener(); RemoveSelectionListener();
return NS_OK; return NS_OK;
} }
@ -81,7 +83,8 @@ NS_IMETHODIMP nsCaretAccessible::RemoveSelectionListener()
NS_IMETHODIMP nsCaretAccessible::AttachNewSelectionListener(nsIDOMNode *aCurrentNode) NS_IMETHODIMP nsCaretAccessible::AttachNewSelectionListener(nsIDOMNode *aCurrentNode)
{ {
mCurrentDOMNode = aCurrentNode; mSelectionControllerNode = aCurrentNode;
mLastNodeWithCaret = nsnull;
// When focus moves such that the caret is part of a new frame selection // When focus moves such that the caret is part of a new frame selection
// this removes the old selection listener and attaches a new one for the current focus // this removes the old selection listener and attaches a new one for the current focus
@ -123,7 +126,7 @@ NS_IMETHODIMP nsCaretAccessible::AttachNewSelectionListener(nsIDOMNode *aCurrent
NS_IMETHODIMP nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc, nsISelection *aSel, PRInt16 aReason) NS_IMETHODIMP nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc, nsISelection *aSel, PRInt16 aReason)
{ {
nsCOMPtr<nsIPresShell> presShell = GetPresShellFor(mCurrentDOMNode); nsCOMPtr<nsIPresShell> presShell = GetPresShellFor(mSelectionControllerNode);
nsCOMPtr<nsISelection> domSel(do_QueryReferent(mDomSelectionWeak)); nsCOMPtr<nsISelection> domSel(do_QueryReferent(mDomSelectionWeak));
if (!presShell || domSel != aSel) if (!presShell || domSel != aSel)
return NS_OK; // Only listening to selection changes in currently focused frame return NS_OK; // Only listening to selection changes in currently focused frame
@ -181,8 +184,11 @@ NS_IMETHODIMP nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc, ns
nsCOMPtr<nsIDOMNode> focusNode; nsCOMPtr<nsIDOMNode> focusNode;
domSel->GetFocusNode(getter_AddRefs(focusNode)); domSel->GetFocusNode(getter_AddRefs(focusNode));
if (!focusNode) { if (!focusNode) {
mLastNodeWithCaret = nsnull;
return NS_OK; // No selection return NS_OK; // No selection
} }
nsCOMPtr<nsIDOMNode> nodeWithCaret = focusNode;
nsCOMPtr<nsIAccessibleText> textAcc; nsCOMPtr<nsIAccessibleText> textAcc;
while (focusNode) { while (focusNode) {
// Make sure to get the correct starting node for selection events inside XBL content trees // Make sure to get the correct starting node for selection events inside XBL content trees
@ -206,6 +212,19 @@ NS_IMETHODIMP nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc, ns
NS_ASSERTION(textAcc, "No nsIAccessibleText for caret move event!"); // No nsIAccessibleText for caret move event! NS_ASSERTION(textAcc, "No nsIAccessibleText for caret move event!"); // No nsIAccessibleText for caret move event!
NS_ENSURE_TRUE(textAcc, NS_ERROR_FAILURE); NS_ENSURE_TRUE(textAcc, NS_ERROR_FAILURE);
PRInt32 caretOffset;
textAcc->GetCaretOffset(&caretOffset);
if (nodeWithCaret == mLastNodeWithCaret && caretOffset == mLastCaretOffset) {
PRInt32 selectionCount;
textAcc->GetSelectionCount(&selectionCount); // Don't swallow similar events when selecting text
if (!selectionCount) {
return NS_OK; // Swallow duplicate caret event
}
}
mLastCaretOffset = caretOffset;
mLastNodeWithCaret = nodeWithCaret;
return mRootAccessible->FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, return mRootAccessible->FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED,
focusNode, nsnull, PR_FALSE); focusNode, nsnull, PR_FALSE);
} }

View File

@ -91,7 +91,9 @@ public:
private: private:
nsRect mCaretRect; nsRect mCaretRect;
PRBool mVisible; PRBool mVisible;
nsCOMPtr<nsIDOMNode> mCurrentDOMNode; PRInt32 mLastCaretOffset;
nsCOMPtr<nsIDOMNode> mLastNodeWithCaret;
nsCOMPtr<nsIDOMNode> mSelectionControllerNode;
// mListener is not a com pointer. It's a copy of the listener in the nsRootAccessible owner. // mListener is not a com pointer. It's a copy of the listener in the nsRootAccessible owner.
//See nsRootAccessible.h for details of the lifetime if this listener //See nsRootAccessible.h for details of the lifetime if this listener
nsRootAccessible *mRootAccessible; nsRootAccessible *mRootAccessible;