mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 522352 - make nsSubDocumentFrame not assume as much about docshells: move all that into the frameloader, r=bz (preparation and merge reduction for Electrolysis, where not all frameloaders have docshells)
--HG-- extra : rebase_source : 7c51147603fccb93040fdb6e883b33dbab130040
This commit is contained in:
parent
bbc370f4a7
commit
4bb6d6c511
@ -49,6 +49,7 @@
|
||||
#include "nsPresContext.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIContentViewer.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
@ -64,6 +65,7 @@
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIScrollable.h"
|
||||
#include "nsFrameLoader.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIFrame.h"
|
||||
@ -74,6 +76,8 @@
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsISHistory.h"
|
||||
#include "nsISHistoryInternal.h"
|
||||
#include "nsIDOMNSHTMLDocument.h"
|
||||
#include "nsIView.h"
|
||||
|
||||
#include "nsIURI.h"
|
||||
#include "nsIURL.h"
|
||||
@ -465,6 +469,107 @@ AllDescendantsOfType(nsIDocShellTreeItem* aParentItem, PRInt32 aType)
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
bool
|
||||
nsFrameLoader::Show(PRInt32 marginWidth, PRInt32 marginHeight,
|
||||
PRInt32 scrollbarPrefX, PRInt32 scrollbarPrefY,
|
||||
nsIFrameFrame* frame)
|
||||
{
|
||||
nsContentType contentType;
|
||||
|
||||
nsresult rv = EnsureDocShell();
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mDocShell)
|
||||
return false;
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
mDocShell->GetPresShell(getter_AddRefs(presShell));
|
||||
if (presShell)
|
||||
return true;
|
||||
|
||||
mDocShell->SetMarginWidth(marginWidth);
|
||||
mDocShell->SetMarginHeight(marginHeight);
|
||||
|
||||
nsCOMPtr<nsIScrollable> sc = do_QueryInterface(mDocShell);
|
||||
if (sc) {
|
||||
sc->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_X,
|
||||
scrollbarPrefX);
|
||||
sc->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_Y,
|
||||
scrollbarPrefY);
|
||||
}
|
||||
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(mDocShell);
|
||||
NS_ASSERTION(treeItem,
|
||||
"Found a nsIDocShell that isn't a nsIDocShellTreeItem.");
|
||||
|
||||
PRInt32 itemType;
|
||||
treeItem->GetItemType(&itemType);
|
||||
|
||||
if (itemType == nsIDocShellTreeItem::typeChrome)
|
||||
contentType = eContentTypeUI;
|
||||
else {
|
||||
nsCOMPtr<nsIDocShellTreeItem> sameTypeParent;
|
||||
treeItem->GetSameTypeParent(getter_AddRefs(sameTypeParent));
|
||||
contentType = sameTypeParent ? eContentTypeContentFrame : eContentTypeContent;
|
||||
}
|
||||
|
||||
nsIView* view = frame->CreateViewAndWidget(contentType);
|
||||
if (!view)
|
||||
return false;
|
||||
|
||||
nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(mDocShell);
|
||||
NS_ASSERTION(baseWindow, "Found a nsIDocShell that isn't a nsIBaseWindow.");
|
||||
baseWindow->InitWindow(nsnull, view->GetWidget(), 0, 0, 10, 10);
|
||||
// This is kinda whacky, this "Create()" call doesn't really
|
||||
// create anything, one starts to wonder why this was named
|
||||
// "Create"...
|
||||
baseWindow->Create();
|
||||
baseWindow->SetVisibility(PR_TRUE);
|
||||
|
||||
// Trigger editor re-initialization if midas is turned on in the
|
||||
// sub-document. This shouldn't be necessary, but given the way our
|
||||
// editor works, it is. See
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=284245
|
||||
mDocShell->GetPresShell(getter_AddRefs(presShell));
|
||||
if (presShell) {
|
||||
nsCOMPtr<nsIDOMNSHTMLDocument> doc =
|
||||
do_QueryInterface(presShell->GetDocument());
|
||||
|
||||
if (doc) {
|
||||
nsAutoString designMode;
|
||||
doc->GetDesignMode(designMode);
|
||||
|
||||
if (designMode.EqualsLiteral("on")) {
|
||||
doc->SetDesignMode(NS_LITERAL_STRING("off"));
|
||||
doc->SetDesignMode(NS_LITERAL_STRING("on"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
nsFrameLoader::Hide()
|
||||
{
|
||||
if (!mDocShell)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIContentViewer> contentViewer;
|
||||
mDocShell->GetContentViewer(getter_AddRefs(contentViewer));
|
||||
if (contentViewer)
|
||||
contentViewer->SetSticky(PR_FALSE);
|
||||
|
||||
nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(mDocShell);
|
||||
NS_ASSERTION(baseWin,
|
||||
"Found an nsIDocShell which doesn't implement nsIBaseWindow.");
|
||||
baseWin->SetVisibility(PR_FALSE);
|
||||
baseWin->SetParentWidget(nsnull);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
|
||||
nsRefPtr<nsFrameLoader>& aFirstToSwap,
|
||||
|
@ -51,6 +51,7 @@
|
||||
|
||||
class nsIContent;
|
||||
class nsIURI;
|
||||
class nsIFrameFrame;
|
||||
|
||||
class nsFrameLoader : public nsIFrameLoader
|
||||
{
|
||||
@ -80,6 +81,21 @@ public:
|
||||
void Finalize();
|
||||
nsIDocShell* GetExistingDocShell() { return mDocShell; }
|
||||
|
||||
/**
|
||||
* Called from the layout frame associated with this frame loader;
|
||||
* this notifies us to hook up with the widget and view.
|
||||
*/
|
||||
bool Show(PRInt32 marginWidth, PRInt32 marginHeight,
|
||||
PRInt32 scrollbarPrefX, PRInt32 scrollbarPrefY,
|
||||
nsIFrameFrame* frame);
|
||||
|
||||
/**
|
||||
* Called from the layout frame associated with this frame loader, when
|
||||
* the frame is being torn down; this notifies us that out widget and view
|
||||
* are going away and we should unhook from them.
|
||||
*/
|
||||
void Hide();
|
||||
|
||||
// The guts of an nsIFrameLoaderOwner::SwapFrameLoader implementation. A
|
||||
// frame loader owner needs to call this, and pass in the two references to
|
||||
// nsRefPtrs for frame loaders that need to be swapped.
|
||||
|
@ -74,7 +74,7 @@
|
||||
#include "nsIDOMHTMLFrameElement.h"
|
||||
#include "nsIDOMHTMLIFrameElement.h"
|
||||
#include "nsIDOMXULElement.h"
|
||||
#include "nsIFrameLoader.h"
|
||||
#include "nsFrameLoader.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsIScrollable.h"
|
||||
@ -190,9 +190,10 @@ protected:
|
||||
// Helper method to look up the HTML marginwidth & marginheight attributes
|
||||
nsIntSize GetMarginAttributes();
|
||||
|
||||
nsFrameLoader* FrameLoader();
|
||||
|
||||
PRBool IsInline() { return mIsInline; }
|
||||
nsresult ShowDocShell();
|
||||
nsresult CreateViewAndWidget(nsContentType aContentType);
|
||||
nsIView* CreateViewAndWidget(nsContentType aContentType);
|
||||
|
||||
virtual nscoord GetIntrinsicWidth();
|
||||
virtual nscoord GetIntrinsicHeight();
|
||||
@ -213,16 +214,18 @@ protected:
|
||||
*/
|
||||
nsIFrame* ObtainIntrinsicSizeFrame();
|
||||
|
||||
nsCOMPtr<nsIFrameLoader> mFrameLoader;
|
||||
nsRefPtr<nsFrameLoader> mFrameLoader;
|
||||
nsIView* mInnerView;
|
||||
PRPackedBool mDidCreateDoc;
|
||||
PRPackedBool mIsInline;
|
||||
PRPackedBool mPostedReflowCallback;
|
||||
bool mDidCreateDoc;
|
||||
};
|
||||
|
||||
nsSubDocumentFrame::nsSubDocumentFrame(nsStyleContext* aContext)
|
||||
: nsLeafFrame(aContext), mDidCreateDoc(PR_FALSE),
|
||||
mIsInline(PR_FALSE), mPostedReflowCallback(PR_FALSE)
|
||||
: nsLeafFrame(aContext)
|
||||
, mIsInline(PR_FALSE)
|
||||
, mPostedReflowCallback(PR_FALSE)
|
||||
, mDidCreateDoc(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -287,22 +290,39 @@ nsSubDocumentFrame::Init(nsIContent* aContent,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
inline PRInt32 ConvertOverflow(PRUint8 aOverflow)
|
||||
{
|
||||
switch (aOverflow) {
|
||||
case NS_STYLE_OVERFLOW_VISIBLE:
|
||||
case NS_STYLE_OVERFLOW_AUTO:
|
||||
return nsIScrollable::Scrollbar_Auto;
|
||||
case NS_STYLE_OVERFLOW_HIDDEN:
|
||||
case NS_STYLE_OVERFLOW_CLIP:
|
||||
return nsIScrollable::Scrollbar_Never;
|
||||
case NS_STYLE_OVERFLOW_SCROLL:
|
||||
return nsIScrollable::Scrollbar_Always;
|
||||
}
|
||||
NS_NOTREACHED("invalid overflow value passed to ConvertOverflow");
|
||||
return nsIScrollable::Scrollbar_Auto;
|
||||
}
|
||||
|
||||
void
|
||||
nsSubDocumentFrame::ShowViewer()
|
||||
{
|
||||
if (!PresContext()->IsDynamic()) {
|
||||
// We let the printing code take care of loading the document; just
|
||||
// create a widget for it to use
|
||||
nsresult rv = CreateViewAndWidget(eContentTypeContent);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
(void) CreateViewAndWidget(eContentTypeContent);
|
||||
} else {
|
||||
nsresult rv = ShowDocShell();
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
nsFrameLoader* frameloader = FrameLoader();
|
||||
if (frameloader) {
|
||||
nsIntSize margin = GetMarginAttributes();
|
||||
const nsStyleDisplay* disp = GetStyleDisplay();
|
||||
mDidCreateDoc = frameloader->Show(margin.width, margin.height,
|
||||
ConvertOverflow(disp->mOverflowX),
|
||||
ConvertOverflow(disp->mOverflowY),
|
||||
this);
|
||||
}
|
||||
mDidCreateDoc = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -777,39 +797,8 @@ nsSubDocumentFrame::Destroy()
|
||||
void
|
||||
nsSubDocumentFrame::HideViewer()
|
||||
{
|
||||
if (mFrameLoader && mDidCreateDoc) {
|
||||
// Get the content viewer through the docshell, but don't call
|
||||
// GetDocShell() since we don't want to create one if we don't
|
||||
// have one.
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell;
|
||||
mFrameLoader->GetDocShell(getter_AddRefs(docShell));
|
||||
|
||||
if (docShell) {
|
||||
nsCOMPtr<nsIContentViewer> content_viewer;
|
||||
docShell->GetContentViewer(getter_AddRefs(content_viewer));
|
||||
|
||||
if (content_viewer) {
|
||||
// Mark the content viewer as non-sticky so that the presentation
|
||||
// can safely go away when this frame is destroyed.
|
||||
|
||||
content_viewer->SetSticky(PR_FALSE);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(docShell);
|
||||
NS_ASSERTION(baseWin, "Docshell must be an nsIBaseWindow");
|
||||
|
||||
// Now reverse the steps we took in ShowDocShell(). But don't call
|
||||
// Destroy(); that will be handled by destroying our frame loader, if
|
||||
// needed.
|
||||
|
||||
// Hide the content viewer now that the frame is going away...
|
||||
baseWin->SetVisibility(PR_FALSE);
|
||||
|
||||
// Clear out the parentWidget, since it might be about to die with us
|
||||
baseWin->SetParentWidget(nsnull);
|
||||
}
|
||||
}
|
||||
if (mFrameLoader && mDidCreateDoc)
|
||||
mFrameLoader->Hide();
|
||||
}
|
||||
|
||||
nsIntSize
|
||||
@ -828,6 +817,24 @@ nsSubDocumentFrame::GetMarginAttributes()
|
||||
return result;
|
||||
}
|
||||
|
||||
nsFrameLoader*
|
||||
nsSubDocumentFrame::FrameLoader()
|
||||
{
|
||||
nsIContent* content = GetContent();
|
||||
if (!content)
|
||||
return nsnull;
|
||||
|
||||
if (!mFrameLoader) {
|
||||
nsCOMPtr<nsIFrameLoaderOwner> loaderOwner = do_QueryInterface(content);
|
||||
if (loaderOwner) {
|
||||
nsCOMPtr<nsIFrameLoader> loader;
|
||||
loaderOwner->GetFrameLoader(getter_AddRefs(loader));
|
||||
mFrameLoader = static_cast<nsFrameLoader*>(loader.get());
|
||||
}
|
||||
}
|
||||
return mFrameLoader;
|
||||
}
|
||||
|
||||
// XXX this should be called ObtainDocShell or something like that,
|
||||
// to indicate that it could have side effects
|
||||
NS_IMETHODIMP
|
||||
@ -835,23 +842,7 @@ nsSubDocumentFrame::GetDocShell(nsIDocShell **aDocShell)
|
||||
{
|
||||
*aDocShell = nsnull;
|
||||
|
||||
nsIContent* content = GetContent();
|
||||
if (!content) {
|
||||
// Hmm, no content in this frame
|
||||
// that's odd, not much to be done here then.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!mFrameLoader) {
|
||||
nsCOMPtr<nsIFrameLoaderOwner> loaderOwner = do_QueryInterface(content);
|
||||
|
||||
if (loaderOwner) {
|
||||
loaderOwner->GetFrameLoader(getter_AddRefs(mFrameLoader));
|
||||
}
|
||||
|
||||
NS_ENSURE_STATE(mFrameLoader);
|
||||
}
|
||||
|
||||
NS_ENSURE_STATE(FrameLoader());
|
||||
return mFrameLoader->GetDocShell(aDocShell);
|
||||
}
|
||||
|
||||
@ -895,122 +886,14 @@ nsSubDocumentFrame::EndSwapDocShells(nsIFrame* aOther)
|
||||
other->InvalidateOverflowRect();
|
||||
}
|
||||
|
||||
inline PRInt32 ConvertOverflow(PRUint8 aOverflow)
|
||||
{
|
||||
switch (aOverflow) {
|
||||
case NS_STYLE_OVERFLOW_VISIBLE:
|
||||
case NS_STYLE_OVERFLOW_AUTO:
|
||||
return nsIScrollable::Scrollbar_Auto;
|
||||
case NS_STYLE_OVERFLOW_HIDDEN:
|
||||
case NS_STYLE_OVERFLOW_CLIP:
|
||||
return nsIScrollable::Scrollbar_Never;
|
||||
case NS_STYLE_OVERFLOW_SCROLL:
|
||||
return nsIScrollable::Scrollbar_Always;
|
||||
}
|
||||
NS_NOTREACHED("invalid overflow value passed to ConvertOverflow");
|
||||
return nsIScrollable::Scrollbar_Auto;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSubDocumentFrame::ShowDocShell()
|
||||
{
|
||||
nsCOMPtr<nsIDocShell> docShell;
|
||||
nsresult rv = GetDocShell(getter_AddRefs(docShell));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
docShell->GetPresShell(getter_AddRefs(presShell));
|
||||
|
||||
if (presShell) {
|
||||
// The docshell is already showing, nothing left to do...
|
||||
NS_ASSERTION(mInnerView, "What's going on?");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// pass along marginwidth, marginheight, scrolling so sub document
|
||||
// can use it
|
||||
nsIntSize margin = GetMarginAttributes();
|
||||
docShell->SetMarginWidth(margin.width);
|
||||
docShell->SetMarginHeight(margin.height);
|
||||
|
||||
// Current and initial scrolling is set so that all succeeding docs
|
||||
// will use the scrolling value set here, regardless if scrolling is
|
||||
// set by viewing a particular document (e.g. XUL turns off scrolling)
|
||||
nsCOMPtr<nsIScrollable> sc(do_QueryInterface(docShell));
|
||||
|
||||
if (sc) {
|
||||
const nsStyleDisplay *disp = GetStyleDisplay();
|
||||
sc->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_X,
|
||||
ConvertOverflow(disp->mOverflowX));
|
||||
sc->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_Y,
|
||||
ConvertOverflow(disp->mOverflowY));
|
||||
}
|
||||
|
||||
PRInt32 itemType = nsIDocShellTreeItem::typeContent;
|
||||
nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(docShell));
|
||||
if (treeItem) {
|
||||
treeItem->GetItemType(&itemType);
|
||||
}
|
||||
|
||||
nsContentType contentType;
|
||||
if (itemType == nsIDocShellTreeItem::typeChrome) {
|
||||
contentType = eContentTypeUI;
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIDocShellTreeItem> sameTypeParent;
|
||||
treeItem->GetSameTypeParent(getter_AddRefs(sameTypeParent));
|
||||
contentType = sameTypeParent ? eContentTypeContentFrame : eContentTypeContent;
|
||||
}
|
||||
rv = CreateViewAndWidget(contentType);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(docShell));
|
||||
|
||||
if (baseWindow) {
|
||||
baseWindow->InitWindow(nsnull, mInnerView->GetWidget(), 0, 0, 10, 10);
|
||||
|
||||
// This is kinda whacky, this "Create()" call doesn't really
|
||||
// create anything, one starts to wonder why this was named
|
||||
// "Create"...
|
||||
|
||||
baseWindow->Create();
|
||||
|
||||
baseWindow->SetVisibility(PR_TRUE);
|
||||
}
|
||||
|
||||
// Trigger editor re-initialization if midas is turned on in the
|
||||
// sub-document. This shouldn't be necessary, but given the way our
|
||||
// editor works, it is. See
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=284245
|
||||
docShell->GetPresShell(getter_AddRefs(presShell));
|
||||
if (presShell) {
|
||||
nsCOMPtr<nsIDOMNSHTMLDocument> doc =
|
||||
do_QueryInterface(presShell->GetDocument());
|
||||
|
||||
if (doc) {
|
||||
nsAutoString designMode;
|
||||
doc->GetDesignMode(designMode);
|
||||
|
||||
if (designMode.EqualsLiteral("on")) {
|
||||
doc->SetDesignMode(NS_LITERAL_STRING("off"));
|
||||
doc->SetDesignMode(NS_LITERAL_STRING("on"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsIView*
|
||||
nsSubDocumentFrame::CreateViewAndWidget(nsContentType aContentType)
|
||||
{
|
||||
if (mInnerView) {
|
||||
// Nothing to do here
|
||||
return NS_OK;
|
||||
return mInnerView;
|
||||
}
|
||||
|
||||
|
||||
// create, init, set the parent of the view
|
||||
nsIView* outerView = GetView();
|
||||
NS_ASSERTION(outerView, "Must have an outer view already");
|
||||
@ -1020,18 +903,21 @@ nsSubDocumentFrame::CreateViewAndWidget(nsContentType aContentType)
|
||||
nsIView* innerView = viewMan->CreateView(viewBounds, outerView);
|
||||
if (!innerView) {
|
||||
NS_ERROR("Could not create inner view");
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
return nsnull;
|
||||
}
|
||||
mInnerView = innerView;
|
||||
viewMan->InsertChild(outerView, innerView, nsnull, PR_TRUE);
|
||||
|
||||
if (aContentType == eContentTypeContentFrame) {
|
||||
// No widget needed.
|
||||
return NS_OK;
|
||||
if (aContentType != eContentTypeContentFrame) {
|
||||
// widget needed.
|
||||
nsresult rv = innerView->CreateWidget(kCChildCID, nsnull, nsnull,
|
||||
PR_TRUE, PR_TRUE, aContentType);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Couldn't create widget for frame.");
|
||||
mInnerView = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
return innerView->CreateWidget(kCChildCID, nsnull, nsnull, PR_TRUE, PR_TRUE,
|
||||
aContentType);
|
||||
return mInnerView;
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
|
@ -44,6 +44,7 @@
|
||||
#define nsIFrameFrame_h___
|
||||
|
||||
class nsIDocShell;
|
||||
class nsIView;
|
||||
|
||||
class nsIFrameFrame
|
||||
{
|
||||
@ -59,6 +60,11 @@ public:
|
||||
*/
|
||||
NS_IMETHOD BeginSwapDocShells(nsIFrame* aOther) = 0;
|
||||
virtual void EndSwapDocShells(nsIFrame* aOther) = 0;
|
||||
|
||||
/**
|
||||
* The frameloader informs us what kind of widget to create during Show()
|
||||
*/
|
||||
virtual nsIView* CreateViewAndWidget(nsContentType aContentType) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user