From ed5fb21283bb453cc813bf1eb96db8cb2d4e4e32 Mon Sep 17 00:00:00 2001 From: "aaronl%netscape.com" Date: Sat, 14 Dec 2002 08:05:51 +0000 Subject: [PATCH] Bug 110718. During the 'transferring' when the currently visible document is a zombie, the keyboard is dead for the entire document. r=bryner, sr=hyatt+scc git-svn-id: svn://10.0.0.236/trunk@135298 18797224-902f-48f8-a5cc-f745e15eee43 --- .../events/src/nsEventStateManager.cpp | 39 ++++++++++--- mozilla/docshell/base/nsDocShell.cpp | 17 ++++++ mozilla/layout/base/nsPresShell.cpp | 58 ++++++++++++++++++- mozilla/layout/html/base/src/nsPresShell.cpp | 58 ++++++++++++++++++- 4 files changed, 161 insertions(+), 11 deletions(-) diff --git a/mozilla/content/events/src/nsEventStateManager.cpp b/mozilla/content/events/src/nsEventStateManager.cpp index 7abc8d69736..a81eda8ff5f 100644 --- a/mozilla/content/events/src/nsEventStateManager.cpp +++ b/mozilla/content/events/src/nsEventStateManager.cpp @@ -3620,12 +3620,32 @@ nsEventStateManager::GetNextTabbableContent(nsIContent* aRootContent, nsIFrame* disabled = PR_FALSE; } } - else if (nsHTMLAtoms::iframe==tag) { - disabled = PR_FALSE; + else if (nsHTMLAtoms::iframe==tag || nsHTMLAtoms::frame==tag) { + disabled = PR_TRUE; + if (child) { + nsCOMPtr doc, subDoc; + child->GetDocument(*getter_AddRefs(doc)); + if (doc) { + doc->GetSubDocumentFor(child, getter_AddRefs(subDoc)); + nsCOMPtr container; + subDoc->GetContainer(getter_AddRefs(container)); + nsCOMPtr docShell(do_QueryInterface(container)); + if (docShell) { + nsCOMPtr contentViewer, zombieViewer; + docShell->GetContentViewer(getter_AddRefs(contentViewer)); + if (contentViewer) { + contentViewer->GetPreviousViewer(getter_AddRefs(zombieViewer)); + if (!zombieViewer) { + // If there are 2 viewers for the current docshell, that + // means the current document is a zombie document. + // Only navigate into the frame/iframe if it's not a zombie + disabled = PR_FALSE; + } + } + } + } + } } - else if (nsHTMLAtoms::frame==tag) { - disabled = PR_FALSE; - } } // Check the tabindex attribute, unless the model specifies text only. // If the model is unset then we'll depend on tabindex. @@ -4684,7 +4704,11 @@ void nsEventStateManager::FocusElementButNotDocument(nsIContent *aContent) { // Focus an element in the current document, but don't switch document/window focus! - if (gLastFocusedDocument == mDocument) { // If we're already in this document, use normal focus method + if (gLastFocusedDocument == mDocument || + !gLastFocusedContent) { + // If we're already focused in this document, + // or if there was no last focus + // use normal focus method if (mCurrentFocus != aContent) { if (aContent) aContent->SetFocus(mPresContext); @@ -4693,7 +4717,8 @@ void nsEventStateManager::FocusElementButNotDocument(nsIContent *aContent) } return; } - // The last focus wasn't in this document, so we may be getting our postion from the selection + + // The last focus wasn't in this document, so we may be getting our position from the selection // while the window focus is currently somewhere else such as the find dialog // Temporarily save the current focus globals so we can leave them undisturbed after this method diff --git a/mozilla/docshell/base/nsDocShell.cpp b/mozilla/docshell/base/nsDocShell.cpp index 46304e5bcf0..e65c890c73d 100644 --- a/mozilla/docshell/base/nsDocShell.cpp +++ b/mozilla/docshell/base/nsDocShell.cpp @@ -117,6 +117,7 @@ #include "nsIExternalProtocolService.h" #include "nsIFocusController.h" +#include "nsIEventStateManager.h" #include "nsITextToSubURI.h" @@ -4614,6 +4615,22 @@ nsDocShell::SetupNewViewer(nsIContentViewer * aNewViewer) } } + // Eliminate the focus ring in the current docshell, which is + // now a zombie. If we key navigate, it won't be within this + // docshell, until the newly loading document is displayed. + if (mItemType == typeContent) { + nsCOMPtr presContext; + GetPresContext(getter_AddRefs(presContext)); + if (presContext) { + nsCOMPtr esm; + presContext->GetEventStateManager(getter_AddRefs(esm)); + if (esm) { + esm->SetFocusedContent(nsnull); + esm->SetContentState(nsnull, NS_EVENT_STATE_FOCUS); + } + } + } + // It is necessary to obtain the focus controller to utilize its ability // to suppress focus. This is necessary to fix Win32-only bugs related to // a loss of focus when mContentViewer is set to null. The internal window diff --git a/mozilla/layout/base/nsPresShell.cpp b/mozilla/layout/base/nsPresShell.cpp index 97124d5bcdf..351fc28688d 100644 --- a/mozilla/layout/base/nsPresShell.cpp +++ b/mozilla/layout/base/nsPresShell.cpp @@ -1360,6 +1360,11 @@ protected: private: + PRBool InZombieDocument(nsIContent *aContent); + nsresult RetargetEventToParent(nsIView *aView, nsGUIEvent* aEvent, + nsEventStatus* aEventStatus, PRBool aForceHandle, + PRBool& aHandled); + void FreeDynamicStack(); //helper funcs for disabing autoscrolling @@ -5864,6 +5869,52 @@ PresShell::PopCurrentEventInfo() } } +PRBool PresShell::InZombieDocument(nsIContent *aContent) +{ + // If a content node points to a null document, it is a + // zombie document, about to be replaced by a newly loading document. + // Such documents cannot handle DOM events. + nsCOMPtr doc; + mCurrentEventContent->GetDocument(*getter_AddRefs(doc)); + return !doc; +} + +nsresult PresShell::RetargetEventToParent(nsIView *aView, + nsGUIEvent* aEvent, + nsEventStatus* aEventStatus, + PRBool aForceHandle, + PRBool& aHandled) +{ + // Sent this events straight up to the parent pres shell. + // We do this for non-mouse events in zombie documents. + // That way at least the UI key bindings can work. + + nsCOMPtr container; + mPresContext->GetContainer(getter_AddRefs(container)); + nsCOMPtr treeItem = + do_QueryInterface(container); + if (treeItem) { + nsCOMPtr parentTreeItem; + treeItem->GetParent(getter_AddRefs(parentTreeItem)); + nsCOMPtr parentDocShell = + do_QueryInterface(parentTreeItem); + if (parentDocShell && treeItem != parentTreeItem) { + nsCOMPtr parentPresShell; + parentDocShell->GetPresShell(getter_AddRefs(parentPresShell)); + nsCOMPtr parentViewObserver = + do_QueryInterface(parentPresShell); + if (parentViewObserver) { + PopCurrentEventInfo(); + return parentViewObserver->HandleEvent(aView, aEvent, + aEventStatus, + aForceHandle, + aHandled); + } + } + } + return NS_ERROR_FAILURE; +} + NS_IMETHODIMP PresShell::HandleEvent(nsIView *aView, nsGUIEvent* aEvent, @@ -5942,8 +5993,7 @@ PresShell::HandleEvent(nsIView *aView, if (mSelectionFlags && NS_SUCCEEDED(mSelection->HandleKeyEvent(mPresContext, aEvent))) { return NS_OK; - } - } + } } */ if (nsnull != frame) { PushCurrentEventInfo(nsnull, nsnull); @@ -5996,6 +6046,10 @@ PresShell::HandleEvent(nsIView *aView, #endif /* defined(MOZ_X11) */ mCurrentEventFrame = nsnull; } + if (mCurrentEventContent && InZombieDocument(mCurrentEventContent)) { + return RetargetEventToParent(aView, aEvent, aEventStatus, + aForceHandle, aHandled); + } } else if (!InClipRect(frame, aEvent->point)) { // we only check for the clip rect on this frame ... all frames with clip have views so any diff --git a/mozilla/layout/html/base/src/nsPresShell.cpp b/mozilla/layout/html/base/src/nsPresShell.cpp index 97124d5bcdf..351fc28688d 100644 --- a/mozilla/layout/html/base/src/nsPresShell.cpp +++ b/mozilla/layout/html/base/src/nsPresShell.cpp @@ -1360,6 +1360,11 @@ protected: private: + PRBool InZombieDocument(nsIContent *aContent); + nsresult RetargetEventToParent(nsIView *aView, nsGUIEvent* aEvent, + nsEventStatus* aEventStatus, PRBool aForceHandle, + PRBool& aHandled); + void FreeDynamicStack(); //helper funcs for disabing autoscrolling @@ -5864,6 +5869,52 @@ PresShell::PopCurrentEventInfo() } } +PRBool PresShell::InZombieDocument(nsIContent *aContent) +{ + // If a content node points to a null document, it is a + // zombie document, about to be replaced by a newly loading document. + // Such documents cannot handle DOM events. + nsCOMPtr doc; + mCurrentEventContent->GetDocument(*getter_AddRefs(doc)); + return !doc; +} + +nsresult PresShell::RetargetEventToParent(nsIView *aView, + nsGUIEvent* aEvent, + nsEventStatus* aEventStatus, + PRBool aForceHandle, + PRBool& aHandled) +{ + // Sent this events straight up to the parent pres shell. + // We do this for non-mouse events in zombie documents. + // That way at least the UI key bindings can work. + + nsCOMPtr container; + mPresContext->GetContainer(getter_AddRefs(container)); + nsCOMPtr treeItem = + do_QueryInterface(container); + if (treeItem) { + nsCOMPtr parentTreeItem; + treeItem->GetParent(getter_AddRefs(parentTreeItem)); + nsCOMPtr parentDocShell = + do_QueryInterface(parentTreeItem); + if (parentDocShell && treeItem != parentTreeItem) { + nsCOMPtr parentPresShell; + parentDocShell->GetPresShell(getter_AddRefs(parentPresShell)); + nsCOMPtr parentViewObserver = + do_QueryInterface(parentPresShell); + if (parentViewObserver) { + PopCurrentEventInfo(); + return parentViewObserver->HandleEvent(aView, aEvent, + aEventStatus, + aForceHandle, + aHandled); + } + } + } + return NS_ERROR_FAILURE; +} + NS_IMETHODIMP PresShell::HandleEvent(nsIView *aView, nsGUIEvent* aEvent, @@ -5942,8 +5993,7 @@ PresShell::HandleEvent(nsIView *aView, if (mSelectionFlags && NS_SUCCEEDED(mSelection->HandleKeyEvent(mPresContext, aEvent))) { return NS_OK; - } - } + } } */ if (nsnull != frame) { PushCurrentEventInfo(nsnull, nsnull); @@ -5996,6 +6046,10 @@ PresShell::HandleEvent(nsIView *aView, #endif /* defined(MOZ_X11) */ mCurrentEventFrame = nsnull; } + if (mCurrentEventContent && InZombieDocument(mCurrentEventContent)) { + return RetargetEventToParent(aView, aEvent, aEventStatus, + aForceHandle, aHandled); + } } else if (!InClipRect(frame, aEvent->point)) { // we only check for the clip rect on this frame ... all frames with clip have views so any