зеркало из https://github.com/mozilla/pjs.git
Fix some issues related to focus changes in onfocus and onblur handlers:
- Abort firing blur events on the document and/or window if one of the blur handlers focuses something else. This ensures that the caret doesn't get confused about whether it should be active. - Release any mouse or key grab when the view manager sees a deactivate event; this fixes event targeting when a mousedown handler opens a modal dialog. - Make sure the editor element is actually focused before activating the caret. Just receiving a focus event isn't good enough, since a focus change does not cancel propagation of the original event. Bug 53579, r=jkeiser, sr=roc.
This commit is contained in:
Родитель
5e33fad8a7
Коммит
6d59e7a395
|
@ -4145,9 +4145,13 @@ nsEventStateManager::SendFocusBlur(nsIPresContext* aPresContext, nsIContent *aCo
|
|||
{
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
aPresContext->GetShell(getter_AddRefs(presShell));
|
||||
|
||||
|
||||
nsCOMPtr<nsIContent> previousFocus = mCurrentFocus;
|
||||
|
||||
if (nsnull != gLastFocusedPresContext) {
|
||||
|
||||
|
||||
nsCOMPtr<nsIContent> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<nsIDocument> doc;
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aTarget);
|
||||
if (content)
|
||||
content->GetDocument(getter_AddRefs(doc));
|
||||
else
|
||||
doc = do_QueryInterface(aTarget);
|
||||
|
||||
if (!doc)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
doc->GetShellAt(0, getter_AddRefs(shell));
|
||||
if (!shell)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIPresContext> presContext;
|
||||
shell->GetPresContext(getter_AddRefs(presContext));
|
||||
if (!presContext)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIEventStateManager> esm;
|
||||
presContext->GetEventStateManager(getter_AddRefs(esm));
|
||||
if (!esm)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIContent> 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<nsIDOMEventTarget> target;
|
||||
aEvent->GetTarget(getter_AddRefs(target));
|
||||
if (!IsTargetFocused(target))
|
||||
return NS_OK;
|
||||
|
||||
// turn on selection and caret
|
||||
if (mEditor)
|
||||
{
|
||||
|
|
|
@ -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)))) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче