зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
279d8c6aef
Коммит
0bfc91bf4e
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче