Bug 1358926 - Check and dequeue delayed events in the queue before firing events. r=smaug

When firing an event, check if there is any event in the delayed events queue,
if yes, fire them first to ensure the events are fired in the right order.

MozReview-Commit-ID: DY842oiHcVJ
This commit is contained in:
Jessica Jong 2017-04-30 10:00:11 -07:00
parent c398656635
commit 99028eff3f
2 changed files with 55 additions and 13 deletions

View File

@ -1058,8 +1058,9 @@ nsFocusManager::FireDelayedEvents(nsIDocument* aDocument)
nsCOMPtr<nsIPresShell> presShell = mDelayedBlurFocusEvents[i].mPresShell;
nsCOMPtr<EventTarget> relatedTarget = mDelayedBlurFocusEvents[i].mRelatedTarget;
mDelayedBlurFocusEvents.RemoveElementAt(i);
SendFocusOrBlurEvent(message, presShell, aDocument, target, 0,
false, false, relatedTarget);
FireFocusOrBlurEvent(message, presShell, target, false, false,
relatedTarget);
--i;
}
}
@ -2081,7 +2082,7 @@ GetDocumentHelper(EventTarget* aTarget)
return node->OwnerDoc();
}
void nsFocusManager::SendFocusInOrOutEvent(EventMessage aEventMessage,
void nsFocusManager::FireFocusInOrOutEvent(EventMessage aEventMessage,
nsIPresShell* aPresShell,
nsISupports* aTarget,
nsPIDOMWindowOuter* aCurrentFocusedWindow,
@ -2089,7 +2090,7 @@ void nsFocusManager::SendFocusInOrOutEvent(EventMessage aEventMessage,
EventTarget* aRelatedTarget)
{
NS_ASSERTION(aEventMessage == eFocusIn || aEventMessage == eFocusOut,
"Wrong event type for SendFocusInOrOutEvent");
"Wrong event type for FireFocusInOrOutEvent");
nsContentUtils::AddScriptRunner(
new FocusInOutEvent(
@ -2117,11 +2118,6 @@ nsFocusManager::SendFocusOrBlurEvent(EventMessage aEventMessage,
nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
nsCOMPtr<nsIDocument> eventTargetDoc = GetDocumentHelper(eventTarget);
nsCOMPtr<nsIDocument> relatedTargetDoc = GetDocumentHelper(aRelatedTarget);
nsCOMPtr<nsPIDOMWindowOuter> currentWindow = mFocusedWindow;
nsCOMPtr<nsPIDOMWindowInner> targetWindow = do_QueryInterface(aTarget);
nsCOMPtr<nsIDocument> targetDocument = do_QueryInterface(aTarget);
nsCOMPtr<nsIContent> currentFocusedContent = currentWindow ?
currentWindow->GetFocusedNode() : nullptr;
// set aRelatedTarget to null if it's not in the same document as eventTarget
if (eventTargetDoc != relatedTargetDoc) {
@ -2149,6 +2145,36 @@ nsFocusManager::SendFocusOrBlurEvent(EventMessage aEventMessage,
return;
}
// If mDelayedBlurFocusEvents queue is not empty, check if there are events
// that belongs to this doc, if yes, fire them first.
if (aDocument && !aDocument->EventHandlingSuppressed() &&
mDelayedBlurFocusEvents.Length()) {
FireDelayedEvents(aDocument);
}
FireFocusOrBlurEvent(aEventMessage, aPresShell, aTarget, aWindowRaised,
aIsRefocus, aRelatedTarget);
}
void
nsFocusManager::FireFocusOrBlurEvent(EventMessage aEventMessage,
nsIPresShell* aPresShell,
nsISupports* aTarget,
bool aWindowRaised,
bool aIsRefocus,
EventTarget* aRelatedTarget)
{
nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
nsCOMPtr<nsIDocument> eventTargetDoc = GetDocumentHelper(eventTarget);
nsCOMPtr<nsPIDOMWindowOuter> currentWindow = mFocusedWindow;
nsCOMPtr<nsPIDOMWindowInner> targetWindow = do_QueryInterface(aTarget);
nsCOMPtr<nsIDocument> targetDocument = do_QueryInterface(aTarget);
nsCOMPtr<nsIContent> currentFocusedContent = currentWindow ?
currentWindow->GetFocusedNode() : nullptr;
bool dontDispatchEvent =
eventTargetDoc && nsContentUtils::IsUserFocusIgnored(eventTargetDoc);
#ifdef ACCESSIBILITY
nsAccessibilityService* accService = GetAccService();
if (accService) {
@ -2174,7 +2200,7 @@ nsFocusManager::SendFocusOrBlurEvent(EventMessage aEventMessage,
// resolved.
if (!targetWindow && !targetDocument) {
EventMessage focusInOrOutMessage = aEventMessage == eFocus ? eFocusIn : eFocusOut;
SendFocusInOrOutEvent(focusInOrOutMessage, aPresShell, aTarget,
FireFocusInOrOutEvent(focusInOrOutMessage, aPresShell, aTarget,
currentWindow, currentFocusedContent, aRelatedTarget);
}
}

View File

@ -280,7 +280,8 @@ protected:
nsIContent* aContentLostFocus = nullptr);
/**
* Fires a focus or blur event at aTarget.
* Send a focus or blur event at aTarget. It may be added to the delayed
* event queue if the document is suppressing events.
*
* aEventMessage should be either eFocus or eBlur.
* For blur events, aFocusMethod should normally be non-zero.
@ -297,7 +298,22 @@ protected:
mozilla::dom::EventTarget* aRelatedTarget = nullptr);
/**
* Send a focusin or focusout event
* Fire a focus or blur event at aTarget.
*
* aEventMessage should be either eFocus or eBlur.
* For blur events, aFocusMethod should normally be non-zero.
*
* aWindowRaised should only be true if called from WindowRaised.
*/
void FireFocusOrBlurEvent(mozilla::EventMessage aEventMessage,
nsIPresShell* aPresShell,
nsISupports* aTarget,
bool aWindowRaised,
bool aIsRefocus = false,
mozilla::dom::EventTarget* aRelatedTarget = nullptr);
/**
* Fire a focusin or focusout event
*
* aEventMessage should be either eFocusIn or eFocusOut.
*
@ -313,7 +329,7 @@ protected:
* aRelatedTarget is the content related to the event (the object
* losing focus for focusin, the object getting focus for focusout).
*/
void SendFocusInOrOutEvent(mozilla::EventMessage aEventMessage,
void FireFocusInOrOutEvent(mozilla::EventMessage aEventMessage,
nsIPresShell* aPresShell,
nsISupports* aTarget,
nsPIDOMWindowOuter* aCurrentFocusedWindow,