Don't do resize reflows for view managers that aren't visible. (Improve window resizing and find toolbar performance when multiple tabs are open.) b=227361 r+sr=roc

This commit is contained in:
dbaron%dbaron.org 2004-10-13 22:37:32 +00:00
Родитель 279d8c6aef
Коммит 0bfc91bf4e
5 изменённых файлов: 107 добавлений и 21 удалений

Просмотреть файл

@ -126,6 +126,7 @@
#include "nsIObserverService.h"
#include "nsIObserver.h"
#include "nsIDocShell.h" // for reflow observation
#include "nsIBaseWindow.h"
#include "nsLayoutErrors.h"
#include "nsLayoutUtils.h"
#include "nsCSSRendering.h"
@ -1221,6 +1222,7 @@ public:
nsEvent* aEvent,
nsEventStatus* aStatus);
NS_IMETHOD ResizeReflow(nsIView *aView, nscoord aWidth, nscoord aHeight);
NS_IMETHOD_(PRBool) IsVisible();
// caret handling
NS_IMETHOD GetCaret(nsICaret **aOutCaret);
@ -6034,6 +6036,18 @@ PresShell::ResizeReflow(nsIView *aView, nscoord aWidth, nscoord aHeight)
return ResizeReflow(aWidth, aHeight);
}
NS_IMETHODIMP_(PRBool)
PresShell::IsVisible()
{
nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
nsCOMPtr<nsIBaseWindow> bw = do_QueryInterface(container);
if (!bw)
return PR_FALSE;
PRBool res = PR_TRUE;
bw->GetVisibility(&res);
return res;
}
nsresult
PresShell::GetAgentStyleSheets(nsCOMArray<nsIStyleSheet>& aSheets)
{

Просмотреть файл

@ -126,6 +126,7 @@
#include "nsIObserverService.h"
#include "nsIObserver.h"
#include "nsIDocShell.h" // for reflow observation
#include "nsIBaseWindow.h"
#include "nsLayoutErrors.h"
#include "nsLayoutUtils.h"
#include "nsCSSRendering.h"
@ -1221,6 +1222,7 @@ public:
nsEvent* aEvent,
nsEventStatus* aStatus);
NS_IMETHOD ResizeReflow(nsIView *aView, nscoord aWidth, nscoord aHeight);
NS_IMETHOD_(PRBool) IsVisible();
// caret handling
NS_IMETHOD GetCaret(nsICaret **aOutCaret);
@ -6034,6 +6036,18 @@ PresShell::ResizeReflow(nsIView *aView, nscoord aWidth, nscoord aHeight)
return ResizeReflow(aWidth, aHeight);
}
NS_IMETHODIMP_(PRBool)
PresShell::IsVisible()
{
nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
nsCOMPtr<nsIBaseWindow> bw = do_QueryInterface(container);
if (!bw)
return PR_FALSE;
PRBool res = PR_TRUE;
bw->GetVisibility(&res);
return res;
}
nsresult
PresShell::GetAgentStyleSheets(nsCOMArray<nsIStyleSheet>& aSheets)
{

Просмотреть файл

@ -46,8 +46,8 @@ struct nsRect;
struct nsGUIEvent;
#define NS_IVIEWOBSERVER_IID \
{ 0x6a1529e0, 0x3d2c, 0x11d2, \
{ 0xa8, 0x32, 0x00, 0x40, 0x95, 0x9a, 0x28, 0xc9 } }
{ 0x0f4bc34a, 0xc93b, 0x4699, \
{ 0xb6, 0xc2, 0xb3, 0xca, 0x9e, 0xe4, 0x6c, 0x95 } }
class nsIViewObserver : public nsISupports
{
@ -85,6 +85,12 @@ public:
* @return error status
*/
NS_IMETHOD ResizeReflow(nsIView * aView, nscoord aWidth, nscoord aHeight) = 0;
/**
* Hack to find out if the view observer is itself visible, in lieu
* of having the view trees linked.
*/
NS_IMETHOD_(PRBool) IsVisible();
};
#endif

Просмотреть файл

@ -412,6 +412,24 @@ static PRInt32 CompareZIndex(PRInt32 aZIndex1, PRBool aTopMost1, PRBool aIsAuto1
}
}
static PRBool IsViewVisible(nsView *aView)
{
for (nsIView *view = aView; view; view = view->GetParent()) {
// We don't check widget visibility here because in the future (with
// the better approach to this that's in attachment 160801 on bug
// 227361), callers of the equivalent to this function should be able
// to rely on being notified when the result of this function changes.
if (view->GetVisibility() == nsViewVisibility_kHide)
return PR_FALSE;
}
// Find out if the root view is visible by asking the view observer
// (this won't be needed anymore if we link view trees across chrome /
// content boundaries in DocumentViewerImpl::MakeWindow).
nsCOMPtr<nsIViewObserver> vo;
aView->GetViewManager()->GetViewObserver(*getter_AddRefs(vo));
return vo->IsVisible();
}
void
nsViewManager::PostInvalidateEvent()
{
@ -438,6 +456,7 @@ PRUint32 nsViewManager::gLastUserEventTime = 0;
nsViewManager::nsViewManager()
: mMouseLocation(NSCOORD_NONE, NSCOORD_NONE)
, mDelayedResize(NSCOORD_NONE, NSCOORD_NONE)
{
if (gViewManagers == nsnull) {
NS_ASSERTION(mVMCount == 0, "View Manager count is incorrect");
@ -607,10 +626,15 @@ NS_IMETHODIMP nsViewManager::SetRootView(nsIView *aView)
NS_IMETHODIMP nsViewManager::GetWindowDimensions(nscoord *aWidth, nscoord *aHeight)
{
if (nsnull != mRootView) {
if (mDelayedResize == nsSize(NSCOORD_NONE, NSCOORD_NONE)) {
nsRect dim;
mRootView->GetDimensions(dim);
*aWidth = dim.width;
*aHeight = dim.height;
} else {
*aWidth = mDelayedResize.width;
*aHeight = mDelayedResize.height;
}
}
else
{
@ -622,18 +646,14 @@ NS_IMETHODIMP nsViewManager::GetWindowDimensions(nscoord *aWidth, nscoord *aHeig
NS_IMETHODIMP nsViewManager::SetWindowDimensions(nscoord aWidth, nscoord aHeight)
{
// Resize the root view
if (nsnull != mRootView) {
nsRect dim(0, 0, aWidth, aHeight);
// Don't resize the widget. It is already being set elsewhere.
mRootView->SetDimensions(dim, PR_TRUE, PR_FALSE);
if (mRootView) {
if (IsViewVisible(mRootView)) {
mDelayedResize.SizeTo(NSCOORD_NONE, NSCOORD_NONE);
DoSetWindowDimensions(aWidth, aHeight);
} else {
mDelayedResize.SizeTo(aWidth, aHeight);
}
}
//printf("new dims: %d %d\n", aWidth, aHeight);
// Inform the presentation shell that we've been resized
if (nsnull != mObserver)
mObserver->ResizeReflow(mRootView, aWidth, aHeight);
//printf("reflow done\n");
return NS_OK;
}
@ -1811,6 +1831,7 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus *aS
case NS_PAINT:
{
nsPaintEvent *event = NS_STATIC_CAST(nsPaintEvent*, aEvent);
nsView *view = nsView::GetViewFor(aEvent->widget);
if (!view || !mContext)
@ -1820,12 +1841,12 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus *aS
// The rect is in device units, and it's in the coordinate space of its
// associated window.
nsCOMPtr<nsIRegion> region = ((nsPaintEvent*)aEvent)->region;
nsCOMPtr<nsIRegion> region = event->region;
if (!region) {
if (NS_FAILED(CreateRegion(getter_AddRefs(region))))
break;
const nsRect& damrect = *((nsPaintEvent*)aEvent)->rect;
const nsRect& damrect = *event->rect;
region->SetTo(damrect.x, damrect.y, damrect.width, damrect.height);
}
@ -1834,8 +1855,21 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus *aS
// Refresh the view
if (mRefreshEnabled) {
Refresh(view, ((nsPaintEvent*)aEvent)->renderingContext, region,
// If an ancestor widget was hidden and then shown, we could
// have a delayed resize to handle.
if (view == mRootView &&
mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) &&
IsViewVisible(view)) {
DoSetWindowDimensions(mDelayedResize.width, mDelayedResize.height);
mDelayedResize.SizeTo(NSCOORD_NONE, NSCOORD_NONE);
// Paint later.
UpdateView(view, NS_VMREFRESH_NO_SYNC);
} else {
NS_ASSERTION(IsViewVisible(view), "painting an invisible view");
Refresh(view, event->renderingContext, region,
NS_VMREFRESH_DOUBLE_BUFFER);
}
} else {
// since we got an NS_PAINT event, we need to
// draw something so we don't get blank areas.

Просмотреть файл

@ -351,6 +351,19 @@ private:
*/
void GetMaxWidgetBounds(nsRect& aMaxWidgetBounds) const;
void DoSetWindowDimensions(nscoord aWidth, nscoord aHeight)
{
nsRect oldDim;
nsRect newDim(0, 0, aWidth, aHeight);
mRootView->GetDimensions(oldDim);
if (oldDim != newDim) {
// Don't resize the widget. It is already being set elsewhere.
mRootView->SetDimensions(newDim, PR_TRUE, PR_FALSE);
if (mObserver)
mObserver->ResizeReflow(mRootView, aWidth, aHeight);
}
}
public: // NOT in nsIViewManager, so private to the view module
nsView* GetRootView() const { return mRootView; }
nsView* GetMouseEventGrabber() const;
@ -391,6 +404,11 @@ private:
nsIScrollableView *mRootScrollable;
nscolor mDefaultBackgroundColor;
nsPoint mMouseLocation; // device units, relative to mRootView
// The size for a resize that we delayed until the root view becomes
// visible again.
nsSize mDelayedResize;
nsCOMPtr<nsIBlender> mBlender;
nsISupportsArray *mCompositeListeners;
nsCOMPtr<nsIFactory> mRegionFactory;