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 "nsIObserverService.h"
#include "nsIObserver.h" #include "nsIObserver.h"
#include "nsIDocShell.h" // for reflow observation #include "nsIDocShell.h" // for reflow observation
#include "nsIBaseWindow.h"
#include "nsLayoutErrors.h" #include "nsLayoutErrors.h"
#include "nsLayoutUtils.h" #include "nsLayoutUtils.h"
#include "nsCSSRendering.h" #include "nsCSSRendering.h"
@ -1221,6 +1222,7 @@ public:
nsEvent* aEvent, nsEvent* aEvent,
nsEventStatus* aStatus); nsEventStatus* aStatus);
NS_IMETHOD ResizeReflow(nsIView *aView, nscoord aWidth, nscoord aHeight); NS_IMETHOD ResizeReflow(nsIView *aView, nscoord aWidth, nscoord aHeight);
NS_IMETHOD_(PRBool) IsVisible();
// caret handling // caret handling
NS_IMETHOD GetCaret(nsICaret **aOutCaret); NS_IMETHOD GetCaret(nsICaret **aOutCaret);
@ -6034,6 +6036,18 @@ PresShell::ResizeReflow(nsIView *aView, nscoord aWidth, nscoord aHeight)
return ResizeReflow(aWidth, 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 nsresult
PresShell::GetAgentStyleSheets(nsCOMArray<nsIStyleSheet>& aSheets) PresShell::GetAgentStyleSheets(nsCOMArray<nsIStyleSheet>& aSheets)
{ {

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

@ -126,6 +126,7 @@
#include "nsIObserverService.h" #include "nsIObserverService.h"
#include "nsIObserver.h" #include "nsIObserver.h"
#include "nsIDocShell.h" // for reflow observation #include "nsIDocShell.h" // for reflow observation
#include "nsIBaseWindow.h"
#include "nsLayoutErrors.h" #include "nsLayoutErrors.h"
#include "nsLayoutUtils.h" #include "nsLayoutUtils.h"
#include "nsCSSRendering.h" #include "nsCSSRendering.h"
@ -1221,6 +1222,7 @@ public:
nsEvent* aEvent, nsEvent* aEvent,
nsEventStatus* aStatus); nsEventStatus* aStatus);
NS_IMETHOD ResizeReflow(nsIView *aView, nscoord aWidth, nscoord aHeight); NS_IMETHOD ResizeReflow(nsIView *aView, nscoord aWidth, nscoord aHeight);
NS_IMETHOD_(PRBool) IsVisible();
// caret handling // caret handling
NS_IMETHOD GetCaret(nsICaret **aOutCaret); NS_IMETHOD GetCaret(nsICaret **aOutCaret);
@ -6034,6 +6036,18 @@ PresShell::ResizeReflow(nsIView *aView, nscoord aWidth, nscoord aHeight)
return ResizeReflow(aWidth, 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 nsresult
PresShell::GetAgentStyleSheets(nsCOMArray<nsIStyleSheet>& aSheets) PresShell::GetAgentStyleSheets(nsCOMArray<nsIStyleSheet>& aSheets)
{ {

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

@ -46,8 +46,8 @@ struct nsRect;
struct nsGUIEvent; struct nsGUIEvent;
#define NS_IVIEWOBSERVER_IID \ #define NS_IVIEWOBSERVER_IID \
{ 0x6a1529e0, 0x3d2c, 0x11d2, \ { 0x0f4bc34a, 0xc93b, 0x4699, \
{ 0xa8, 0x32, 0x00, 0x40, 0x95, 0x9a, 0x28, 0xc9 } } { 0xb6, 0xc2, 0xb3, 0xca, 0x9e, 0xe4, 0x6c, 0x95 } }
class nsIViewObserver : public nsISupports class nsIViewObserver : public nsISupports
{ {
@ -85,6 +85,12 @@ public:
* @return error status * @return error status
*/ */
NS_IMETHOD ResizeReflow(nsIView * aView, nscoord aWidth, nscoord aHeight) = 0; 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 #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 void
nsViewManager::PostInvalidateEvent() nsViewManager::PostInvalidateEvent()
{ {
@ -438,6 +456,7 @@ PRUint32 nsViewManager::gLastUserEventTime = 0;
nsViewManager::nsViewManager() nsViewManager::nsViewManager()
: mMouseLocation(NSCOORD_NONE, NSCOORD_NONE) : mMouseLocation(NSCOORD_NONE, NSCOORD_NONE)
, mDelayedResize(NSCOORD_NONE, NSCOORD_NONE)
{ {
if (gViewManagers == nsnull) { if (gViewManagers == nsnull) {
NS_ASSERTION(mVMCount == 0, "View Manager count is incorrect"); 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) NS_IMETHODIMP nsViewManager::GetWindowDimensions(nscoord *aWidth, nscoord *aHeight)
{ {
if (nsnull != mRootView) { if (nsnull != mRootView) {
if (mDelayedResize == nsSize(NSCOORD_NONE, NSCOORD_NONE)) {
nsRect dim; nsRect dim;
mRootView->GetDimensions(dim); mRootView->GetDimensions(dim);
*aWidth = dim.width; *aWidth = dim.width;
*aHeight = dim.height; *aHeight = dim.height;
} else {
*aWidth = mDelayedResize.width;
*aHeight = mDelayedResize.height;
}
} }
else else
{ {
@ -622,18 +646,14 @@ NS_IMETHODIMP nsViewManager::GetWindowDimensions(nscoord *aWidth, nscoord *aHeig
NS_IMETHODIMP nsViewManager::SetWindowDimensions(nscoord aWidth, nscoord aHeight) NS_IMETHODIMP nsViewManager::SetWindowDimensions(nscoord aWidth, nscoord aHeight)
{ {
// Resize the root view if (mRootView) {
if (nsnull != mRootView) { if (IsViewVisible(mRootView)) {
nsRect dim(0, 0, aWidth, aHeight); mDelayedResize.SizeTo(NSCOORD_NONE, NSCOORD_NONE);
// Don't resize the widget. It is already being set elsewhere. DoSetWindowDimensions(aWidth, aHeight);
mRootView->SetDimensions(dim, PR_TRUE, PR_FALSE); } 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; return NS_OK;
} }
@ -1811,6 +1831,7 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus *aS
case NS_PAINT: case NS_PAINT:
{ {
nsPaintEvent *event = NS_STATIC_CAST(nsPaintEvent*, aEvent);
nsView *view = nsView::GetViewFor(aEvent->widget); nsView *view = nsView::GetViewFor(aEvent->widget);
if (!view || !mContext) 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 // The rect is in device units, and it's in the coordinate space of its
// associated window. // associated window.
nsCOMPtr<nsIRegion> region = ((nsPaintEvent*)aEvent)->region; nsCOMPtr<nsIRegion> region = event->region;
if (!region) { if (!region) {
if (NS_FAILED(CreateRegion(getter_AddRefs(region)))) if (NS_FAILED(CreateRegion(getter_AddRefs(region))))
break; break;
const nsRect& damrect = *((nsPaintEvent*)aEvent)->rect; const nsRect& damrect = *event->rect;
region->SetTo(damrect.x, damrect.y, damrect.width, damrect.height); 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 // Refresh the view
if (mRefreshEnabled) { 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); NS_VMREFRESH_DOUBLE_BUFFER);
}
} else { } else {
// since we got an NS_PAINT event, we need to // since we got an NS_PAINT event, we need to
// draw something so we don't get blank areas. // draw something so we don't get blank areas.

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

@ -351,6 +351,19 @@ private:
*/ */
void GetMaxWidgetBounds(nsRect& aMaxWidgetBounds) const; 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 public: // NOT in nsIViewManager, so private to the view module
nsView* GetRootView() const { return mRootView; } nsView* GetRootView() const { return mRootView; }
nsView* GetMouseEventGrabber() const; nsView* GetMouseEventGrabber() const;
@ -391,6 +404,11 @@ private:
nsIScrollableView *mRootScrollable; nsIScrollableView *mRootScrollable;
nscolor mDefaultBackgroundColor; nscolor mDefaultBackgroundColor;
nsPoint mMouseLocation; // device units, relative to mRootView 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; nsCOMPtr<nsIBlender> mBlender;
nsISupportsArray *mCompositeListeners; nsISupportsArray *mCompositeListeners;
nsCOMPtr<nsIFactory> mRegionFactory; nsCOMPtr<nsIFactory> mRegionFactory;