2001-10-11 06:57:31 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2012-05-21 15:12:37 +04:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2006-02-09 04:24:30 +03:00
|
|
|
#include "nsAutoPtr.h"
|
1998-04-14 00:24:54 +04:00
|
|
|
#include "nsViewManager.h"
|
|
|
|
#include "nsGfxCIID.h"
|
2013-01-03 17:23:11 +04:00
|
|
|
#include "nsView.h"
|
1999-09-12 07:27:14 +04:00
|
|
|
#include "nsCOMPtr.h"
|
2013-09-25 15:21:18 +04:00
|
|
|
#include "mozilla/MouseEvents.h"
|
2002-08-30 07:32:05 +04:00
|
|
|
#include "nsRegion.h"
|
2005-01-20 06:39:09 +03:00
|
|
|
#include "nsCOMArray.h"
|
2009-07-22 04:45:00 +04:00
|
|
|
#include "nsIPluginWidget.h"
|
2010-07-27 17:38:02 +04:00
|
|
|
#include "nsXULPopupManager.h"
|
2010-08-05 22:39:39 +04:00
|
|
|
#include "nsIPresShell.h"
|
2017-02-10 05:42:27 +03:00
|
|
|
#include "nsIPresShellInlines.h"
|
2010-08-05 22:39:39 +04:00
|
|
|
#include "nsPresContext.h"
|
2011-11-18 11:54:27 +04:00
|
|
|
#include "mozilla/StartupTimeline.h"
|
2013-03-18 18:25:50 +04:00
|
|
|
#include "GeckoProfiler.h"
|
2012-08-13 14:10:10 +04:00
|
|
|
#include "nsRefreshDriver.h"
|
2012-08-13 14:11:33 +04:00
|
|
|
#include "mozilla/Preferences.h"
|
2013-08-14 10:56:21 +04:00
|
|
|
#include "nsContentUtils.h" // for nsAutoScriptBlocker
|
2013-05-14 03:47:02 +04:00
|
|
|
#include "nsLayoutUtils.h"
|
2013-08-20 23:45:30 +04:00
|
|
|
#include "Layers.h"
|
2013-08-22 20:54:05 +04:00
|
|
|
#include "gfxPlatform.h"
|
2014-02-27 06:53:31 +04:00
|
|
|
#include "gfxPrefs.h"
|
2013-10-22 17:27:35 +04:00
|
|
|
#include "nsIDocument.h"
|
2006-02-09 04:24:30 +03:00
|
|
|
|
2001-12-01 17:31:45 +03:00
|
|
|
/**
|
|
|
|
XXX TODO XXX
|
|
|
|
|
|
|
|
DeCOMify newly private methods
|
|
|
|
Optimize view storage
|
|
|
|
*/
|
|
|
|
|
2000-08-23 18:58:22 +04:00
|
|
|
/**
|
2001-10-11 06:57:31 +04:00
|
|
|
A note about platform assumptions:
|
2000-08-23 18:58:22 +04:00
|
|
|
|
2001-10-11 06:57:31 +04:00
|
|
|
We assume that a widget is z-ordered on top of its parent.
|
|
|
|
|
|
|
|
We do NOT assume anything about the relative z-ordering of sibling widgets. Even though
|
|
|
|
we ask for a specific z-order, we don't assume that widget z-ordering actually works.
|
2000-08-23 18:58:22 +04:00
|
|
|
*/
|
|
|
|
|
2013-10-02 07:46:03 +04:00
|
|
|
using namespace mozilla;
|
2013-06-18 11:59:29 +04:00
|
|
|
using namespace mozilla::layers;
|
|
|
|
|
2012-09-28 10:57:33 +04:00
|
|
|
#define NSCOORD_NONE INT32_MIN
|
2004-06-22 08:32:52 +04:00
|
|
|
|
2004-06-25 23:02:37 +04:00
|
|
|
#undef DEBUG_MOUSE_LOCATION
|
|
|
|
|
2000-08-23 18:58:22 +04:00
|
|
|
// Weakly held references to all of the view managers
|
2014-05-09 12:00:48 +04:00
|
|
|
nsTArray<nsViewManager*>* nsViewManager::gViewManagers = nullptr;
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t nsViewManager::gLastUserEventTime = 0;
|
1999-02-25 21:44:45 +03:00
|
|
|
|
2000-08-23 18:58:22 +04:00
|
|
|
nsViewManager::nsViewManager()
|
2017-01-24 19:10:01 +03:00
|
|
|
: mPresShell(nullptr)
|
|
|
|
, mDelayedResize(NSCOORD_NONE, NSCOORD_NONE)
|
|
|
|
, mRootView(nullptr)
|
|
|
|
, mRootViewManager(this)
|
|
|
|
, mRefreshDisableCount(0)
|
|
|
|
, mPainting(false)
|
|
|
|
, mRecursiveRefreshPending(false)
|
|
|
|
, mHasPendingWidgetGeometryChanges(false)
|
2017-04-28 01:50:00 +03:00
|
|
|
, mPrintRelated(false)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
if (gViewManagers == nullptr) {
|
2000-08-24 06:35:00 +04:00
|
|
|
// Create an array to hold a list of view managers
|
2014-05-09 12:00:48 +04:00
|
|
|
gViewManagers = new nsTArray<nsViewManager*>;
|
2000-08-23 18:58:22 +04:00
|
|
|
}
|
2000-08-24 06:35:00 +04:00
|
|
|
|
2000-08-23 18:58:22 +04:00
|
|
|
gViewManagers->AppendElement(this);
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
2000-08-23 18:58:22 +04:00
|
|
|
nsViewManager::~nsViewManager()
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
2004-05-17 20:29:13 +04:00
|
|
|
if (mRootView) {
|
2004-01-29 03:04:58 +03:00
|
|
|
// Destroy any remaining views
|
2004-05-17 20:29:13 +04:00
|
|
|
mRootView->Destroy();
|
2012-07-30 18:20:58 +04:00
|
|
|
mRootView = nullptr;
|
2004-01-29 03:04:58 +03:00
|
|
|
}
|
|
|
|
|
2005-01-07 06:23:34 +03:00
|
|
|
if (!IsRootVM()) {
|
2004-11-22 06:06:14 +03:00
|
|
|
// We have a strong ref to mRootViewManager
|
2005-06-01 19:43:08 +04:00
|
|
|
NS_RELEASE(mRootViewManager);
|
2004-10-30 00:47:25 +04:00
|
|
|
}
|
2001-01-20 07:59:39 +03:00
|
|
|
|
2014-05-09 12:00:48 +04:00
|
|
|
NS_ASSERTION(gViewManagers != nullptr, "About to use null gViewManagers");
|
1998-08-13 01:17:52 +04:00
|
|
|
|
2004-02-04 03:11:59 +03:00
|
|
|
#ifdef DEBUG
|
2011-09-29 10:19:26 +04:00
|
|
|
bool removed =
|
2004-02-04 03:11:59 +03:00
|
|
|
#endif
|
|
|
|
gViewManagers->RemoveElement(this);
|
2014-05-09 12:00:48 +04:00
|
|
|
NS_ASSERTION(removed, "Viewmanager instance was not in the global list of viewmanagers");
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2014-05-09 12:00:48 +04:00
|
|
|
if (gViewManagers->IsEmpty()) {
|
2001-10-11 06:57:31 +04:00
|
|
|
// There aren't any more view managers so
|
|
|
|
// release the global array of view managers
|
|
|
|
delete gViewManagers;
|
2012-07-30 18:20:58 +04:00
|
|
|
gViewManagers = nullptr;
|
2000-08-24 06:35:00 +04:00
|
|
|
}
|
1999-02-25 21:44:45 +03:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
mPresShell = nullptr;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// We don't hold a reference to the presentation context because it
|
|
|
|
// holds a reference to us.
|
2013-01-05 07:13:05 +04:00
|
|
|
nsresult
|
|
|
|
nsViewManager::Init(nsDeviceContext* aContext)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
NS_PRECONDITION(nullptr != aContext, "null ptr");
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
if (nullptr == aContext) {
|
2001-10-11 06:57:31 +04:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
}
|
2012-07-30 18:20:58 +04:00
|
|
|
if (nullptr != mContext) {
|
2001-10-11 06:57:31 +04:00
|
|
|
return NS_ERROR_ALREADY_INITIALIZED;
|
|
|
|
}
|
|
|
|
mContext = aContext;
|
2000-08-23 18:58:22 +04:00
|
|
|
|
2004-05-17 20:29:13 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2004-05-06 07:17:14 +04:00
|
|
|
|
2013-01-05 07:13:05 +04:00
|
|
|
nsView*
|
2004-11-04 18:06:50 +03:00
|
|
|
nsViewManager::CreateView(const nsRect& aBounds,
|
2013-03-20 10:10:25 +04:00
|
|
|
nsView* aParent,
|
2004-11-04 18:06:50 +03:00
|
|
|
nsViewVisibility aVisibilityFlag)
|
|
|
|
{
|
2016-11-29 11:36:29 +03:00
|
|
|
auto *v = new nsView(this, aVisibilityFlag);
|
2013-03-20 10:10:25 +04:00
|
|
|
v->SetParent(aParent);
|
2013-03-20 05:47:47 +04:00
|
|
|
v->SetPosition(aBounds.x, aBounds.y);
|
|
|
|
nsRect dim(0, 0, aBounds.width, aBounds.height);
|
|
|
|
v->SetDimensions(dim, false);
|
2004-11-04 18:06:50 +03:00
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
2013-01-05 07:13:05 +04:00
|
|
|
void
|
|
|
|
nsViewManager::SetRootView(nsView *aView)
|
2004-05-17 20:29:13 +04:00
|
|
|
{
|
2013-01-03 17:23:08 +04:00
|
|
|
NS_PRECONDITION(!aView || aView->GetViewManager() == this,
|
2005-06-01 19:43:08 +04:00
|
|
|
"Unexpected viewmanager on root view");
|
|
|
|
|
2004-05-17 20:29:13 +04:00
|
|
|
// Do NOT destroy the current root view. It's the caller's responsibility
|
|
|
|
// to destroy it
|
2013-01-03 17:23:08 +04:00
|
|
|
mRootView = aView;
|
2004-05-17 20:29:13 +04:00
|
|
|
|
|
|
|
if (mRootView) {
|
2013-01-03 17:23:11 +04:00
|
|
|
nsView* parent = mRootView->GetParent();
|
2004-05-17 20:29:13 +04:00
|
|
|
if (parent) {
|
2005-06-01 19:43:08 +04:00
|
|
|
// Calling InsertChild on |parent| will InvalidateHierarchy() on us, so
|
|
|
|
// no need to set mRootViewManager ourselves here.
|
2012-07-30 18:20:58 +04:00
|
|
|
parent->InsertChild(mRootView, nullptr);
|
2004-10-30 00:47:25 +04:00
|
|
|
} else {
|
2005-06-01 19:43:08 +04:00
|
|
|
InvalidateHierarchy();
|
2004-05-17 20:29:13 +04:00
|
|
|
}
|
|
|
|
|
2013-07-31 01:10:28 +04:00
|
|
|
mRootView->SetZIndex(false, 0);
|
2004-05-17 20:29:13 +04:00
|
|
|
}
|
2004-11-22 06:06:14 +03:00
|
|
|
// Else don't touch mRootViewManager
|
2004-05-17 20:29:13 +04:00
|
|
|
}
|
|
|
|
|
2013-01-05 07:13:05 +04:00
|
|
|
void
|
|
|
|
nsViewManager::GetWindowDimensions(nscoord *aWidth, nscoord *aHeight)
|
2004-05-17 20:29:13 +04:00
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
if (nullptr != mRootView) {
|
2004-10-15 01:51:00 +04:00
|
|
|
if (mDelayedResize == nsSize(NSCOORD_NONE, NSCOORD_NONE)) {
|
2011-05-11 19:49:16 +04:00
|
|
|
nsRect dim = mRootView->GetDimensions();
|
2004-10-15 01:51:00 +04:00
|
|
|
*aWidth = dim.width;
|
|
|
|
*aHeight = dim.height;
|
|
|
|
} else {
|
|
|
|
*aWidth = mDelayedResize.width;
|
|
|
|
*aHeight = mDelayedResize.height;
|
|
|
|
}
|
2004-05-17 20:29:13 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*aWidth = 0;
|
|
|
|
*aHeight = 0;
|
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
2010-06-25 06:01:06 +04:00
|
|
|
void nsViewManager::DoSetWindowDimensions(nscoord aWidth, nscoord aHeight)
|
|
|
|
{
|
2011-05-11 19:49:16 +04:00
|
|
|
nsRect oldDim = mRootView->GetDimensions();
|
2010-06-25 06:01:06 +04:00
|
|
|
nsRect newDim(0, 0, aWidth, aHeight);
|
|
|
|
// We care about resizes even when one dimension is already zero.
|
2011-04-19 07:07:23 +04:00
|
|
|
if (!oldDim.IsEqualEdges(newDim)) {
|
2010-06-25 06:01:06 +04:00
|
|
|
// Don't resize the widget. It is already being set elsewhere.
|
2011-10-17 18:59:28 +04:00
|
|
|
mRootView->SetDimensions(newDim, true, false);
|
2011-11-21 21:53:20 +04:00
|
|
|
if (mPresShell)
|
2016-05-12 03:06:11 +03:00
|
|
|
mPresShell->ResizeReflow(aWidth, aHeight, oldDim.width, oldDim.height);
|
2010-06-25 06:01:06 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-03 10:58:57 +03:00
|
|
|
bool
|
|
|
|
nsViewManager::ShouldDelayResize() const
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mRootView);
|
|
|
|
if (!mRootView->IsEffectivelyVisible() ||
|
2016-05-03 10:58:57 +03:00
|
|
|
!mPresShell || !mPresShell->IsVisible()) {
|
2016-05-03 10:58:57 +03:00
|
|
|
return true;
|
|
|
|
}
|
2016-05-03 10:58:57 +03:00
|
|
|
if (nsRefreshDriver* rd = mPresShell->GetRefreshDriver()) {
|
|
|
|
if (rd->IsResizeSuppressed()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2016-05-03 10:58:57 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-01-05 07:13:05 +04:00
|
|
|
void
|
2016-05-12 03:07:45 +03:00
|
|
|
nsViewManager::SetWindowDimensions(nscoord aWidth, nscoord aHeight, bool aDelayResize)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
2004-10-15 01:51:00 +04:00
|
|
|
if (mRootView) {
|
2016-05-12 03:07:45 +03:00
|
|
|
if (!ShouldDelayResize() && !aDelayResize) {
|
2011-01-29 03:10:46 +03:00
|
|
|
if (mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) &&
|
|
|
|
mDelayedResize != nsSize(aWidth, aHeight)) {
|
|
|
|
// We have a delayed resize; that now obsolete size may already have
|
|
|
|
// been flushed to the PresContext so we need to update the PresContext
|
|
|
|
// with the new size because if the new size is exactly the same as the
|
|
|
|
// root view's current size then DoSetWindowDimensions will not
|
|
|
|
// request a resize reflow (which would correct it). See bug 617076.
|
|
|
|
mDelayedResize = nsSize(aWidth, aHeight);
|
2011-10-17 18:59:28 +04:00
|
|
|
FlushDelayedResize(false);
|
2011-01-29 03:10:46 +03:00
|
|
|
}
|
2004-10-15 01:51:00 +04:00
|
|
|
mDelayedResize.SizeTo(NSCOORD_NONE, NSCOORD_NONE);
|
|
|
|
DoSetWindowDimensions(aWidth, aHeight);
|
|
|
|
} else {
|
|
|
|
mDelayedResize.SizeTo(aWidth, aHeight);
|
2017-02-10 05:42:27 +03:00
|
|
|
if (mPresShell) {
|
|
|
|
mPresShell->SetNeedStyleFlush();
|
|
|
|
mPresShell->SetNeedLayoutFlush();
|
2011-12-15 08:42:15 +04:00
|
|
|
}
|
2004-10-15 01:51:00 +04:00
|
|
|
}
|
2004-05-17 20:29:13 +04:00
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
2013-01-05 07:13:05 +04:00
|
|
|
void
|
|
|
|
nsViewManager::FlushDelayedResize(bool aDoReflow)
|
2008-09-09 17:43:10 +04:00
|
|
|
{
|
|
|
|
if (mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE)) {
|
2010-08-05 22:39:39 +04:00
|
|
|
if (aDoReflow) {
|
|
|
|
DoSetWindowDimensions(mDelayedResize.width, mDelayedResize.height);
|
|
|
|
mDelayedResize.SizeTo(NSCOORD_NONE, NSCOORD_NONE);
|
2015-01-12 02:26:39 +03:00
|
|
|
} else if (mPresShell && !mPresShell->GetIsViewportOverridden()) {
|
2011-11-21 21:53:20 +04:00
|
|
|
nsPresContext* presContext = mPresShell->GetPresContext();
|
2010-08-05 22:39:39 +04:00
|
|
|
if (presContext) {
|
|
|
|
presContext->SetVisibleArea(nsRect(nsPoint(0, 0), mDelayedResize));
|
|
|
|
}
|
|
|
|
}
|
2008-09-09 17:43:10 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-19 06:23:47 +04:00
|
|
|
// Convert aIn from being relative to and in appunits of aFromView, to being
|
|
|
|
// relative to and in appunits of aToView.
|
|
|
|
static nsRegion ConvertRegionBetweenViews(const nsRegion& aIn,
|
2013-01-03 17:23:11 +04:00
|
|
|
nsView* aFromView,
|
|
|
|
nsView* aToView)
|
2003-03-25 05:58:10 +03:00
|
|
|
{
|
2010-07-19 06:23:47 +04:00
|
|
|
nsRegion out = aIn;
|
|
|
|
out.MoveBy(aFromView->GetOffsetTo(aToView));
|
2015-03-27 00:44:40 +03:00
|
|
|
out = out.ScaleToOtherAppUnitsRoundOut(
|
2013-01-05 07:13:23 +04:00
|
|
|
aFromView->GetViewManager()->AppUnitsPerDevPixel(),
|
|
|
|
aToView->GetViewManager()->AppUnitsPerDevPixel());
|
2010-03-01 11:03:49 +03:00
|
|
|
return out;
|
2003-03-25 05:58:10 +03:00
|
|
|
}
|
|
|
|
|
2013-01-05 07:12:24 +04:00
|
|
|
nsView* nsViewManager::GetDisplayRootFor(nsView* aView)
|
2006-01-26 05:29:17 +03:00
|
|
|
{
|
2013-01-03 17:23:11 +04:00
|
|
|
nsView *displayRoot = aView;
|
2006-01-26 05:29:17 +03:00
|
|
|
for (;;) {
|
2013-01-03 17:23:11 +04:00
|
|
|
nsView *displayParent = displayRoot->GetParent();
|
2006-01-26 05:29:17 +03:00
|
|
|
if (!displayParent)
|
|
|
|
return displayRoot;
|
|
|
|
|
|
|
|
if (displayRoot->GetFloating() && !displayParent->GetFloating())
|
|
|
|
return displayRoot;
|
2011-05-30 07:15:00 +04:00
|
|
|
|
|
|
|
// If we have a combobox dropdown popup within a panel popup, both the view
|
|
|
|
// for the dropdown popup and its parent will be floating, so we need to
|
|
|
|
// distinguish this situation. We do this by looking for a widget. Any view
|
|
|
|
// with a widget is a display root, except for plugins.
|
|
|
|
nsIWidget* widget = displayRoot->GetWidget();
|
2014-03-19 20:48:08 +04:00
|
|
|
if (widget && widget->WindowType() == eWindowType_popup) {
|
|
|
|
NS_ASSERTION(displayRoot->GetFloating() && displayParent->GetFloating(),
|
|
|
|
"this should only happen with floating views that have floating parents");
|
|
|
|
return displayRoot;
|
2011-05-30 07:15:00 +04:00
|
|
|
}
|
|
|
|
|
2006-01-26 05:29:17 +03:00
|
|
|
displayRoot = displayParent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-10-23 05:35:50 +04:00
|
|
|
/**
|
|
|
|
aRegion is given in device coordinates!!
|
2010-03-01 11:03:49 +03:00
|
|
|
aContext may be null, in which case layers should be used for
|
|
|
|
rendering.
|
2001-10-23 05:35:50 +04:00
|
|
|
*/
|
2015-12-03 08:45:41 +03:00
|
|
|
void nsViewManager::Refresh(nsView* aView, const LayoutDeviceIntRegion& aRegion)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
2010-07-19 06:23:47 +04:00
|
|
|
NS_ASSERTION(aView->GetViewManager() == this, "wrong view manager");
|
|
|
|
|
2013-10-16 17:18:42 +04:00
|
|
|
if (mPresShell && mPresShell->IsNeverPainting()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-05-14 04:40:17 +04:00
|
|
|
// damageRegion is the damaged area, in twips, relative to the view origin
|
2010-07-19 06:23:47 +04:00
|
|
|
nsRegion damageRegion = aRegion.ToAppUnits(AppUnitsPerDevPixel());
|
2015-12-03 08:45:41 +03:00
|
|
|
|
2010-03-01 11:03:49 +03:00
|
|
|
// move region from widget coordinates into view coordinates
|
2010-07-19 06:23:47 +04:00
|
|
|
damageRegion.MoveBy(-aView->ViewToWidgetOffset());
|
2003-03-25 05:58:10 +03:00
|
|
|
|
|
|
|
if (damageRegion.IsEmpty()) {
|
|
|
|
#ifdef DEBUG_roc
|
2011-05-11 19:49:16 +04:00
|
|
|
nsRect viewRect = aView->GetDimensions();
|
2003-03-25 05:58:10 +03:00
|
|
|
nsRect damageRect = damageRegion.GetBounds();
|
2013-11-24 02:44:18 +04:00
|
|
|
printf_stderr("XXX Damage rectangle (%d,%d,%d,%d) does not intersect the widget's view (%d,%d,%d,%d)!\n",
|
2003-03-25 05:58:10 +03:00
|
|
|
damageRect.x, damageRect.y, damageRect.width, damageRect.height,
|
|
|
|
viewRect.x, viewRect.y, viewRect.width, viewRect.height);
|
|
|
|
#endif
|
|
|
|
return;
|
|
|
|
}
|
2012-09-12 01:21:46 +04:00
|
|
|
|
|
|
|
nsIWidget *widget = aView->GetWidget();
|
|
|
|
if (!widget) {
|
|
|
|
return;
|
|
|
|
}
|
2012-08-21 06:40:45 +04:00
|
|
|
|
2004-10-30 00:47:25 +04:00
|
|
|
NS_ASSERTION(!IsPainting(), "recursive painting not permitted");
|
|
|
|
if (IsPainting()) {
|
2011-10-17 18:59:28 +04:00
|
|
|
RootViewManager()->mRecursiveRefreshPending = true;
|
2001-10-11 06:57:31 +04:00
|
|
|
return;
|
|
|
|
}
|
1998-08-20 00:56:52 +04:00
|
|
|
|
2008-03-15 02:08:57 +03:00
|
|
|
{
|
2009-11-16 01:48:18 +03:00
|
|
|
nsAutoScriptBlocker scriptBlocker;
|
2011-10-17 18:59:28 +04:00
|
|
|
SetPainting(true);
|
2008-03-15 02:08:57 +03:00
|
|
|
|
2012-01-28 07:36:23 +04:00
|
|
|
NS_ASSERTION(GetDisplayRootFor(aView) == aView,
|
|
|
|
"Widgets that we paint must all be display roots");
|
|
|
|
|
|
|
|
if (mPresShell) {
|
2013-05-14 03:47:02 +04:00
|
|
|
#ifdef MOZ_DUMP_PAINTING
|
|
|
|
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
|
2013-11-24 02:44:18 +04:00
|
|
|
printf_stderr("--COMPOSITE-- %p\n", mPresShell);
|
2013-05-14 03:47:02 +04:00
|
|
|
}
|
2012-08-13 14:10:10 +04:00
|
|
|
#endif
|
2013-06-18 11:59:29 +04:00
|
|
|
uint32_t paintFlags = nsIPresShell::PAINT_COMPOSITE;
|
|
|
|
LayerManager *manager = widget->GetLayerManager();
|
|
|
|
if (!manager->NeedsWidgetInvalidation()) {
|
|
|
|
manager->FlushRendering();
|
|
|
|
} else {
|
|
|
|
mPresShell->Paint(aView, damageRegion,
|
|
|
|
paintFlags);
|
|
|
|
}
|
2013-05-14 03:47:02 +04:00
|
|
|
#ifdef MOZ_DUMP_PAINTING
|
|
|
|
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
|
2013-11-24 02:44:18 +04:00
|
|
|
printf_stderr("--ENDCOMPOSITE--\n");
|
2013-05-14 03:47:02 +04:00
|
|
|
}
|
2012-08-13 14:10:10 +04:00
|
|
|
#endif
|
2012-01-28 07:36:23 +04:00
|
|
|
mozilla::StartupTimeline::RecordOnce(mozilla::StartupTimeline::FIRST_PAINT);
|
|
|
|
}
|
2001-10-11 06:57:31 +04:00
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
SetPainting(false);
|
2008-03-15 02:08:57 +03:00
|
|
|
}
|
1999-10-15 08:29:30 +04:00
|
|
|
|
2004-10-30 00:47:25 +04:00
|
|
|
if (RootViewManager()->mRecursiveRefreshPending) {
|
2011-10-17 18:59:28 +04:00
|
|
|
RootViewManager()->mRecursiveRefreshPending = false;
|
2011-12-24 07:52:25 +04:00
|
|
|
InvalidateAllViews();
|
2001-10-11 06:57:31 +04:00
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
2014-03-08 13:41:20 +04:00
|
|
|
void
|
|
|
|
nsViewManager::ProcessPendingUpdatesForView(nsView* aView,
|
|
|
|
bool aFlushDirtyRegion)
|
1999-09-03 06:27:40 +04:00
|
|
|
{
|
2004-10-30 00:47:25 +04:00
|
|
|
NS_ASSERTION(IsRootVM(), "Updates will be missed");
|
2014-03-08 13:41:20 +04:00
|
|
|
if (!aView) {
|
2012-07-04 04:14:47 +04:00
|
|
|
return;
|
2001-09-15 21:22:06 +04:00
|
|
|
}
|
2004-10-12 00:35:51 +04:00
|
|
|
|
2014-03-08 13:41:20 +04:00
|
|
|
nsCOMPtr<nsIPresShell> rootShell(mPresShell);
|
2017-02-14 04:44:23 +03:00
|
|
|
AutoTArray<nsCOMPtr<nsIWidget>, 1> widgets;
|
2014-03-08 13:41:20 +04:00
|
|
|
aView->GetViewManager()->ProcessPendingUpdatesRecurse(aView, widgets);
|
|
|
|
for (uint32_t i = 0; i < widgets.Length(); ++i) {
|
|
|
|
nsView* view = nsView::GetViewFor(widgets[i]);
|
2015-05-04 22:29:19 +03:00
|
|
|
if (view) {
|
|
|
|
if (view->mNeedsWindowPropertiesSync) {
|
|
|
|
view->mNeedsWindowPropertiesSync = false;
|
|
|
|
if (nsViewManager* vm = view->GetViewManager()) {
|
|
|
|
if (nsIPresShell* ps = vm->GetPresShell()) {
|
|
|
|
ps->SyncWindowProperties(view);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
view = nsView::GetViewFor(widgets[i]);
|
2014-03-08 13:41:20 +04:00
|
|
|
if (view) {
|
|
|
|
view->ResetWidgetBounds(false, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (rootShell->GetViewManager() != this) {
|
2016-05-11 06:58:47 +03:00
|
|
|
return; // presentation might have been torn down
|
2014-03-08 13:41:20 +04:00
|
|
|
}
|
|
|
|
if (aFlushDirtyRegion) {
|
|
|
|
nsAutoScriptBlocker scriptBlocker;
|
|
|
|
SetPainting(true);
|
|
|
|
for (uint32_t i = 0; i < widgets.Length(); ++i) {
|
|
|
|
nsIWidget* widget = widgets[i];
|
|
|
|
nsView* view = nsView::GetViewFor(widget);
|
|
|
|
if (view) {
|
|
|
|
view->GetViewManager()->ProcessPendingUpdatesPaint(widget);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SetPainting(false);
|
2013-10-16 17:18:42 +04:00
|
|
|
}
|
2014-03-08 13:41:20 +04:00
|
|
|
}
|
2013-10-16 17:18:42 +04:00
|
|
|
|
2014-03-08 13:41:20 +04:00
|
|
|
void
|
|
|
|
nsViewManager::ProcessPendingUpdatesRecurse(nsView* aView,
|
2017-02-14 04:44:23 +03:00
|
|
|
AutoTArray<nsCOMPtr<nsIWidget>, 1>& aWidgets)
|
2014-03-08 13:41:20 +04:00
|
|
|
{
|
|
|
|
if (mPresShell && mPresShell->IsNeverPainting()) {
|
|
|
|
return;
|
2001-10-11 06:57:31 +04:00
|
|
|
}
|
|
|
|
|
2013-01-03 17:23:11 +04:00
|
|
|
for (nsView* childView = aView->GetFirstChild(); childView;
|
2003-07-03 17:05:57 +04:00
|
|
|
childView = childView->GetNextSibling()) {
|
2014-03-08 13:41:20 +04:00
|
|
|
childView->GetViewManager()->
|
|
|
|
ProcessPendingUpdatesRecurse(childView, aWidgets);
|
2001-10-11 06:57:31 +04:00
|
|
|
}
|
2004-11-03 05:37:21 +03:00
|
|
|
|
2014-03-08 13:41:20 +04:00
|
|
|
nsIWidget* widget = aView->GetWidget();
|
|
|
|
if (widget) {
|
|
|
|
aWidgets.AppendElement(widget);
|
|
|
|
} else {
|
|
|
|
FlushDirtyRegionToWidget(aView);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsViewManager::ProcessPendingUpdatesPaint(nsIWidget* aWidget)
|
|
|
|
{
|
|
|
|
if (aWidget->NeedsPaint()) {
|
|
|
|
// If an ancestor widget was hidden and then shown, we could
|
|
|
|
// have a delayed resize to handle.
|
2016-05-11 06:58:26 +03:00
|
|
|
for (RefPtr<nsViewManager> vm = this; vm;
|
2014-03-08 13:41:20 +04:00
|
|
|
vm = vm->mRootView->GetParent()
|
|
|
|
? vm->mRootView->GetParent()->GetViewManager()
|
|
|
|
: nullptr) {
|
|
|
|
if (vm->mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) &&
|
|
|
|
vm->mRootView->IsEffectivelyVisible() &&
|
|
|
|
vm->mPresShell && vm->mPresShell->IsVisible()) {
|
|
|
|
vm->FlushDelayedResize(true);
|
2013-01-05 07:14:17 +04:00
|
|
|
}
|
2014-03-08 13:41:20 +04:00
|
|
|
}
|
|
|
|
nsView* view = nsView::GetViewFor(aWidget);
|
2015-07-22 04:09:02 +03:00
|
|
|
|
2014-03-08 13:41:20 +04:00
|
|
|
if (!view) {
|
|
|
|
NS_ERROR("FlushDelayedResize destroyed the nsView?");
|
|
|
|
return;
|
|
|
|
}
|
2012-08-13 14:10:11 +04:00
|
|
|
|
2015-07-22 04:09:02 +03:00
|
|
|
nsIWidgetListener* previousListener = aWidget->GetPreviouslyAttachedWidgetListener();
|
|
|
|
|
|
|
|
if (previousListener &&
|
|
|
|
previousListener != view &&
|
|
|
|
view->IsPrimaryFramePaintSuppressed()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-03-08 13:41:20 +04:00
|
|
|
if (mPresShell) {
|
2014-03-07 12:11:08 +04:00
|
|
|
#ifdef MOZ_DUMP_PAINTING
|
2014-03-08 13:41:20 +04:00
|
|
|
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
|
|
|
|
printf_stderr("---- PAINT START ----PresShell(%p), nsView(%p), nsIWidget(%p)\n",
|
|
|
|
mPresShell, view, aWidget);
|
|
|
|
}
|
2014-03-07 12:11:08 +04:00
|
|
|
#endif
|
2014-03-07 22:40:58 +04:00
|
|
|
|
2014-03-08 13:41:20 +04:00
|
|
|
mPresShell->Paint(view, nsRegion(), nsIPresShell::PAINT_LAYERS);
|
|
|
|
view->SetForcedRepaint(false);
|
|
|
|
|
|
|
|
#ifdef MOZ_DUMP_PAINTING
|
|
|
|
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
|
|
|
|
printf_stderr("---- PAINT END ----\n");
|
2014-03-07 22:40:58 +04:00
|
|
|
}
|
2014-03-08 13:41:20 +04:00
|
|
|
#endif
|
2012-08-13 14:10:10 +04:00
|
|
|
}
|
2011-12-24 07:52:23 +04:00
|
|
|
}
|
2014-03-08 13:41:20 +04:00
|
|
|
FlushDirtyRegionToWidget(nsView::GetViewFor(aWidget));
|
2011-12-24 07:52:22 +04:00
|
|
|
}
|
|
|
|
|
2013-01-03 17:23:11 +04:00
|
|
|
void nsViewManager::FlushDirtyRegionToWidget(nsView* aView)
|
2011-12-24 07:52:22 +04:00
|
|
|
{
|
2014-03-02 14:32:35 +04:00
|
|
|
NS_ASSERTION(aView->GetViewManager() == this,
|
|
|
|
"FlushDirtyRegionToWidget called on view we don't own");
|
|
|
|
|
2011-12-24 07:52:22 +04:00
|
|
|
if (!aView->HasNonEmptyDirtyRegion())
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsRegion* dirtyRegion = aView->GetDirtyRegion();
|
2013-01-03 17:23:11 +04:00
|
|
|
nsView* nearestViewWithWidget = aView;
|
2011-12-24 07:52:22 +04:00
|
|
|
while (!nearestViewWithWidget->HasWidget() &&
|
|
|
|
nearestViewWithWidget->GetParent()) {
|
|
|
|
nearestViewWithWidget = nearestViewWithWidget->GetParent();
|
2011-12-24 07:52:23 +04:00
|
|
|
}
|
2011-12-24 07:52:22 +04:00
|
|
|
nsRegion r =
|
|
|
|
ConvertRegionBetweenViews(*dirtyRegion, aView, nearestViewWithWidget);
|
2013-08-22 20:54:05 +04:00
|
|
|
|
2013-01-05 07:13:23 +04:00
|
|
|
nsViewManager* widgetVM = nearestViewWithWidget->GetViewManager();
|
2011-12-24 07:52:25 +04:00
|
|
|
widgetVM->InvalidateWidgetArea(nearestViewWithWidget, r);
|
2011-12-24 07:52:22 +04:00
|
|
|
dirtyRegion->SetEmpty();
|
2011-12-24 07:52:22 +04:00
|
|
|
}
|
|
|
|
|
2013-01-05 07:13:05 +04:00
|
|
|
void
|
|
|
|
nsViewManager::InvalidateView(nsView *aView)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
2001-10-11 06:57:31 +04:00
|
|
|
// Mark the entire view as damaged
|
2013-01-05 07:13:05 +04:00
|
|
|
InvalidateView(aView, aView->GetDimensions());
|
2011-12-24 07:52:23 +04:00
|
|
|
}
|
|
|
|
|
2011-12-24 07:52:22 +04:00
|
|
|
static void
|
2013-01-03 17:23:11 +04:00
|
|
|
AddDirtyRegion(nsView *aView, const nsRegion &aDamagedRegion)
|
2011-12-24 07:52:22 +04:00
|
|
|
{
|
|
|
|
nsRegion* dirtyRegion = aView->GetDirtyRegion();
|
|
|
|
if (!dirtyRegion)
|
|
|
|
return;
|
|
|
|
|
|
|
|
dirtyRegion->Or(*dirtyRegion, aDamagedRegion);
|
|
|
|
dirtyRegion->SimplifyOutward(8);
|
|
|
|
}
|
|
|
|
|
2011-12-24 07:52:23 +04:00
|
|
|
void
|
|
|
|
nsViewManager::PostPendingUpdate()
|
|
|
|
{
|
|
|
|
nsViewManager* rootVM = RootViewManager();
|
2011-12-24 07:52:23 +04:00
|
|
|
rootVM->mHasPendingWidgetGeometryChanges = true;
|
2012-07-04 04:14:47 +04:00
|
|
|
if (rootVM->mPresShell) {
|
2012-07-04 04:20:24 +04:00
|
|
|
rootVM->mPresShell->ScheduleViewManagerFlush();
|
2011-12-24 07:52:23 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-11-03 05:37:21 +03:00
|
|
|
/**
|
|
|
|
* @param aDamagedRegion this region, relative to aWidgetView, is invalidated in
|
|
|
|
* every widget child of aWidgetView, plus aWidgetView's own widget
|
|
|
|
*/
|
|
|
|
void
|
2013-01-03 17:23:11 +04:00
|
|
|
nsViewManager::InvalidateWidgetArea(nsView *aWidgetView,
|
2011-12-24 07:52:25 +04:00
|
|
|
const nsRegion &aDamagedRegion)
|
2000-08-23 18:58:22 +04:00
|
|
|
{
|
2010-07-19 06:23:47 +04:00
|
|
|
NS_ASSERTION(aWidgetView->GetViewManager() == this,
|
2011-12-24 07:52:25 +04:00
|
|
|
"InvalidateWidgetArea called on view we don't own");
|
2011-12-24 07:52:23 +04:00
|
|
|
nsIWidget* widget = aWidgetView->GetWidget();
|
2010-07-19 06:23:47 +04:00
|
|
|
|
2010-06-25 06:01:06 +04:00
|
|
|
#if 0
|
|
|
|
nsRect dbgBounds = aDamagedRegion.GetBounds();
|
2011-12-24 07:52:25 +04:00
|
|
|
printf("InvalidateWidgetArea view:%X (%d) widget:%X region: %d, %d, %d, %d\n",
|
2010-06-25 06:01:06 +04:00
|
|
|
aWidgetView, aWidgetView->IsAttachedToTopLevel(),
|
2011-12-24 07:52:23 +04:00
|
|
|
widget, dbgBounds.x, dbgBounds.y, dbgBounds.width, dbgBounds.height);
|
2010-06-25 06:01:06 +04:00
|
|
|
#endif
|
|
|
|
|
2002-10-18 23:17:35 +04:00
|
|
|
// If the widget is hidden, it don't cover nothing
|
2012-07-19 12:57:50 +04:00
|
|
|
if (widget && !widget->IsVisible()) {
|
|
|
|
return;
|
2002-10-18 23:17:35 +04:00
|
|
|
}
|
2002-06-12 07:22:35 +04:00
|
|
|
|
2011-12-24 07:52:23 +04:00
|
|
|
if (!widget) {
|
2002-10-08 08:18:05 +04:00
|
|
|
// The root view or a scrolling view might not have a widget
|
|
|
|
// (for example, during printing). We get here when we scroll
|
|
|
|
// during printing to show selected options in a listbox, for example.
|
2004-11-03 05:37:21 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-11-05 16:59:33 +03:00
|
|
|
// Update all child widgets with the damage. In the process,
|
|
|
|
// accumulate the union of all the child widget areas, or at least
|
|
|
|
// some subset of that.
|
|
|
|
nsRegion children;
|
2011-12-24 07:52:23 +04:00
|
|
|
if (widget->GetTransparencyMode() != eTransparencyTransparent) {
|
|
|
|
for (nsIWidget* childWidget = widget->GetFirstChild();
|
2009-02-24 19:53:32 +03:00
|
|
|
childWidget;
|
|
|
|
childWidget = childWidget->GetNextSibling()) {
|
2013-01-03 17:23:11 +04:00
|
|
|
nsView* view = nsView::GetViewFor(childWidget);
|
2009-02-24 19:53:32 +03:00
|
|
|
NS_ASSERTION(view != aWidgetView, "will recur infinitely");
|
2014-03-19 20:48:08 +04:00
|
|
|
nsWindowType type = childWidget->WindowType();
|
2012-07-19 12:57:50 +04:00
|
|
|
if (view && childWidget->IsVisible() && type != eWindowType_popup) {
|
2014-11-12 23:59:19 +03:00
|
|
|
NS_ASSERTION(childWidget->IsPlugin(),
|
2010-09-17 22:05:51 +04:00
|
|
|
"Only plugin or popup widgets can be children!");
|
|
|
|
|
|
|
|
// We do not need to invalidate in plugin widgets, but we should
|
|
|
|
// exclude them from the invalidation region IF we're not on
|
|
|
|
// Mac. On Mac we need to draw under plugin widgets, because
|
|
|
|
// plugin widgets are basically invisible
|
|
|
|
#ifndef XP_MACOSX
|
|
|
|
// GetBounds should compensate for chrome on a toplevel widget
|
2016-08-19 02:03:04 +03:00
|
|
|
LayoutDeviceIntRect bounds = childWidget->GetBounds();
|
2010-09-17 22:05:51 +04:00
|
|
|
|
2015-12-03 01:32:55 +03:00
|
|
|
nsTArray<LayoutDeviceIntRect> clipRects;
|
2010-09-17 22:05:51 +04:00
|
|
|
childWidget->GetWindowClipRegion(&clipRects);
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t i = 0; i < clipRects.Length(); ++i) {
|
2015-12-03 01:32:55 +03:00
|
|
|
nsRect rr = LayoutDeviceIntRect::ToAppUnits(
|
|
|
|
clipRects[i] + bounds.TopLeft(), AppUnitsPerDevPixel());
|
2015-04-21 18:04:57 +03:00
|
|
|
children.Or(children, rr - aWidgetView->ViewToWidgetOffset());
|
2010-09-17 22:05:51 +04:00
|
|
|
children.SimplifyInward(20);
|
2009-02-24 19:53:32 +03:00
|
|
|
}
|
2010-09-17 22:05:51 +04:00
|
|
|
#endif
|
2002-06-12 07:22:35 +04:00
|
|
|
}
|
2004-05-23 00:54:40 +04:00
|
|
|
}
|
2001-10-11 06:57:31 +04:00
|
|
|
}
|
2000-08-23 18:58:22 +04:00
|
|
|
|
2004-11-05 16:59:33 +03:00
|
|
|
nsRegion leftOver;
|
2012-05-03 20:33:51 +04:00
|
|
|
leftOver.Sub(aDamagedRegion, children);
|
2004-11-05 16:59:33 +03:00
|
|
|
|
|
|
|
if (!leftOver.IsEmpty()) {
|
2016-01-19 04:20:59 +03:00
|
|
|
for (auto iter = leftOver.RectIter(); !iter.Done(); iter.Next()) {
|
|
|
|
LayoutDeviceIntRect bounds = ViewToWidget(aWidgetView, iter.Get());
|
2011-12-24 07:52:23 +04:00
|
|
|
widget->Invalidate(bounds);
|
2001-10-20 07:09:36 +04:00
|
|
|
}
|
|
|
|
}
|
2000-08-23 18:58:22 +04:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
static bool
|
2010-08-19 05:16:58 +04:00
|
|
|
ShouldIgnoreInvalidation(nsViewManager* aVM)
|
|
|
|
{
|
|
|
|
while (aVM) {
|
2011-11-21 21:53:20 +04:00
|
|
|
nsIPresShell* shell = aVM->GetPresShell();
|
|
|
|
if (!shell || shell->ShouldIgnoreInvalidation()) {
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2010-08-19 05:16:58 +04:00
|
|
|
}
|
2013-01-05 07:12:24 +04:00
|
|
|
nsView* view = aVM->GetRootView()->GetParent();
|
2013-01-05 07:13:23 +04:00
|
|
|
aVM = view ? view->GetViewManager() : nullptr;
|
2010-08-19 05:16:58 +04:00
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2010-08-19 05:16:58 +04:00
|
|
|
}
|
|
|
|
|
2013-01-05 07:13:05 +04:00
|
|
|
void
|
|
|
|
nsViewManager::InvalidateView(nsView *aView, const nsRect &aRect)
|
2010-08-19 05:16:58 +04:00
|
|
|
{
|
|
|
|
// If painting is suppressed in the presshell or an ancestor drop all
|
|
|
|
// invalidates, it will invalidate everything when it unsuppresses.
|
|
|
|
if (ShouldIgnoreInvalidation(this)) {
|
2013-01-05 07:13:05 +04:00
|
|
|
return;
|
2010-08-19 05:16:58 +04:00
|
|
|
}
|
|
|
|
|
2013-01-05 07:13:05 +04:00
|
|
|
InvalidateViewNoSuppression(aView, aRect);
|
2010-08-19 05:16:58 +04:00
|
|
|
}
|
|
|
|
|
2013-01-05 07:13:05 +04:00
|
|
|
void
|
|
|
|
nsViewManager::InvalidateViewNoSuppression(nsView *aView,
|
|
|
|
const nsRect &aRect)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
NS_PRECONDITION(nullptr != aView, "null view");
|
2000-03-15 04:20:07 +03:00
|
|
|
|
2013-01-03 17:23:08 +04:00
|
|
|
NS_ASSERTION(aView->GetViewManager() == this,
|
2011-12-24 07:52:25 +04:00
|
|
|
"InvalidateViewNoSuppression called on view we don't own");
|
2010-07-19 06:23:47 +04:00
|
|
|
|
2007-02-24 18:27:20 +03:00
|
|
|
nsRect damagedRect(aRect);
|
2009-09-09 09:40:02 +04:00
|
|
|
if (damagedRect.IsEmpty()) {
|
2013-01-05 07:13:05 +04:00
|
|
|
return;
|
2000-03-15 04:20:07 +03:00
|
|
|
}
|
|
|
|
|
2013-01-03 17:23:11 +04:00
|
|
|
nsView* displayRoot = GetDisplayRootFor(aView);
|
2013-01-05 07:13:23 +04:00
|
|
|
nsViewManager* displayRootVM = displayRoot->GetViewManager();
|
2008-11-26 01:09:37 +03:00
|
|
|
// Propagate the update to the displayRoot, since iframes, for example,
|
|
|
|
// can overlap each other and be translucent. So we have to possibly
|
|
|
|
// invalidate our rect in each of the widgets we have lying about.
|
2013-01-03 17:23:08 +04:00
|
|
|
damagedRect.MoveBy(aView->GetOffsetTo(displayRoot));
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t rootAPD = displayRootVM->AppUnitsPerDevPixel();
|
|
|
|
int32_t APD = AppUnitsPerDevPixel();
|
2015-03-27 00:44:40 +03:00
|
|
|
damagedRect = damagedRect.ScaleToOtherAppUnitsRoundOut(APD, rootAPD);
|
2011-12-24 07:52:23 +04:00
|
|
|
|
|
|
|
// accumulate this rectangle in the view's dirty region, so we can
|
|
|
|
// process it later.
|
|
|
|
AddDirtyRegion(displayRoot, nsRegion(damagedRect));
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
2013-01-05 07:13:05 +04:00
|
|
|
void
|
|
|
|
nsViewManager::InvalidateAllViews()
|
1999-09-19 04:51:41 +04:00
|
|
|
{
|
2004-10-30 00:47:25 +04:00
|
|
|
if (RootViewManager() != this) {
|
2011-12-24 07:52:25 +04:00
|
|
|
return RootViewManager()->InvalidateAllViews();
|
2004-10-30 00:47:25 +04:00
|
|
|
}
|
|
|
|
|
2011-12-24 07:52:25 +04:00
|
|
|
InvalidateViews(mRootView);
|
1999-09-19 04:51:41 +04:00
|
|
|
}
|
|
|
|
|
2013-01-03 17:23:11 +04:00
|
|
|
void nsViewManager::InvalidateViews(nsView *aView)
|
1999-09-19 04:51:41 +04:00
|
|
|
{
|
2011-12-24 07:52:25 +04:00
|
|
|
// Invalidate this view.
|
|
|
|
InvalidateView(aView);
|
1999-09-19 04:51:41 +04:00
|
|
|
|
2011-12-24 07:52:25 +04:00
|
|
|
// Invalidate all children as well.
|
2013-01-03 17:23:11 +04:00
|
|
|
nsView* childView = aView->GetFirstChild();
|
2012-07-30 18:20:58 +04:00
|
|
|
while (nullptr != childView) {
|
2013-01-05 07:13:23 +04:00
|
|
|
childView->GetViewManager()->InvalidateViews(childView);
|
2001-11-07 07:05:38 +03:00
|
|
|
childView = childView->GetNextSibling();
|
2001-10-11 06:57:31 +04:00
|
|
|
}
|
1999-09-19 04:51:41 +04:00
|
|
|
}
|
|
|
|
|
2013-01-28 23:34:08 +04:00
|
|
|
void nsViewManager::WillPaintWindow(nsIWidget* aWidget)
|
2010-07-27 17:38:02 +04:00
|
|
|
{
|
2016-05-11 06:58:47 +03:00
|
|
|
RefPtr<nsIWidget> widget(aWidget);
|
|
|
|
if (widget) {
|
|
|
|
nsView* view = nsView::GetViewFor(widget);
|
|
|
|
LayerManager* manager = widget->GetLayerManager();
|
2013-06-20 17:01:20 +04:00
|
|
|
if (view &&
|
|
|
|
(view->ForcedRepaint() || !manager->NeedsWidgetInvalidation())) {
|
2015-04-13 19:02:27 +03:00
|
|
|
ProcessPendingUpdates();
|
2012-12-13 01:57:08 +04:00
|
|
|
// Re-get the view pointer here since the ProcessPendingUpdates might have
|
|
|
|
// destroyed it during CallWillPaintOnObservers.
|
2016-05-11 06:58:47 +03:00
|
|
|
view = nsView::GetViewFor(widget);
|
2012-12-13 01:57:08 +04:00
|
|
|
if (view) {
|
|
|
|
view->SetForcedRepaint(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-10 14:25:57 +04:00
|
|
|
nsCOMPtr<nsIPresShell> shell = mPresShell;
|
|
|
|
if (shell) {
|
2013-01-28 23:34:11 +04:00
|
|
|
shell->WillPaintWindow();
|
2012-10-10 14:25:57 +04:00
|
|
|
}
|
2012-08-15 22:52:42 +04:00
|
|
|
}
|
2001-10-11 06:57:31 +04:00
|
|
|
|
2015-12-03 08:45:41 +03:00
|
|
|
bool nsViewManager::PaintWindow(nsIWidget* aWidget,
|
2016-11-15 01:16:52 +03:00
|
|
|
const LayoutDeviceIntRegion& aRegion)
|
2013-01-28 23:34:06 +04:00
|
|
|
{
|
2012-08-15 22:52:42 +04:00
|
|
|
if (!aWidget || !mContext)
|
|
|
|
return false;
|
2010-07-27 17:38:02 +04:00
|
|
|
|
2012-08-15 22:52:42 +04:00
|
|
|
NS_ASSERTION(IsPaintingAllowed(),
|
|
|
|
"shouldn't be receiving paint events while painting is disallowed!");
|
2001-10-11 06:57:31 +04:00
|
|
|
|
2012-08-15 22:52:42 +04:00
|
|
|
// Get the view pointer here since NS_WILL_PAINT might have
|
|
|
|
// destroyed it during CallWillPaintOnObservers (bug 378273).
|
2013-01-03 17:23:11 +04:00
|
|
|
nsView* view = nsView::GetViewFor(aWidget);
|
2012-08-15 22:52:42 +04:00
|
|
|
if (view && !aRegion.IsEmpty()) {
|
2013-01-28 23:34:08 +04:00
|
|
|
Refresh(view, aRegion);
|
2012-08-15 22:52:42 +04:00
|
|
|
}
|
2012-08-13 14:11:33 +04:00
|
|
|
|
2012-08-15 22:52:42 +04:00
|
|
|
return true;
|
|
|
|
}
|
2011-12-24 07:52:24 +04:00
|
|
|
|
2012-08-15 22:52:42 +04:00
|
|
|
void nsViewManager::DidPaintWindow()
|
|
|
|
{
|
2012-10-10 14:25:57 +04:00
|
|
|
nsCOMPtr<nsIPresShell> shell = mPresShell;
|
|
|
|
if (shell) {
|
|
|
|
shell->DidPaintWindow();
|
|
|
|
}
|
2012-08-15 22:52:42 +04:00
|
|
|
}
|
2011-12-24 07:52:24 +04:00
|
|
|
|
2013-01-05 07:13:05 +04:00
|
|
|
void
|
2013-10-02 07:46:03 +04:00
|
|
|
nsViewManager::DispatchEvent(WidgetGUIEvent *aEvent,
|
|
|
|
nsView* aView,
|
|
|
|
nsEventStatus* aStatus)
|
2012-08-15 22:52:42 +04:00
|
|
|
{
|
2014-05-24 01:12:29 +04:00
|
|
|
PROFILER_LABEL("nsViewManager", "DispatchEvent",
|
|
|
|
js::ProfileEntry::Category::EVENTS);
|
2001-10-11 06:57:31 +04:00
|
|
|
|
2013-10-28 13:03:19 +04:00
|
|
|
WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
|
|
|
|
if ((mouseEvent &&
|
2012-08-15 22:52:42 +04:00
|
|
|
// Ignore mouse events that we synthesize.
|
2016-05-12 05:36:41 +03:00
|
|
|
mouseEvent->mReason == WidgetMouseEvent::eReal &&
|
2012-08-15 22:52:42 +04:00
|
|
|
// Ignore mouse exit and enter (we'll get moves if the user
|
|
|
|
// is really moving the mouse) since we get them when we
|
|
|
|
// create and destroy widgets.
|
2015-08-29 02:58:31 +03:00
|
|
|
mouseEvent->mMessage != eMouseExitFromWidget &&
|
2015-08-29 02:58:31 +03:00
|
|
|
mouseEvent->mMessage != eMouseEnterIntoWidget) ||
|
2013-09-24 14:04:16 +04:00
|
|
|
aEvent->HasKeyEventMessage() ||
|
|
|
|
aEvent->HasIMEEventMessage() ||
|
2015-09-08 17:33:38 +03:00
|
|
|
aEvent->mMessage == ePluginInputEvent) {
|
2012-08-15 22:52:42 +04:00
|
|
|
gLastUserEventTime = PR_IntervalToMicroseconds(PR_IntervalNow());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the view whose coordinates system we're in.
|
2013-01-03 17:23:11 +04:00
|
|
|
nsView* view = aView;
|
2013-09-24 14:04:16 +04:00
|
|
|
bool dispatchUsingCoordinates = aEvent->IsUsingCoordinates();
|
2012-08-15 22:52:42 +04:00
|
|
|
if (dispatchUsingCoordinates) {
|
|
|
|
// Will dispatch using coordinates. Pretty bogus but it's consistent
|
|
|
|
// with what presshell does.
|
|
|
|
view = GetDisplayRootFor(view);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the view has no frame, look for a view that does.
|
|
|
|
nsIFrame* frame = view->GetFrame();
|
|
|
|
if (!frame &&
|
2013-09-24 14:04:16 +04:00
|
|
|
(dispatchUsingCoordinates || aEvent->HasKeyEventMessage() ||
|
|
|
|
aEvent->IsIMERelatedEvent() ||
|
|
|
|
aEvent->IsNonRetargetedNativeEventDelivererForPlugin() ||
|
2014-12-11 17:44:07 +03:00
|
|
|
aEvent->HasPluginActivationEventMessage())) {
|
2012-08-15 22:52:42 +04:00
|
|
|
while (view && !view->GetFrame()) {
|
|
|
|
view = view->GetParent();
|
2010-07-16 01:08:08 +04:00
|
|
|
}
|
|
|
|
|
2012-08-15 22:52:42 +04:00
|
|
|
if (view) {
|
|
|
|
frame = view->GetFrame();
|
|
|
|
}
|
|
|
|
}
|
2011-11-21 21:53:20 +04:00
|
|
|
|
2012-08-15 22:52:42 +04:00
|
|
|
if (nullptr != frame) {
|
|
|
|
// Hold a refcount to the presshell. The continued existence of the
|
|
|
|
// presshell will delay deletion of this view hierarchy should the event
|
|
|
|
// want to cause its destruction in, say, some JavaScript event handler.
|
|
|
|
nsCOMPtr<nsIPresShell> shell = view->GetViewManager()->GetPresShell();
|
|
|
|
if (shell) {
|
2013-01-05 07:13:05 +04:00
|
|
|
shell->HandleEvent(frame, aEvent, false, aStatus);
|
|
|
|
return;
|
2001-10-11 06:57:31 +04:00
|
|
|
}
|
2012-08-15 22:52:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
*aStatus = nsEventStatus_eIgnore;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
2002-09-12 07:59:15 +04:00
|
|
|
// Recursively reparent widgets if necessary
|
|
|
|
|
2013-01-03 17:23:11 +04:00
|
|
|
void nsViewManager::ReparentChildWidgets(nsView* aView, nsIWidget *aNewWidget)
|
2002-09-12 07:59:15 +04:00
|
|
|
{
|
2010-09-18 15:28:50 +04:00
|
|
|
NS_PRECONDITION(aNewWidget, "");
|
|
|
|
|
2003-07-03 17:05:57 +04:00
|
|
|
if (aView->HasWidget()) {
|
2002-09-12 07:59:15 +04:00
|
|
|
// Check to see if the parent widget is the
|
|
|
|
// same as the new parent. If not then reparent
|
|
|
|
// the widget, otherwise there is nothing more
|
|
|
|
// to do for the view and its descendants
|
2003-07-03 17:05:57 +04:00
|
|
|
nsIWidget* widget = aView->GetWidget();
|
2006-03-22 21:00:28 +03:00
|
|
|
nsIWidget* parentWidget = widget->GetParent();
|
2010-09-18 15:28:50 +04:00
|
|
|
if (parentWidget) {
|
|
|
|
// Child widget
|
|
|
|
if (parentWidget != aNewWidget) {
|
2016-12-16 02:54:11 +03:00
|
|
|
widget->SetParent(aNewWidget);
|
2010-09-18 15:28:50 +04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Toplevel widget (popup, dialog, etc)
|
|
|
|
widget->ReparentNativeWidget(aNewWidget);
|
2002-09-12 07:59:15 +04:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Need to check each of the views children to see
|
|
|
|
// if they have a widget and reparent it.
|
|
|
|
|
2013-01-03 17:23:11 +04:00
|
|
|
for (nsView *kid = aView->GetFirstChild(); kid; kid = kid->GetNextSibling()) {
|
2002-09-12 07:59:15 +04:00
|
|
|
ReparentChildWidgets(kid, aNewWidget);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reparent a view and its descendant views widgets if necessary
|
|
|
|
|
2013-01-03 17:23:11 +04:00
|
|
|
void nsViewManager::ReparentWidgets(nsView* aView, nsView *aParent)
|
2002-09-12 07:59:15 +04:00
|
|
|
{
|
2004-05-18 05:13:45 +04:00
|
|
|
NS_PRECONDITION(aParent, "Must have a parent");
|
|
|
|
NS_PRECONDITION(aView, "Must have a view");
|
|
|
|
|
2002-09-12 07:59:15 +04:00
|
|
|
// Quickly determine whether the view has pre-existing children or a
|
|
|
|
// widget. In most cases the view will not have any pre-existing
|
|
|
|
// children when this is called. Only in the case
|
|
|
|
// where a view has been reparented by removing it from
|
|
|
|
// a reinserting it into a new location in the view hierarchy do we
|
|
|
|
// have to consider reparenting the existing widgets for the view and
|
|
|
|
// it's descendants.
|
2013-01-03 17:23:08 +04:00
|
|
|
if (aView->HasWidget() || aView->GetFirstChild()) {
|
2012-07-30 18:20:58 +04:00
|
|
|
nsIWidget* parentWidget = aParent->GetNearestWidget(nullptr);
|
2002-09-12 07:59:15 +04:00
|
|
|
if (parentWidget) {
|
|
|
|
ReparentChildWidgets(aView, parentWidget);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
NS_WARNING("Can not find a widget for the parent view");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-05 07:13:05 +04:00
|
|
|
void
|
|
|
|
nsViewManager::InsertChild(nsView *aParent, nsView *aChild, nsView *aSibling,
|
|
|
|
bool aAfter)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
2013-01-03 17:23:08 +04:00
|
|
|
NS_PRECONDITION(nullptr != aParent, "null ptr");
|
|
|
|
NS_PRECONDITION(nullptr != aChild, "null ptr");
|
|
|
|
NS_ASSERTION(aSibling == nullptr || aSibling->GetParent() == aParent,
|
2001-12-01 17:31:45 +03:00
|
|
|
"tried to insert view with invalid sibling");
|
2013-01-03 17:23:08 +04:00
|
|
|
NS_ASSERTION(!IsViewInserted(aChild), "tried to insert an already-inserted view");
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2013-01-03 17:23:08 +04:00
|
|
|
if ((nullptr != aParent) && (nullptr != aChild))
|
2001-10-11 06:57:31 +04:00
|
|
|
{
|
2002-09-11 06:33:43 +04:00
|
|
|
// if aAfter is set, we will insert the child after 'prev' (i.e. after 'kid' in document
|
|
|
|
// order, otherwise after 'kid' (i.e. before 'kid' in document order).
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
if (nullptr == aSibling) {
|
2002-09-11 06:33:43 +04:00
|
|
|
if (aAfter) {
|
|
|
|
// insert at end of document order, i.e., before first view
|
|
|
|
// this is the common case, by far
|
2013-01-03 17:23:08 +04:00
|
|
|
aParent->InsertChild(aChild, nullptr);
|
|
|
|
ReparentWidgets(aChild, aParent);
|
2002-09-11 06:33:43 +04:00
|
|
|
} else {
|
|
|
|
// insert at beginning of document order, i.e., after last view
|
2013-01-03 17:23:11 +04:00
|
|
|
nsView *kid = aParent->GetFirstChild();
|
|
|
|
nsView *prev = nullptr;
|
2003-07-03 17:05:57 +04:00
|
|
|
while (kid) {
|
2002-09-11 06:33:43 +04:00
|
|
|
prev = kid;
|
|
|
|
kid = kid->GetNextSibling();
|
|
|
|
}
|
|
|
|
// prev is last view or null if there are no children
|
2013-01-03 17:23:08 +04:00
|
|
|
aParent->InsertChild(aChild, prev);
|
|
|
|
ReparentWidgets(aChild, aParent);
|
2002-09-11 06:33:43 +04:00
|
|
|
}
|
|
|
|
} else {
|
2013-01-03 17:23:11 +04:00
|
|
|
nsView *kid = aParent->GetFirstChild();
|
|
|
|
nsView *prev = nullptr;
|
2013-01-03 17:23:08 +04:00
|
|
|
while (kid && aSibling != kid) {
|
2001-10-11 06:57:31 +04:00
|
|
|
//get the next sibling view
|
|
|
|
prev = kid;
|
2001-11-07 07:05:38 +03:00
|
|
|
kid = kid->GetNextSibling();
|
2001-10-11 06:57:31 +04:00
|
|
|
}
|
2012-07-30 18:20:58 +04:00
|
|
|
NS_ASSERTION(kid != nullptr,
|
2002-09-11 06:33:43 +04:00
|
|
|
"couldn't find sibling in child list");
|
|
|
|
if (aAfter) {
|
|
|
|
// insert after 'kid' in document order, i.e. before in view order
|
2013-01-03 17:23:08 +04:00
|
|
|
aParent->InsertChild(aChild, prev);
|
|
|
|
ReparentWidgets(aChild, aParent);
|
2002-09-11 06:33:43 +04:00
|
|
|
} else {
|
|
|
|
// insert before 'kid' in document order, i.e. after in view order
|
2013-01-03 17:23:08 +04:00
|
|
|
aParent->InsertChild(aChild, kid);
|
|
|
|
ReparentWidgets(aChild, aParent);
|
2002-09-11 06:33:43 +04:00
|
|
|
}
|
|
|
|
}
|
2001-12-01 17:31:45 +03:00
|
|
|
|
2001-10-11 06:57:31 +04:00
|
|
|
// if the parent view is marked as "floating", make the newly added view float as well.
|
2013-01-03 17:23:08 +04:00
|
|
|
if (aParent->GetFloating())
|
|
|
|
aChild->SetFloating(true);
|
2001-10-11 06:57:31 +04:00
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
2013-01-05 07:13:05 +04:00
|
|
|
void
|
|
|
|
nsViewManager::RemoveChild(nsView *aChild)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
2013-01-05 07:13:05 +04:00
|
|
|
NS_ASSERTION(aChild, "aChild must not be null");
|
1998-05-01 07:15:31 +04:00
|
|
|
|
2013-01-03 17:23:11 +04:00
|
|
|
nsView* parent = aChild->GetParent();
|
2001-12-01 17:31:45 +03:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
if (nullptr != parent) {
|
2013-01-03 17:23:08 +04:00
|
|
|
NS_ASSERTION(aChild->GetViewManager() == this ||
|
2010-07-19 06:23:47 +04:00
|
|
|
parent->GetViewManager() == this, "wrong view manager");
|
2013-01-03 17:23:08 +04:00
|
|
|
parent->RemoveChild(aChild);
|
2010-07-19 06:23:47 +04:00
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
2013-01-05 07:13:05 +04:00
|
|
|
void
|
|
|
|
nsViewManager::MoveViewTo(nsView *aView, nscoord aX, nscoord aY)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
2013-01-03 17:23:08 +04:00
|
|
|
NS_ASSERTION(aView->GetViewManager() == this, "wrong view manager");
|
|
|
|
aView->SetPosition(aX, aY);
|
2002-01-27 10:56:23 +03:00
|
|
|
}
|
|
|
|
|
2013-01-05 07:13:05 +04:00
|
|
|
void
|
|
|
|
nsViewManager::ResizeView(nsView *aView, const nsRect &aRect, bool aRepaintExposedAreaOnly)
|
1999-09-01 08:53:55 +04:00
|
|
|
{
|
2013-01-03 17:23:08 +04:00
|
|
|
NS_ASSERTION(aView->GetViewManager() == this, "wrong view manager");
|
2001-12-01 17:31:45 +03:00
|
|
|
|
2013-01-03 17:23:08 +04:00
|
|
|
nsRect oldDimensions = aView->GetDimensions();
|
2011-04-19 07:07:23 +04:00
|
|
|
if (!oldDimensions.IsEqualEdges(aRect)) {
|
2013-06-18 11:59:00 +04:00
|
|
|
aView->SetDimensions(aRect, true);
|
2001-03-30 09:17:07 +04:00
|
|
|
}
|
2004-03-11 03:32:01 +03:00
|
|
|
|
|
|
|
// Note that if layout resizes the view and the view has a custom clip
|
|
|
|
// region set, then we expect layout to update the clip region too. Thus
|
|
|
|
// in the case where mClipRect has been optimized away to just be a null
|
|
|
|
// pointer, and this resize is implicitly changing the clip rect, it's OK
|
|
|
|
// because layout will change it back again if necessary.
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
2013-01-05 07:13:05 +04:00
|
|
|
void
|
|
|
|
nsViewManager::SetViewFloating(nsView *aView, bool aFloating)
|
2001-11-24 08:37:25 +03:00
|
|
|
{
|
2013-01-03 17:23:08 +04:00
|
|
|
NS_ASSERTION(!(nullptr == aView), "no view");
|
1998-10-27 23:16:09 +03:00
|
|
|
|
2013-01-03 17:23:08 +04:00
|
|
|
aView->SetFloating(aFloating);
|
2001-12-01 17:31:45 +03:00
|
|
|
}
|
2001-11-24 08:37:25 +03:00
|
|
|
|
2013-01-05 07:13:05 +04:00
|
|
|
void
|
|
|
|
nsViewManager::SetViewVisibility(nsView *aView, nsViewVisibility aVisible)
|
2001-12-01 17:31:45 +03:00
|
|
|
{
|
2013-01-03 17:23:08 +04:00
|
|
|
NS_ASSERTION(aView->GetViewManager() == this, "wrong view manager");
|
2001-12-01 17:31:45 +03:00
|
|
|
|
2013-01-03 17:23:08 +04:00
|
|
|
if (aVisible != aView->GetVisibility()) {
|
|
|
|
aView->SetVisibility(aVisible);
|
2001-12-01 17:31:45 +03:00
|
|
|
}
|
|
|
|
}
|
2001-11-24 08:37:25 +03:00
|
|
|
|
2013-01-03 17:23:11 +04:00
|
|
|
bool nsViewManager::IsViewInserted(nsView *aView)
|
2001-12-01 17:31:45 +03:00
|
|
|
{
|
2004-05-17 20:29:13 +04:00
|
|
|
if (mRootView == aView) {
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2017-02-09 12:42:41 +03:00
|
|
|
}
|
|
|
|
if (aView->GetParent() == nullptr) {
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2017-02-09 12:42:41 +03:00
|
|
|
}
|
|
|
|
nsView* view = aView->GetParent()->GetFirstChild();
|
|
|
|
while (view != nullptr) {
|
|
|
|
if (view == aView) {
|
|
|
|
return true;
|
2001-12-01 17:31:45 +03:00
|
|
|
}
|
2017-02-09 12:42:41 +03:00
|
|
|
view = view->GetNextSibling();
|
2001-12-01 17:31:45 +03:00
|
|
|
}
|
2017-02-09 12:42:41 +03:00
|
|
|
return false;
|
2001-11-24 08:37:25 +03:00
|
|
|
}
|
|
|
|
|
2013-01-05 07:13:05 +04:00
|
|
|
void
|
2013-07-31 01:10:28 +04:00
|
|
|
nsViewManager::SetViewZIndex(nsView *aView, bool aAutoZIndex, int32_t aZIndex)
|
2001-11-24 08:37:25 +03:00
|
|
|
{
|
2013-01-03 17:23:08 +04:00
|
|
|
NS_ASSERTION((aView != nullptr), "no view");
|
2000-08-23 18:58:22 +04:00
|
|
|
|
2002-02-20 00:33:26 +03:00
|
|
|
// don't allow the root view's z-index to be changed. It should always be zero.
|
|
|
|
// This could be removed and replaced with a style rule, or just removed altogether, with interesting consequences
|
2004-05-17 20:29:13 +04:00
|
|
|
if (aView == mRootView) {
|
2013-01-05 07:13:05 +04:00
|
|
|
return;
|
2002-02-20 00:33:26 +03:00
|
|
|
}
|
|
|
|
|
2001-12-01 17:31:45 +03:00
|
|
|
if (aAutoZIndex) {
|
|
|
|
aZIndex = 0;
|
|
|
|
}
|
2001-11-24 08:37:25 +03:00
|
|
|
|
2013-07-31 01:10:28 +04:00
|
|
|
aView->SetZIndex(aAutoZIndex, aZIndex);
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
2013-01-05 07:12:24 +04:00
|
|
|
nsViewManager*
|
2011-12-24 07:52:23 +04:00
|
|
|
nsViewManager::IncrementDisableRefreshCount()
|
2011-12-24 10:21:58 +04:00
|
|
|
{
|
|
|
|
if (!IsRootVM()) {
|
2011-12-24 07:52:23 +04:00
|
|
|
return RootViewManager()->IncrementDisableRefreshCount();
|
2011-12-24 10:21:58 +04:00
|
|
|
}
|
2011-12-24 07:52:23 +04:00
|
|
|
|
|
|
|
++mRefreshDisableCount;
|
1999-05-27 01:13:06 +04:00
|
|
|
|
2008-01-27 02:59:50 +03:00
|
|
|
return this;
|
1999-05-27 01:13:06 +04:00
|
|
|
}
|
|
|
|
|
2011-12-24 07:52:23 +04:00
|
|
|
void
|
|
|
|
nsViewManager::DecrementDisableRefreshCount()
|
1999-05-27 01:13:06 +04:00
|
|
|
{
|
2008-01-27 02:59:50 +03:00
|
|
|
NS_ASSERTION(IsRootVM(), "Should only be called on root");
|
2011-12-24 07:52:23 +04:00
|
|
|
--mRefreshDisableCount;
|
|
|
|
NS_ASSERTION(mRefreshDisableCount >= 0, "Invalid refresh disable count!");
|
1999-05-27 01:13:06 +04:00
|
|
|
}
|
|
|
|
|
2013-01-05 07:13:05 +04:00
|
|
|
void
|
|
|
|
nsViewManager::GetRootWidget(nsIWidget **aWidget)
|
2009-07-22 04:45:03 +04:00
|
|
|
{
|
|
|
|
if (!mRootView) {
|
2012-07-30 18:20:58 +04:00
|
|
|
*aWidget = nullptr;
|
2013-01-05 07:13:05 +04:00
|
|
|
return;
|
2009-07-22 04:45:03 +04:00
|
|
|
}
|
|
|
|
if (mRootView->HasWidget()) {
|
|
|
|
*aWidget = mRootView->GetWidget();
|
|
|
|
NS_ADDREF(*aWidget);
|
2013-01-05 07:13:05 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (mRootView->GetParent()) {
|
2013-01-05 07:13:23 +04:00
|
|
|
mRootView->GetParent()->GetViewManager()->GetRootWidget(aWidget);
|
2013-01-05 07:13:05 +04:00
|
|
|
return;
|
2009-07-22 04:45:03 +04:00
|
|
|
}
|
2012-07-30 18:20:58 +04:00
|
|
|
*aWidget = nullptr;
|
2009-07-22 04:45:03 +04:00
|
|
|
}
|
|
|
|
|
2015-11-17 08:18:31 +03:00
|
|
|
LayoutDeviceIntRect
|
|
|
|
nsViewManager::ViewToWidget(nsView* aView, const nsRect& aRect) const
|
1999-11-14 05:51:25 +03:00
|
|
|
{
|
2010-07-02 23:11:04 +04:00
|
|
|
NS_ASSERTION(aView->GetViewManager() == this, "wrong view manager");
|
|
|
|
|
|
|
|
// account for the view's origin not lining up with the widget's
|
2012-05-03 20:33:51 +04:00
|
|
|
nsRect rect = aRect + aView->ViewToWidgetOffset();
|
2007-06-28 10:02:05 +04:00
|
|
|
|
2001-10-11 06:57:31 +04:00
|
|
|
// finally, convert to device coordinates.
|
2015-11-17 08:18:31 +03:00
|
|
|
return LayoutDeviceIntRect::FromUnknownRect(
|
|
|
|
rect.ToOutsidePixels(AppUnitsPerDevPixel()));
|
1999-11-14 05:51:25 +03:00
|
|
|
}
|
2000-01-27 02:04:40 +03:00
|
|
|
|
2013-01-05 07:13:05 +04:00
|
|
|
void
|
2011-09-29 10:19:26 +04:00
|
|
|
nsViewManager::IsPainting(bool& aIsPainting)
|
2000-10-17 09:03:45 +04:00
|
|
|
{
|
2004-10-30 00:47:25 +04:00
|
|
|
aIsPainting = IsPainting();
|
2000-10-17 09:03:45 +04:00
|
|
|
}
|
|
|
|
|
2012-07-04 04:14:47 +04:00
|
|
|
void
|
2015-04-13 19:02:27 +03:00
|
|
|
nsViewManager::ProcessPendingUpdates()
|
2011-12-24 07:52:22 +04:00
|
|
|
{
|
2011-12-24 07:52:23 +04:00
|
|
|
if (!IsRootVM()) {
|
2015-04-13 19:02:27 +03:00
|
|
|
RootViewManager()->ProcessPendingUpdates();
|
2012-07-04 04:14:47 +04:00
|
|
|
return;
|
2011-12-24 07:52:23 +04:00
|
|
|
}
|
2010-08-05 22:39:39 +04:00
|
|
|
|
2013-01-05 07:14:17 +04:00
|
|
|
// Flush things like reflows by calling WillPaint on observer presShells.
|
|
|
|
if (mPresShell) {
|
2014-10-28 18:59:08 +03:00
|
|
|
mPresShell->GetPresContext()->RefreshDriver()->RevokeViewManagerFlush();
|
|
|
|
|
2016-05-11 06:58:47 +03:00
|
|
|
RefPtr<nsViewManager> strongThis(this);
|
2013-01-28 23:34:08 +04:00
|
|
|
CallWillPaintOnObservers();
|
2014-10-28 18:59:08 +03:00
|
|
|
|
|
|
|
ProcessPendingUpdatesForView(mRootView, true);
|
2012-07-04 04:24:55 +04:00
|
|
|
}
|
2001-01-20 07:59:39 +03:00
|
|
|
}
|
|
|
|
|
2011-12-24 07:52:23 +04:00
|
|
|
void
|
|
|
|
nsViewManager::UpdateWidgetGeometry()
|
|
|
|
{
|
|
|
|
if (!IsRootVM()) {
|
|
|
|
RootViewManager()->UpdateWidgetGeometry();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mHasPendingWidgetGeometryChanges) {
|
2013-01-05 07:14:17 +04:00
|
|
|
mHasPendingWidgetGeometryChanges = false;
|
2016-05-11 06:58:47 +03:00
|
|
|
RefPtr<nsViewManager> strongThis(this);
|
2012-08-13 14:10:11 +04:00
|
|
|
ProcessPendingUpdatesForView(mRootView, false);
|
2011-12-24 07:52:23 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-16 14:55:19 +04:00
|
|
|
void
|
2013-01-28 23:34:08 +04:00
|
|
|
nsViewManager::CallWillPaintOnObservers()
|
2009-10-16 14:55:19 +04:00
|
|
|
{
|
2010-07-16 01:08:08 +04:00
|
|
|
NS_PRECONDITION(IsRootVM(), "Must be root VM for this to be called!");
|
2009-10-16 14:55:19 +04:00
|
|
|
|
2014-05-10 02:53:41 +04:00
|
|
|
if (NS_WARN_IF(!gViewManagers)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-05-09 12:20:55 +04:00
|
|
|
uint32_t index;
|
2014-05-09 12:00:48 +04:00
|
|
|
for (index = 0; index < gViewManagers->Length(); index++) {
|
|
|
|
nsViewManager* vm = gViewManagers->ElementAt(index);
|
2009-10-16 14:55:19 +04:00
|
|
|
if (vm->RootViewManager() == this) {
|
|
|
|
// One of our kids.
|
2010-09-11 22:24:50 +04:00
|
|
|
if (vm->mRootView && vm->mRootView->IsEffectivelyVisible()) {
|
2011-11-21 21:53:20 +04:00
|
|
|
nsCOMPtr<nsIPresShell> shell = vm->GetPresShell();
|
|
|
|
if (shell) {
|
2013-01-28 23:34:11 +04:00
|
|
|
shell->WillPaint();
|
2010-09-11 22:24:50 +04:00
|
|
|
}
|
2009-10-16 14:55:19 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-05 07:13:05 +04:00
|
|
|
void
|
2012-08-22 19:56:38 +04:00
|
|
|
nsViewManager::GetLastUserEventTime(uint32_t& aTime)
|
2001-06-29 08:01:26 +04:00
|
|
|
{
|
2001-10-11 06:57:31 +04:00
|
|
|
aTime = gLastUserEventTime;
|
2001-06-29 08:01:26 +04:00
|
|
|
}
|
2004-06-22 08:32:52 +04:00
|
|
|
|
2005-05-05 00:22:32 +04:00
|
|
|
void
|
|
|
|
nsViewManager::InvalidateHierarchy()
|
|
|
|
{
|
|
|
|
if (mRootView) {
|
2005-06-01 19:43:08 +04:00
|
|
|
if (!IsRootVM()) {
|
|
|
|
NS_RELEASE(mRootViewManager);
|
2005-05-05 00:22:32 +04:00
|
|
|
}
|
2013-01-03 17:23:11 +04:00
|
|
|
nsView *parent = mRootView->GetParent();
|
2005-05-05 00:22:32 +04:00
|
|
|
if (parent) {
|
2013-01-05 07:13:23 +04:00
|
|
|
mRootViewManager = parent->GetViewManager()->RootViewManager();
|
2005-05-05 00:22:32 +04:00
|
|
|
NS_ADDREF(mRootViewManager);
|
|
|
|
NS_ASSERTION(mRootViewManager != this,
|
|
|
|
"Root view had a parent, but it has the same view manager");
|
|
|
|
} else {
|
|
|
|
mRootViewManager = this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-07-22 04:09:02 +03:00
|
|
|
|