diff --git a/mozilla/content/events/src/nsEventStateManager.cpp b/mozilla/content/events/src/nsEventStateManager.cpp index 2496521ba52..391756fd2ee 100644 --- a/mozilla/content/events/src/nsEventStateManager.cpp +++ b/mozilla/content/events/src/nsEventStateManager.cpp @@ -4145,9 +4145,13 @@ nsEventStateManager::SendFocusBlur(nsIPresContext* aPresContext, nsIContent *aCo { nsCOMPtr presShell; aPresContext->GetShell(getter_AddRefs(presShell)); - + + nsCOMPtr previousFocus = mCurrentFocus; + if (nsnull != gLastFocusedPresContext) { - + + nsCOMPtr focusAfterBlur; + if (gLastFocusedContent && gLastFocusedContent != mFirstBlurEvent) { //Store the first blur event we fire and don't refire blur @@ -4215,6 +4219,7 @@ nsEventStateManager::SendFocusBlur(nsIPresContext* aPresContext, nsIContent *aCo temp->HandleDOMEvent(oldPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); pusher.Pop(); + focusAfterBlur = mCurrentFocus; esm->SetFocusedContent(nsnull); } } @@ -4222,6 +4227,12 @@ nsEventStateManager::SendFocusBlur(nsIPresContext* aPresContext, nsIContent *aCo if (clearFirstBlurEvent) { mFirstBlurEvent = nsnull; } + + if (previousFocus != focusAfterBlur) { + // The content node's blur handler focused something else. + // In this case, abort firing any more blur or focus events. + return NS_OK; + } } // Go ahead and fire a blur on the window. @@ -4269,8 +4280,20 @@ nsEventStateManager::SendFocusBlur(nsIPresContext* aPresContext, nsIContent *aCo temp->HandleDOMEvent(gLastFocusedPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); pusher.Pop(); + if (mCurrentFocus != previousFocus) { + // The document's blur handler focused something else. + // Abort firing any additional blur or focus events. + return NS_OK; + } + pusher.Push(globalObject); globalObject->HandleDOMEvent(gLastFocusedPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); + + if (mCurrentFocus != previousFocus) { + // The window's blur handler focused something else. + // Abort firing any additional blur or focus events. + return NS_OK; + } } } diff --git a/mozilla/editor/libeditor/text/nsEditorEventListeners.cpp b/mozilla/editor/libeditor/text/nsEditorEventListeners.cpp index 612ae674b9f..bda9dc912c6 100644 --- a/mozilla/editor/libeditor/text/nsEditorEventListeners.cpp +++ b/mozilla/editor/libeditor/text/nsEditorEventListeners.cpp @@ -87,6 +87,8 @@ #include "nsLayoutCID.h" #include "nsIDOMNSRange.h" #include "nsEditorUtils.h" +#include "nsIDOMEventTarget.h" +#include "nsIEventStateManager.h" // Drag & Drop, Clipboard Support static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID); @@ -989,9 +991,61 @@ nsTextEditorFocusListener::HandleEvent(nsIDOMEvent* aEvent) return NS_OK; } +static PRBool +IsTargetFocused(nsIDOMEventTarget* aTarget) +{ + // The event target could be either a content node or a document. + nsCOMPtr doc; + nsCOMPtr content = do_QueryInterface(aTarget); + if (content) + content->GetDocument(getter_AddRefs(doc)); + else + doc = do_QueryInterface(aTarget); + + if (!doc) + return PR_FALSE; + + nsCOMPtr shell; + doc->GetShellAt(0, getter_AddRefs(shell)); + if (!shell) + return PR_FALSE; + + nsCOMPtr presContext; + shell->GetPresContext(getter_AddRefs(presContext)); + if (!presContext) + return PR_FALSE; + + nsCOMPtr esm; + presContext->GetEventStateManager(getter_AddRefs(esm)); + if (!esm) + return PR_FALSE; + + nsCOMPtr focusedContent; + esm->GetFocusedContent(getter_AddRefs(focusedContent)); + + // focusedContent will be null in the case where the document has focus, + // and so will content. + + return (focusedContent == content); +} + nsresult nsTextEditorFocusListener::Focus(nsIDOMEvent* aEvent) { + // It's possible for us to receive a focus when we're really not focused. + // This happens, for example, when an onfocus handler that's hooked up + // before this listener focuses something else. In that case, all of the + // onblur handlers will be fired synchronously, then the remaining focus + // handlers will be fired from the original event. So, check to see that + // we're really focused. (Note that the analogous situation does not + // happen for blurs, due to the ordering in + // nsEventStateManager::SendFocuBlur(). + + nsCOMPtr target; + aEvent->GetTarget(getter_AddRefs(target)); + if (!IsTargetFocused(target)) + return NS_OK; + // turn on selection and caret if (mEditor) { diff --git a/mozilla/view/src/nsViewManager.cpp b/mozilla/view/src/nsViewManager.cpp index 55d5ed3a71a..0e100f8e3e5 100644 --- a/mozilla/view/src/nsViewManager.cpp +++ b/mozilla/view/src/nsViewManager.cpp @@ -2003,6 +2003,9 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus *aS //Find the view whose coordinates system we're in. baseView = nsView::GetViewFor(aEvent->widget); + if (aEvent->message == NS_DEACTIVATE) + mMouseGrabber = mKeyGrabber = nsnull; + //Find the view to which we're initially going to send the event //for hittesting. if (nsnull != mMouseGrabber && (NS_IS_MOUSE_EVENT(aEvent) || (NS_IS_DRAG_EVENT(aEvent)))) {