зеркало из https://github.com/mozilla/gecko-dev.git
Bug 610670 - Reuse a single puppet widget. r=bz,cjones a=blocking-fennec
This commit is contained in:
Родитель
73cf0eeb7b
Коммит
731ddee374
|
@ -414,6 +414,11 @@ private:
|
|||
PRBool aStartAtTop);
|
||||
#endif // NS_PRINTING
|
||||
|
||||
// Whether we should attach to the top level widget. This is true if we
|
||||
// are sharing/recycling a single base widget and not creating multiple
|
||||
// child widgets.
|
||||
PRBool ShouldAttachToTopLevel();
|
||||
|
||||
protected:
|
||||
// These return the current shell/prescontext etc.
|
||||
nsIPresShell* GetPresShell();
|
||||
|
@ -1392,6 +1397,32 @@ DocumentViewerImpl::Open(nsISupports *aState, nsISHEntry *aSHEntry)
|
|||
// XXX re-enable image animations once that works correctly
|
||||
|
||||
PrepareToStartLoad();
|
||||
|
||||
// When loading a page from the bfcache with puppet widgets, we do the
|
||||
// widget attachment here (it is otherwise done in MakeWindow, which is
|
||||
// called for non-bfcache pages in the history, but not bfcache pages).
|
||||
// Attachment is necessary, since we get detached when another page
|
||||
// is browsed to. That is, if we are one page A, then when we go to
|
||||
// page B, we detach. So page A's view has no widget. If we then go
|
||||
// back to it, and it is in the bfcache, we will use that view, which
|
||||
// doesn't have a widget. The attach call here will properly attach us.
|
||||
if (nsIWidget::UsePuppetWidgets() && mPresContext &&
|
||||
ShouldAttachToTopLevel()) {
|
||||
// If the old view is already attached to our parent, detach
|
||||
DetachFromTopLevelWidget();
|
||||
|
||||
nsIViewManager *vm = GetViewManager();
|
||||
NS_ABORT_IF_FALSE(vm, "no view manager");
|
||||
nsIView *v;
|
||||
nsresult rv = vm->GetRootView(v);
|
||||
NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "failed in getting the root view");
|
||||
NS_ABORT_IF_FALSE(v, "no root view");
|
||||
NS_ABORT_IF_FALSE(mParentWidget, "no mParentWidget to set");
|
||||
v->AttachToTopLevelWidget(mParentWidget);
|
||||
|
||||
mAttachedToParent = PR_TRUE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2242,30 +2273,12 @@ DocumentViewerImpl::MakeWindow(const nsSize& aSize, nsIView* aContainerView)
|
|||
if (GetIsPrintPreview())
|
||||
return NS_OK;
|
||||
|
||||
// Prior to creating a new widget, check to see if our parent is a base
|
||||
// chrome ui window. If so, drop the content into that widget instead of
|
||||
// creating a new child widget. This eliminates the main content child
|
||||
// widget we've had forever. Also allows for the recycling of the base
|
||||
// widget of each window, vs. creating/discarding child widgets for each
|
||||
// MakeWindow call. (Currently only implemented in windows widgets.)
|
||||
#ifdef XP_WIN
|
||||
nsCOMPtr<nsIDocShellTreeItem> containerItem = do_QueryReferent(mContainer);
|
||||
if (mParentWidget && containerItem) {
|
||||
PRInt32 docType;
|
||||
nsWindowType winType;
|
||||
containerItem->GetItemType(&docType);
|
||||
mParentWidget->GetWindowType(winType);
|
||||
if ((winType == eWindowType_toplevel ||
|
||||
winType == eWindowType_dialog ||
|
||||
winType == eWindowType_invisible) &&
|
||||
docType == nsIDocShellTreeItem::typeChrome) {
|
||||
PRBool shouldAttach = ShouldAttachToTopLevel();
|
||||
|
||||
if (shouldAttach) {
|
||||
// If the old view is already attached to our parent, detach
|
||||
DetachFromTopLevelWidget();
|
||||
// Use the parent widget
|
||||
mAttachedToParent = PR_TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult rv;
|
||||
mViewManager = do_CreateInstance(kViewManagerCID, &rv);
|
||||
|
@ -2304,9 +2317,10 @@ DocumentViewerImpl::MakeWindow(const nsSize& aSize, nsIView* aContainerView)
|
|||
initDataPtr = nsnull;
|
||||
}
|
||||
|
||||
if (mAttachedToParent) {
|
||||
if (shouldAttach) {
|
||||
// Reuse the top level parent widget.
|
||||
rv = view->AttachToTopLevelWidget(mParentWidget);
|
||||
mAttachedToParent = PR_TRUE;
|
||||
}
|
||||
else if (!aContainerView && mParentWidget) {
|
||||
rv = view->CreateWidgetForParent(mParentWidget, initDataPtr,
|
||||
|
@ -4029,6 +4043,37 @@ DocumentViewerImpl::SetIsPrintingInDocShellTree(nsIDocShellTreeNode* aParentNode
|
|||
}
|
||||
#endif // NS_PRINTING
|
||||
|
||||
PRBool
|
||||
DocumentViewerImpl::ShouldAttachToTopLevel()
|
||||
{
|
||||
if (!mParentWidget)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> containerItem = do_QueryReferent(mContainer);
|
||||
if (!containerItem)
|
||||
return PR_FALSE;
|
||||
|
||||
// We always attach when using puppet widgets
|
||||
if (nsIWidget::UsePuppetWidgets())
|
||||
return PR_TRUE;
|
||||
|
||||
#ifdef XP_WIN
|
||||
// On windows, in the parent process we also attach, but just to
|
||||
// chrome items
|
||||
PRInt32 docType;
|
||||
nsWindowType winType;
|
||||
containerItem->GetItemType(&docType);
|
||||
mParentWidget->GetWindowType(winType);
|
||||
if ((winType == eWindowType_toplevel ||
|
||||
winType == eWindowType_dialog ||
|
||||
winType == eWindowType_invisible) &&
|
||||
docType == nsIDocShellTreeItem::typeChrome)
|
||||
return PR_TRUE;
|
||||
#endif
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
// XXX this always returns PR_FALSE for subdocuments
|
||||
PRBool
|
||||
|
|
|
@ -854,7 +854,8 @@ nsresult nsIView::AttachToTopLevelWidget(nsIWidget* aWidget)
|
|||
|
||||
// Note, the previous device context will be released. Detaching
|
||||
// will not restore the old one.
|
||||
nsresult rv = aWidget->AttachViewToTopLevel(::AttachedHandleEvent, dx);
|
||||
nsresult rv = aWidget->AttachViewToTopLevel(
|
||||
nsIWidget::UsePuppetWidgets() ? ::HandleEvent : ::AttachedHandleEvent, dx);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
|
|
|
@ -1330,7 +1330,6 @@ class nsIWidget : public nsISupports {
|
|||
PRBool aIsHorizontal,
|
||||
PRInt32 &aOverriddenDelta) = 0;
|
||||
|
||||
#ifdef MOZ_IPC
|
||||
/**
|
||||
* Return true if this process shouldn't use platform widgets, and
|
||||
* so should use PuppetWidgets instead. If this returns true, the
|
||||
|
@ -1339,8 +1338,15 @@ class nsIWidget : public nsISupports {
|
|||
*/
|
||||
static bool
|
||||
UsePuppetWidgets()
|
||||
{ return XRE_GetProcessType() == GeckoProcessType_Content; }
|
||||
{
|
||||
#ifdef MOZ_IPC
|
||||
return XRE_GetProcessType() == GeckoProcessType_Content;
|
||||
#else
|
||||
return PR_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MOZ_IPC
|
||||
/**
|
||||
* Allocate and return a "puppet widget" that doesn't directly
|
||||
* correlate to a platform widget; platform events and data must
|
||||
|
|
|
@ -276,8 +276,13 @@ PuppetWidget::DispatchEvent(nsGUIEvent* event, nsEventStatus& aStatus)
|
|||
nsCAutoString("PuppetWidget"), nsnull);
|
||||
#endif
|
||||
|
||||
NS_ABORT_IF_FALSE(!mChild || mChild->mWindowType == eWindowType_popup,
|
||||
"Unexpected event dispatch!");
|
||||
|
||||
aStatus = nsEventStatus_eIgnore;
|
||||
if (mEventCallback) {
|
||||
|
||||
NS_ABORT_IF_FALSE(mViewCallback, "No view callback!");
|
||||
|
||||
if (event->message == NS_COMPOSITION_START) {
|
||||
mIMEComposing = PR_TRUE;
|
||||
}
|
||||
|
@ -298,15 +303,11 @@ PuppetWidget::DispatchEvent(nsGUIEvent* event, nsEventStatus& aStatus)
|
|||
return NS_OK;
|
||||
break;
|
||||
}
|
||||
aStatus = (*mEventCallback)(event);
|
||||
aStatus = (*mViewCallback)(event);
|
||||
|
||||
if (event->message == NS_COMPOSITION_END) {
|
||||
mIMEComposing = PR_FALSE;
|
||||
}
|
||||
} else if (mChild) {
|
||||
event->widget = mChild;
|
||||
mChild->DispatchEvent(event, aStatus);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -301,8 +301,9 @@ nsBaseWidget::AttachViewToTopLevel(EVENT_CALLBACK aViewEventFunction,
|
|||
{
|
||||
NS_ASSERTION((mWindowType == eWindowType_toplevel ||
|
||||
mWindowType == eWindowType_dialog ||
|
||||
mWindowType == eWindowType_invisible),
|
||||
"Can't attach to child?");
|
||||
mWindowType == eWindowType_invisible ||
|
||||
mWindowType == eWindowType_child),
|
||||
"Can't attach to window of that type");
|
||||
|
||||
mViewCallback = aViewEventFunction;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче