зеркало из https://github.com/mozilla/gecko-dev.git
Patch for bug 112294: calling an alert box from window.onblur triggers the event multiple times
r=neil/smaug sr=roc
This commit is contained in:
Родитель
d98b8e5209
Коммит
2372bd5fea
|
@ -693,6 +693,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsEventStateManager)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLastFocus);
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLastContentFocus);
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFirstBlurEvent);
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFirstDocumentBlurEvent);
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFirstFocusEvent);
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFirstMouseOverEventElement);
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFirstMouseOutEventElement);
|
||||
|
@ -716,6 +717,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsEventStateManager)
|
|||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLastFocus);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLastContentFocus);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFirstBlurEvent);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFirstDocumentBlurEvent);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFirstFocusEvent);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFirstMouseOverEventElement);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFirstMouseOutEventElement);
|
||||
|
@ -1090,29 +1092,32 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
|||
}
|
||||
}
|
||||
|
||||
// Clear our global variables before firing the event to prevent
|
||||
// duplicate blur events (bug 112294).
|
||||
nsCOMPtr<nsIDocument> lastFocusedDocument;
|
||||
lastFocusedDocument.swap(gLastFocusedDocument);
|
||||
nsCOMPtr<nsPresContext> lastFocusedPresContext;
|
||||
lastFocusedPresContext.swap(gLastFocusedPresContext);
|
||||
mCurrentTarget = nsnull;
|
||||
|
||||
// fire blur on document and window
|
||||
if (gLastFocusedDocument) {
|
||||
if (lastFocusedDocument) {
|
||||
// get the window here, in case the event causes
|
||||
// gLastFocusedDocument to change.
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> window(gLastFocusedDocument->GetWindow());
|
||||
nsCOMPtr<nsPIDOMWindow> window(lastFocusedDocument->GetWindow());
|
||||
|
||||
event.target = nsnull;
|
||||
nsEventDispatcher::Dispatch(gLastFocusedDocument,
|
||||
gLastFocusedPresContext,
|
||||
nsEventDispatcher::Dispatch(lastFocusedDocument,
|
||||
lastFocusedPresContext,
|
||||
&event, nsnull, &status);
|
||||
|
||||
if (window) {
|
||||
event.target = nsnull;
|
||||
nsEventDispatcher::Dispatch(window, gLastFocusedPresContext,
|
||||
nsEventDispatcher::Dispatch(window, lastFocusedPresContext,
|
||||
&event, nsnull, &status);
|
||||
}
|
||||
}
|
||||
|
||||
// Now clear our our global variables
|
||||
mCurrentTarget = nsnull;
|
||||
NS_IF_RELEASE(gLastFocusedDocument);
|
||||
gLastFocusedPresContext = nsnull;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -1233,8 +1238,15 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
|||
|
||||
// Now fire blurs. Blur the content, then the document, then the window.
|
||||
|
||||
if (gLastFocusedDocument && gLastFocusedDocument == mDocument) {
|
||||
if (gLastFocusedDocument && gLastFocusedDocument == mDocument &&
|
||||
gLastFocusedDocument != mFirstDocumentBlurEvent) {
|
||||
|
||||
PRBool clearFirstDocumentBlurEvent = PR_FALSE;
|
||||
if (!mFirstDocumentBlurEvent) {
|
||||
mFirstDocumentBlurEvent = gLastFocusedDocument;
|
||||
clearFirstDocumentBlurEvent = PR_TRUE;
|
||||
}
|
||||
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
nsEvent event(PR_TRUE, NS_BLUR_CONTENT);
|
||||
event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
|
||||
|
@ -1264,6 +1276,12 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
|||
}
|
||||
}
|
||||
|
||||
// Clear our global variables before firing the event to prevent
|
||||
// duplicate blur events (bug 112294).
|
||||
mCurrentTarget = nsnull;
|
||||
NS_IF_RELEASE(gLastFocusedDocument);
|
||||
gLastFocusedPresContext = nsnull;
|
||||
|
||||
// fire blur on document and window
|
||||
event.target = nsnull;
|
||||
nsEventDispatcher::Dispatch(mDocument, aPresContext, &event, nsnull,
|
||||
|
@ -1274,11 +1292,9 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
|||
nsEventDispatcher::Dispatch(ourWindow, aPresContext, &event, nsnull,
|
||||
&status);
|
||||
}
|
||||
|
||||
// Now clear our our global variables
|
||||
mCurrentTarget = nsnull;
|
||||
NS_IF_RELEASE(gLastFocusedDocument);
|
||||
gLastFocusedPresContext = nsnull;
|
||||
if (clearFirstDocumentBlurEvent) {
|
||||
mFirstDocumentBlurEvent = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
if (focusController) {
|
||||
|
|
|
@ -379,6 +379,7 @@ protected:
|
|||
//Anti-recursive stack controls
|
||||
|
||||
nsCOMPtr<nsIContent> mFirstBlurEvent;
|
||||
nsCOMPtr<nsIDocument> mFirstDocumentBlurEvent;
|
||||
nsCOMPtr<nsIContent> mFirstFocusEvent;
|
||||
|
||||
// The last element on which we fired a mouseover event, or null if
|
||||
|
|
|
@ -522,7 +522,8 @@ nsFocusController::SetSuppressFocus(PRBool aSuppressFocus, const char* aReason)
|
|||
//#endif
|
||||
}
|
||||
else
|
||||
NS_ASSERTION(PR_FALSE, "Attempt to decrement focus controller's suppression when no suppression active!\n");
|
||||
// It's ok to unsuppress even if no suppression is active (bug 112294)
|
||||
return NS_OK;
|
||||
|
||||
// we are unsuppressing after activating, so update focus-related commands
|
||||
// we need this to update command, including the case where there is no element
|
||||
|
|
|
@ -675,8 +675,18 @@ nsWindowWatcher::OpenWindowJSInternal(nsIDOMWindow *aParent,
|
|||
if (popupConditions)
|
||||
contextFlags |= nsIWindowCreator2::PARENT_IS_LOADING_OR_RUNNING_TIMEOUT;
|
||||
|
||||
PRBool parentVisible = PR_TRUE;
|
||||
if (parentChrome)
|
||||
{
|
||||
nsCOMPtr<nsIBaseWindow> parentWindow(do_GetInterface(parentTreeOwner));
|
||||
nsCOMPtr<nsIWidget> parentWidget;
|
||||
if (parentWindow)
|
||||
parentWindow->GetMainWidget(getter_AddRefs(parentWidget));
|
||||
if (parentWidget)
|
||||
parentWidget->IsVisible(parentVisible);
|
||||
}
|
||||
PRBool cancel = PR_FALSE;
|
||||
rv = windowCreator2->CreateChromeWindow2(parentChrome, chromeFlags,
|
||||
rv = windowCreator2->CreateChromeWindow2(parentVisible ? parentChrome : nsnull, chromeFlags,
|
||||
contextFlags, uriToLoad,
|
||||
&cancel,
|
||||
getter_AddRefs(newChrome));
|
||||
|
|
|
@ -1608,6 +1608,8 @@ PRBool nsWindow::CanTakeFocus()
|
|||
|
||||
NS_METHOD nsWindow::Show(PRBool bState)
|
||||
{
|
||||
mIsVisible = bState;
|
||||
|
||||
if (mWnd) {
|
||||
if (bState) {
|
||||
if (!mIsVisible && mWindowType == eWindowType_toplevel) {
|
||||
|
@ -1672,8 +1674,6 @@ NS_METHOD nsWindow::Show(PRBool bState)
|
|||
Invalidate(PR_FALSE);
|
||||
#endif
|
||||
|
||||
mIsVisible = bState;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -478,23 +478,31 @@ NS_IMETHODIMP nsXULWindow::Destroy()
|
|||
mWindow->Show(PR_FALSE);
|
||||
|
||||
#if defined(XP_WIN) || defined(XP_OS2)
|
||||
// We need to explicitly set the focus on Windows
|
||||
// We need to explicitly set the focus on Windows, but
|
||||
// only if the parent is visible.
|
||||
nsCOMPtr<nsIBaseWindow> parent(do_QueryReferent(mParentWindow));
|
||||
if (parent) {
|
||||
nsCOMPtr<nsIBaseWindow> baseHiddenWindow;
|
||||
if (appShell) {
|
||||
nsCOMPtr<nsIXULWindow> hiddenWindow;
|
||||
appShell->GetHiddenWindow(getter_AddRefs(hiddenWindow));
|
||||
if (hiddenWindow)
|
||||
baseHiddenWindow = do_GetInterface(hiddenWindow);
|
||||
}
|
||||
// somebody screwed up somewhere. hiddenwindow shouldn't be anybody's
|
||||
// parent. still, when it happens, skip activating it.
|
||||
if (baseHiddenWindow != parent) {
|
||||
nsCOMPtr<nsIWidget> parentWidget;
|
||||
parent->GetMainWidget(getter_AddRefs(parentWidget));
|
||||
if (parentWidget)
|
||||
parentWidget->PlaceBehind(eZPlacementTop, 0, PR_TRUE);
|
||||
PRBool parentVisible = PR_TRUE;
|
||||
nsCOMPtr<nsIWidget> parentWidget;
|
||||
parent->GetMainWidget(getter_AddRefs(parentWidget));
|
||||
if (parentWidget)
|
||||
parentWidget->IsVisible(parentVisible);
|
||||
if (parentVisible) {
|
||||
nsCOMPtr<nsIBaseWindow> baseHiddenWindow;
|
||||
if (appShell) {
|
||||
nsCOMPtr<nsIXULWindow> hiddenWindow;
|
||||
appShell->GetHiddenWindow(getter_AddRefs(hiddenWindow));
|
||||
if (hiddenWindow)
|
||||
baseHiddenWindow = do_GetInterface(hiddenWindow);
|
||||
}
|
||||
// somebody screwed up somewhere. hiddenwindow shouldn't be anybody's
|
||||
// parent. still, when it happens, skip activating it.
|
||||
if (baseHiddenWindow != parent) {
|
||||
nsCOMPtr<nsIWidget> parentWidget;
|
||||
parent->GetMainWidget(getter_AddRefs(parentWidget));
|
||||
if (parentWidget)
|
||||
parentWidget->PlaceBehind(eZPlacementTop, 0, PR_TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче