From 4e288d05f28e0dfa7f63ac4f093e62c0806acfec Mon Sep 17 00:00:00 2001 From: "bzbarsky%mit.edu" Date: Mon, 28 Aug 2006 02:04:16 +0000 Subject: [PATCH] Retarget key events to the parent presshell if we have no root content. Bug 303260, r=mats, sr=roc git-svn-id: svn://10.0.0.236/trunk@208595 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/docshell/base/nsDocShell.cpp | 52 ++++++++++++++++++++++------ mozilla/layout/base/nsPresShell.cpp | 15 ++++---- 2 files changed, 51 insertions(+), 16 deletions(-) diff --git a/mozilla/docshell/base/nsDocShell.cpp b/mozilla/docshell/base/nsDocShell.cpp index b90787f0025..ae801ad184f 100644 --- a/mozilla/docshell/base/nsDocShell.cpp +++ b/mozilla/docshell/base/nsDocShell.cpp @@ -8555,6 +8555,27 @@ nsDocShell::SetHasFocus(PRBool aHasFocus) return NS_OK; } +// Find an nsICanvasFrame under aFrame. Only search the principal +// child lists. aFrame must be non-null. +static nsICanvasFrame* FindCanvasFrame(nsIFrame* aFrame) +{ + nsICanvasFrame* canvasFrame; + if (NS_SUCCEEDED(CallQueryInterface(aFrame, &canvasFrame))) { + return canvasFrame; + } + + nsIFrame* kid = aFrame->GetFirstChild(nsnull); + while (kid) { + canvasFrame = FindCanvasFrame(kid); + if (canvasFrame) { + return canvasFrame; + } + kid = kid->GetNextSibling(); + } + + return nsnull; +} + //------------------------------------------------------- // Tells the HTMLFrame/CanvasFrame that is now has focus NS_IMETHODIMP @@ -8571,17 +8592,28 @@ nsDocShell::SetCanvasHasFocus(PRBool aCanvasHasFocus) if (!doc) return NS_ERROR_FAILURE; nsIContent *rootContent = doc->GetRootContent(); - if (!rootContent) return NS_ERROR_FAILURE; - - nsIFrame* frame = presShell->GetPrimaryFrameFor(rootContent); - if (frame) { - frame = frame->GetParent(); - if (frame) { - nsICanvasFrame* canvasFrame; - if (NS_SUCCEEDED(frame->QueryInterface(NS_GET_IID(nsICanvasFrame), (void**)&canvasFrame))) - return canvasFrame->SetHasFocus(aCanvasHasFocus); - } + if (rootContent) { + nsIFrame* frame = presShell->GetPrimaryFrameFor(rootContent); + if (frame) { + frame = frame->GetParent(); + if (frame) { + nsICanvasFrame* canvasFrame; + if (NS_SUCCEEDED(CallQueryInterface(frame, &canvasFrame))) { + return canvasFrame->SetHasFocus(aCanvasHasFocus); + } + } + } + } else { + // Look for the frame the hard way + nsIFrame* frame = presShell->GetRootFrame(); + if (frame) { + nsICanvasFrame* canvasFrame = FindCanvasFrame(frame); + if (canvasFrame) { + return canvasFrame->SetHasFocus(aCanvasHasFocus); + } + } } + return NS_ERROR_FAILURE; } diff --git a/mozilla/layout/base/nsPresShell.cpp b/mozilla/layout/base/nsPresShell.cpp index 4c898ec4a95..5a88b5099d6 100644 --- a/mozilla/layout/base/nsPresShell.cpp +++ b/mozilla/layout/base/nsPresShell.cpp @@ -5804,9 +5804,10 @@ nsresult PresShell::RetargetEventToParent(nsIView *aView, // We do this for non-mouse events in zombie documents. // That way at least the UI key bindings can work. - // First, 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. + // First, 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 or we + // have a root content again. nsCOMPtr kungFuDeathGrip(this); // hold a reference to the ESM across event dispatch @@ -5814,8 +5815,10 @@ nsresult PresShell::RetargetEventToParent(nsIView *aView, esm->SetContentState(nsnull, NS_EVENT_STATE_FOCUS); esm->SetFocusedContent(nsnull); - ContentStatesChanged(mDocument, aZombieFocusedContent, - nsnull, NS_EVENT_STATE_FOCUS); + if (aZombieFocusedContent) { + ContentStatesChanged(mDocument, aZombieFocusedContent, + nsnull, NS_EVENT_STATE_FOCUS); + } // Next, update the display so the old focus ring is no longer visible @@ -6019,7 +6022,7 @@ PresShell::HandleEvent(nsIView *aView, } mCurrentEventFrame = nsnull; // XXXldb Isn't it already? } - if (mCurrentEventContent && InZombieDocument(mCurrentEventContent)) { + if (!mCurrentEventContent || InZombieDocument(mCurrentEventContent)) { return RetargetEventToParent(aView, aEvent, aEventStatus, mCurrentEventContent); }