Merge m-c tip to m-i

This commit is contained in:
Justin Wood 2012-01-15 05:29:24 -05:00
commit 94e66a942e
86 changed files with 786 additions and 1241 deletions

View File

@ -156,7 +156,10 @@ class RemoteAutomation(Automation):
self.stdoutlen = 0
self.proc = dm.launchProcess(cmd, stdout, cwd, env, True)
if (self.proc is None):
raise Exception("unable to launch process")
if cmd[0] == 'am':
self.proc = stdout
else:
raise Exception("unable to launch process")
exepath = cmd[0]
name = exepath.split('/')[-1]
self.procName = name

View File

@ -503,7 +503,8 @@ nsGenericHTMLElement::GetOffsetRect(nsRect& aRect, nsIContent** aOffsetParent)
nsIFrame* parent = frame->GetParent();
nsPoint origin(0, 0);
if (parent && parent->GetType() == nsGkAtoms::tableOuterFrame) {
if (parent && parent->GetType() == nsGkAtoms::tableOuterFrame &&
frame->GetType() == nsGkAtoms::tableFrame) {
origin = parent->GetPositionIgnoringScrolling();
parent = parent->GetParent();
}

View File

@ -140,17 +140,6 @@ nsHTMLDNSPrefetch::IsAllowed (nsIDocument *aDocument)
nsresult
nsHTMLDNSPrefetch::Prefetch(Link *aElement, PRUint16 flags)
{
if (IsNeckoChild()) {
// Instead of transporting the Link object to the other process
// we are using the hostname based function here, too. Compared to the
// IPC the performance hit should be negligible.
nsAutoString hostname;
nsresult rv = aElement->GetHostname(hostname);
NS_ENSURE_SUCCESS(rv,rv);
return Prefetch(hostname, flags);
}
if (!(sInitialized && sPrefetches && sDNSService && sDNSListener))
return NS_ERROR_NOT_AVAILABLE;
@ -299,11 +288,16 @@ nsHTMLDNSPrefetch::nsDeferrals::SubmitQueue()
hrefURI->GetAsciiHost(hostName);
if (!hostName.IsEmpty()) {
nsCOMPtr<nsICancelable> tmpOutstanding;
if (IsNeckoChild()) {
gNeckoChild->SendHTMLDNSPrefetch(NS_ConvertUTF8toUTF16(hostName),
mEntries[mTail].mFlags);
} else {
nsCOMPtr<nsICancelable> tmpOutstanding;
sDNSService->AsyncResolve(hostName,
sDNSService->AsyncResolve(hostName,
mEntries[mTail].mFlags | nsIDNSService::RESOLVE_SPECULATE,
sDNSListener, nsnull, getter_AddRefs(tmpOutstanding));
}
}
}

View File

@ -1160,10 +1160,6 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
// All nsTextControlFrames are widgets
editorFlags |= nsIPlaintextEditor::eEditorWidgetMask;
// Use async reflow and painting for text widgets to improve
// performance.
editorFlags |= nsIPlaintextEditor::eEditorUseAsyncUpdatesMask;
// Spell check is diabled at creation time. It is enabled once
// the editor comes into focus.
editorFlags |= nsIPlaintextEditor::eEditorSkipSpellCheck;
@ -1314,12 +1310,7 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
// editor for us.
if (!defaultValue.IsEmpty()) {
// Avoid causing reentrant painting and reflowing by telling the editor
// that we don't want it to force immediate view refreshes or force
// immediate reflows during any editor calls.
rv = newEditor->SetFlags(editorFlags |
nsIPlaintextEditor::eEditorUseAsyncUpdatesMask);
rv = newEditor->SetFlags(editorFlags);
NS_ENSURE_SUCCESS(rv, rv);
// Now call SetValue() which will make the necessary editor calls to set
@ -1837,7 +1828,6 @@ nsTextEditorState::SetValue(const nsAString& aValue, bool aUserInput)
flags = savedFlags;
flags &= ~(nsIPlaintextEditor::eEditorDisabledMask);
flags &= ~(nsIPlaintextEditor::eEditorReadonlyMask);
flags |= nsIPlaintextEditor::eEditorUseAsyncUpdatesMask;
flags |= nsIPlaintextEditor::eEditorDontEchoPassword;
mEditor->SetFlags(flags);

View File

@ -282,6 +282,7 @@ _TEST_FILES = \
test_bug677658.html \
test_bug677463.html \
test_bug682886.html \
test_bug717819.html \
file_fullscreen-api.html \
file_fullscreen-api-keys.html \
test_fullscreen-api.html \

View File

@ -76,8 +76,7 @@ function run_test() {
t3('span9' ,[0,0,20,20],[1,1,20,20],[0,0,20,20],'td9');
t3('td9' ,[1,1,22,22],[15,15,24,24],[0,0,24,24],'table9');
t3('tr9' ,[0,0,24,24],[15,15,24,24],[0,0,24,22],'table9');
// t3('span10' ,[0,0,20,20],[3,30,20,20],[0,0,20,20],'table9');
t3('span10' ,[0,0,20,20],[27,450,20,20],[0,0,20,20],'body'); // bug: 'body' should be 'table9'
t3('span10' ,[0,0,20,20],[17,43,20,20],[0,0,20,20],'table9');
t3('table9',[13,13,28,34],[10,407,54,60],[0,0,54,50],'body');
t3('div9',[10,10,-1,0],[0,397,-1,20],[0,0,-1,70],'body');

View File

@ -0,0 +1,37 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=717819
-->
<head>
<title>Test for Bug 717819</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717819">Mozilla Bug 717819</a>
<p id="display"></p>
<div id="content">
<table style="position: relative; top: 100px;">
<tr>
<td>
<div id="test" style="position: absolute; top: 50px;"></div>
</td>
</tr>
</table>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 717819 **/
var div = document.getElementById("test");
is(div.offsetTop, 50, "The offsetTop must be calculated correctly");
is(div.offsetParent, document.querySelector("table"),
"The offset should be calculated off of the correct parent");
</script>
</pre>
</body>
</html>

View File

@ -4732,8 +4732,7 @@ nsDocShell::Repaint(bool aForce)
nsIViewManager* viewManager = presShell->GetViewManager();
NS_ENSURE_TRUE(viewManager, NS_ERROR_FAILURE);
// what about aForce ?
NS_ENSURE_SUCCESS(viewManager->UpdateAllViews(0), NS_ERROR_FAILURE);
NS_ENSURE_SUCCESS(viewManager->InvalidateAllViews(), NS_ERROR_FAILURE);
return NS_OK;
}
@ -7324,7 +7323,7 @@ nsDocShell::RestoreFromHistory()
// call Thaw. So we issue the invalidate here.
newRootView = newVM->GetRootView();
if (newRootView) {
newVM->UpdateView(newRootView, NS_VMREFRESH_NO_SYNC);
newVM->InvalidateView(newRootView);
}
}
}

View File

@ -761,27 +761,6 @@ nsDOMWindowUtils::CycleCollect(nsICycleCollectorListener *aListener)
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::ProcessUpdates()
{
nsPresContext* presContext = GetPresContext();
if (!presContext)
return NS_ERROR_UNEXPECTED;
nsIPresShell* shell = presContext->GetPresShell();
if (!shell)
return NS_ERROR_UNEXPECTED;
nsIViewManager *viewManager = shell->GetViewManager();
if (!viewManager)
return NS_ERROR_UNEXPECTED;
nsIViewManager::UpdateViewBatch batch;
batch.BeginUpdateViewBatch(viewManager);
batch.EndUpdateViewBatch(NS_VMREFRESH_IMMEDIATE);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SendSimpleGestureEvent(const nsAString& aType,
float aX,

View File

@ -69,7 +69,7 @@ interface nsIDOMBlob;
interface nsIDOMFile;
interface nsIFile;
[scriptable, uuid(15fcceb0-37ea-11e1-b86c-0800200c9a66)]
[scriptable, uuid(b9c1f815-c2f2-4607-a060-6a8566581927)]
interface nsIDOMWindowUtils : nsISupports {
/**
@ -378,12 +378,6 @@ interface nsIDOMWindowUtils : nsISupports {
*/
void cycleCollect([optional] in nsICycleCollectorListener aListener);
/**
* Force processing of any queued paints
*/
void processUpdates();
/** Synthesize a simple gesture event for a window. The event types
* supported are: MozSwipeGesture, MozMagnifyGestureStart,
* MozMagnifyGestureUpdate, MozMagnifyGesture, MozRotateGestureStart,

View File

@ -621,8 +621,7 @@ NS_IMETHODIMP nsPluginInstanceOwner::InvalidateRect(NPRect *invalidRect)
if (mWidget) {
mWidget->Invalidate(nsIntRect(invalidRect->left, invalidRect->top,
invalidRect->right - invalidRect->left,
invalidRect->bottom - invalidRect->top),
false);
invalidRect->bottom - invalidRect->top));
return NS_OK;
}
#endif
@ -654,12 +653,6 @@ NS_IMETHODIMP nsPluginInstanceOwner::InvalidateRegion(NPRegion invalidRegion)
NS_IMETHODIMP nsPluginInstanceOwner::ForceRedraw()
{
NS_ENSURE_TRUE(mObjectFrame, NS_ERROR_NULL_POINTER);
nsIView* view = mObjectFrame->GetView();
if (view) {
return view->GetViewManager()->Composite();
}
return NS_OK;
}

View File

@ -37,7 +37,7 @@
#include "nsISupports.idl"
[scriptable, uuid(05d312ef-8914-494e-91c9-2be8ed7f8e29)]
[scriptable, uuid(07b6d070-ccea-4a00-84b4-f4b94dd9eb52)]
interface nsIPlaintextEditor : nsISupports
{
@ -56,29 +56,27 @@ interface nsIPlaintextEditor : nsISupports
const long eEditorFilterInputMask = 0x0020;
// use mail-compose editing rules
const long eEditorMailMask = 0x0040;
// prevent immediate reflows and view refreshes
const long eEditorUseAsyncUpdatesMask = 0x0080;
// allow the editor to set font: monospace on the root node
const long eEditorEnableWrapHackMask = 0x0100;
const long eEditorEnableWrapHackMask = 0x0080;
// bit for widgets (form elements)
const long eEditorWidgetMask = 0x0200;
const long eEditorWidgetMask = 0x0100;
// this HTML editor should not create css styles
const long eEditorNoCSSMask = 0x0400;
const long eEditorNoCSSMask = 0x0200;
// whether HTML document specific actions are executed or not.
// e.g., if this flag is set, the editor doesn't handle Tab key.
// besides, anchors of HTML are not clickable.
const long eEditorAllowInteraction = 0x0800;
const long eEditorAllowInteraction = 0x0400;
// when this is set, the characters in password editor are always masked.
// see bug 530367 for the detail.
const long eEditorDontEchoPassword = 0x1000;
const long eEditorDontEchoPassword = 0x0800;
// when this flag is set, the internal direction of the editor is RTL.
// if neither of the direction flags are set, the direction is determined
// from the text control's content node.
const long eEditorRightToLeft = 0x2000;
const long eEditorRightToLeft = 0x1000;
// when this flag is set, the internal direction of the editor is LTR.
const long eEditorLeftToRight = 0x4000;
const long eEditorLeftToRight = 0x2000;
// when this flag is set, the editor's text content is not spell checked.
const long eEditorSkipSpellCheck = 0x8000;
const long eEditorSkipSpellCheck = 0x4000;
/*
* The valid values for newlines handling.

View File

@ -4206,15 +4206,6 @@ nsresult nsEditor::BeginUpdateViewBatch()
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(selection));
selPrivate->StartBatchChanges();
}
// Turn off view updating.
nsCOMPtr<nsIPresShell> ps = GetPresShell();
if (ps) {
nsCOMPtr<nsIViewManager> viewManager = ps->GetViewManager();
if (viewManager) {
mBatch.BeginUpdateViewBatch(viewManager);
}
}
}
mUpdateCount++;
@ -4250,20 +4241,6 @@ nsresult nsEditor::EndUpdateViewBatch()
StCaretHider caretHider(caret);
PRUint32 flags = 0;
GetFlags(&flags);
// Turn view updating back on.
PRUint32 updateFlag = NS_VMREFRESH_IMMEDIATE;
// If we're doing async updates, use NS_VMREFRESH_DEFERRED here, so that
// the reflows we caused will get processed before the invalidates.
if (flags & nsIPlaintextEditor::eEditorUseAsyncUpdatesMask) {
updateFlag = NS_VMREFRESH_DEFERRED;
}
mBatch.EndUpdateViewBatch(updateFlag);
// Turn selection updating and notifications back on.
nsCOMPtr<nsISelection>selection;

View File

@ -689,11 +689,6 @@ public:
return (mFlags & nsIPlaintextEditor::eEditorMailMask) != 0;
}
bool UseAsyncUpdate() const
{
return (mFlags & nsIPlaintextEditor::eEditorUseAsyncUpdatesMask) != 0;
}
bool IsWrapHackEnabled() const
{
return (mFlags & nsIPlaintextEditor::eEditorEnableWrapHackMask) != 0;
@ -768,7 +763,6 @@ protected:
nsWeakPtr mSelConWeak; // weak reference to the nsISelectionController
PRInt32 mUpdateCount;
nsIViewManager::UpdateViewBatch mBatch;
// Spellchecking
enum Tristate {

View File

@ -32,12 +32,16 @@ function execTests() {
body.style.height='400px';
body.style.padding='0px';
body.style.margin='0px';
body.style.borderSize='0px';
body.style.borderWidth='0px';
var sel = win.getSelection();
doc.designMode='on';
body.innerHTML = "1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>10<br>11<br>12<br>";
win.focus();
// Flush out layout to make sure that the subdocument will be the size we
// expect by the time we try to scroll it.
is(body.getBoundingClientRect().height, 400,
"Body height should be what we set it to");
yield;
function doCommand(cmd) {

View File

@ -376,9 +376,9 @@ struct Ligature
c->buffer->info[c->buffer->i].lig_comp() = 0;
c->buffer->info[c->buffer->i].lig_id() = lig_id;
if (j == c->buffer->i + i) /* No input glyphs skipped */
if (j < c->buffer->i + count) /* No input glyphs skipped */
{
c->replace_glyphs_be16 (i, 1, (const uint16_t *) &ligGlyph);
c->replace_glyphs_be16 (count, 1, (const uint16_t *) &ligGlyph);
}
else
{

View File

@ -2985,14 +2985,14 @@ BasicShadowImageLayer::Swap(const SharedImage& aNewFront,
{
nsRefPtr<gfxASurface> surface =
BasicManager()->OpenDescriptor(aNewFront);
// Destroy mFrontBuffer if size different
bool needDrop = false;
// Destroy mFrontBuffer if size different or image type is different
bool surfaceConfigChanged = surface->GetSize() != mSize;
if (IsSurfaceDescriptorValid(mFrontBuffer)) {
nsRefPtr<gfxASurface> front = BasicManager()->OpenDescriptor(mFrontBuffer);
needDrop = surface->GetSize() != mSize ||
surface->GetContentType() != front->GetContentType();
surfaceConfigChanged = surfaceConfigChanged ||
surface->GetContentType() != front->GetContentType();
}
if (needDrop) {
if (surfaceConfigChanged) {
DestroyFrontBuffer();
mSize = surface->GetSize();
}
@ -3107,13 +3107,13 @@ BasicShadowCanvasLayer::Swap(const CanvasSurface& aNewFront, bool needYFlip,
BasicManager()->OpenDescriptor(aNewFront);
// Destroy mFrontBuffer if size different
gfxIntSize sz = surface->GetSize();
bool needDrop = false;
bool surfaceConfigChanged = sz != gfxIntSize(mBounds.width, mBounds.height);
if (IsSurfaceDescriptorValid(mFrontSurface)) {
nsRefPtr<gfxASurface> front = BasicManager()->OpenDescriptor(mFrontSurface);
needDrop = sz != gfxIntSize(mBounds.width, mBounds.height) ||
surface->GetContentType() != front->GetContentType();
surfaceConfigChanged = surfaceConfigChanged ||
surface->GetContentType() != front->GetContentType();
}
if (needDrop) {
if (surfaceConfigChanged) {
DestroyFrontBuffer();
mBounds.SetRect(0, 0, sz.width, sz.height);
}

View File

@ -3377,9 +3377,13 @@ void gfxFontGroup::ComputeRanges(nsTArray<gfxTextRange>& aRanges,
}
PRUint32 prevCh = 0;
gfxFont *prevFont = nsnull;
PRUint8 matchType = 0;
// initialize prevFont to the group's primary font, so that this will be
// used for string-initial control chars, etc rather than risk hitting font
// fallback for these (bug 716229)
gfxFont *prevFont = GetFontAt(0);
for (PRUint32 i = 0; i < aLength; i++) {
const PRUint32 origI = i; // save off in case we increase for surrogate

View File

@ -653,7 +653,7 @@ class Value
friend jsval_layout (::JSVAL_TO_IMPL)(Value);
friend Value (::IMPL_TO_JSVAL)(jsval_layout l);
} JSVAL_ALIGNMENT;
};
inline bool
IsPoisonedValue(const Value &v)
@ -1158,6 +1158,11 @@ IMPL_TO_JSVAL(jsval_layout l)
return v;
}
#ifdef DEBUG
struct JSValueAlignmentTester { char c; JS::Value v; };
JS_STATIC_ASSERT(sizeof(JSValueAlignmentTester) == 16);
#endif /* DEBUG */
#else /* defined(__cplusplus) */
/*
@ -1182,6 +1187,11 @@ IMPL_TO_JSVAL(jsval_layout l)
#endif /* defined(__cplusplus) */
#ifdef DEBUG
typedef struct { char c; jsval_layout l; } JSLayoutAlignmentTester;
JS_STATIC_ASSERT(sizeof(JSLayoutAlignmentTester) == 16);
#endif /* DEBUG */
JS_STATIC_ASSERT(sizeof(jsval_layout) == sizeof(jsval));
/************************************************************************/

View File

@ -310,7 +310,7 @@ typedef union jsval_layout
} s;
double asDouble;
void *asPtr;
} jsval_layout;
} JSVAL_ALIGNMENT jsval_layout;
# elif JS_BITS_PER_WORD == 64
typedef union jsval_layout
{
@ -332,7 +332,7 @@ typedef union jsval_layout
double asDouble;
void *asPtr;
size_t asWord;
} jsval_layout;
} JSVAL_ALIGNMENT jsval_layout;
# endif /* JS_BITS_PER_WORD */
#else /* defined(IS_LITTLE_ENDIAN) */
# if JS_BITS_PER_WORD == 32
@ -354,7 +354,7 @@ typedef union jsval_layout
} s;
double asDouble;
void *asPtr;
} jsval_layout;
} JSVAL_ALIGNMENT jsval_layout;
# elif JS_BITS_PER_WORD == 64
typedef union jsval_layout
{
@ -374,7 +374,7 @@ typedef union jsval_layout
double asDouble;
void *asPtr;
size_t asWord;
} jsval_layout;
} JSVAL_ALIGNMENT jsval_layout;
# endif /* JS_BITS_PER_WORD */
#endif /* defined(IS_LITTLE_ENDIAN) */

View File

@ -49,11 +49,11 @@
#include "jsatom.h"
#include "jsfriendapi.h"
#include "jsgc.h"
#include "nsThreadUtilsInternal.h"
#include "dom_quickstubs.h"
#include "nsNullPrincipal.h"
#include "nsIURI.h"
#include "nsJSEnvironment.h"
#include "nsThreadUtils.h"
#include "XrayWrapper.h"
#include "WrapperFactory.h"
@ -66,6 +66,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/Base64.h"
#include "mozilla/Util.h"
#include "nsWrapperCacheInlines.h"
@ -105,6 +106,7 @@ nsXPConnect::nsXPConnect()
mDefaultSecurityManagerFlags(0),
mShuttingDown(false),
mNeedGCBeforeCC(true),
mEventDepth(0),
mCycleCollectionContext(nsnull)
{
mRuntime = XPCJSRuntime::newXPCJSRuntime(this);
@ -164,6 +166,12 @@ nsXPConnect::~nsXPConnect()
nsXPConnect*
nsXPConnect::GetXPConnect()
{
// Do a release-mode assert that we're not doing anything significant in
// XPConnect off the main thread. If you're an extension developer hitting
// this, you need to change your code. See bug 716167.
if (!NS_LIKELY(NS_IsMainThread() || NS_IsCycleCollectorThread()))
JS_Assert("NS_IsMainThread()", __FILE__, __LINE__);
if (!gSelf) {
if (gOnceAliveNowDead)
return nsnull;
@ -181,7 +189,14 @@ nsXPConnect::GetXPConnect()
// Initial extra ref to keep the singleton alive
// balanced by explicit call to ReleaseXPConnectSingleton()
NS_ADDREF(gSelf);
if (NS_FAILED(NS_SetGlobalThreadObserver(gSelf))) {
// Add XPConnect as an thread observer.
//
// The cycle collector sometimes calls GetXPConnect, but it should never
// be the one that initializes gSelf.
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIThreadInternal> thread = do_QueryInterface(NS_GetCurrentThread());
if (NS_FAILED(thread->AddObserver(gSelf))) {
NS_RELEASE(gSelf);
// Fall through to returning null
}
@ -204,7 +219,14 @@ nsXPConnect::ReleaseXPConnectSingleton()
{
nsXPConnect* xpc = gSelf;
if (xpc) {
NS_SetGlobalThreadObserver(nsnull);
// The thread subsystem may have been shut down already, so make sure
// to check for null here.
nsCOMPtr<nsIThreadInternal> thread = do_QueryInterface(NS_GetCurrentThread());
if (thread) {
MOZ_ASSERT(NS_IsMainThread());
thread->RemoveObserver(xpc);
}
#ifdef DEBUG
// force a dump of the JavaScript gc heap if JS is still alive
@ -2345,8 +2367,12 @@ NS_IMETHODIMP
nsXPConnect::OnProcessNextEvent(nsIThreadInternal *aThread, bool aMayWait,
PRUint32 aRecursionDepth)
{
// Record this event.
mEventDepth++;
// Push a null JSContext so that we don't see any script during
// event processing.
MOZ_ASSERT(NS_IsMainThread());
return Push(nsnull);
}
@ -2354,10 +2380,14 @@ NS_IMETHODIMP
nsXPConnect::AfterProcessNextEvent(nsIThreadInternal *aThread,
PRUint32 aRecursionDepth)
{
// Watch out for unpaired events during observer registration.
if (NS_UNLIKELY(mEventDepth == 0))
return NS_OK;
mEventDepth--;
// Call cycle collector occasionally.
if (NS_IsMainThread()) {
nsJSContext::MaybePokeCC();
}
MOZ_ASSERT(NS_IsMainThread());
nsJSContext::MaybePokeCC();
return Pop(nsnull);
}

View File

@ -597,6 +597,13 @@ private:
PRUint16 mDefaultSecurityManagerFlags;
JSBool mShuttingDown;
JSBool mNeedGCBeforeCC;
// nsIThreadInternal doesn't remember which observers it called
// OnProcessNextEvent on when it gets around to calling AfterProcessNextEvent.
// So if XPConnect gets initialized mid-event (which can happen), we'll get
// an 'after' notification without getting an 'on' notification. If we don't
// watch out for this, we'll do an unmatched |pop| on the context stack.
PRUint16 mEventDepth;
#ifdef DEBUG_CC
PLDHashTable mJSRoots;
#endif
@ -3644,6 +3651,12 @@ public:
// Get the instance of this object for the current thread
static inline XPCPerThreadData* GetData(JSContext *cx)
{
// Do a release-mode assert that we're not doing anything significant in
// XPConnect off the main thread. If you're an extension developer hitting
// this, you need to change your code. See bug 716167.
if (!NS_LIKELY(NS_IsMainThread() || NS_IsCycleCollectorThread()))
JS_Assert("NS_IsMainThread()", __FILE__, __LINE__);
if (cx) {
NS_ASSERTION(js::GetContextThread(cx), "Uh, JS context w/o a thread?");

View File

@ -7635,7 +7635,6 @@ static bool gInApplyRenderingChangeToTree = false;
static void
DoApplyRenderingChangeToTree(nsIFrame* aFrame,
nsIViewManager* aViewManager,
nsFrameManager* aFrameManager,
nsChangeHint aChange);
@ -7644,7 +7643,7 @@ DoApplyRenderingChangeToTree(nsIFrame* aFrame,
* This rect is relative to aFrame's parent
*/
static void
UpdateViewsForTree(nsIFrame* aFrame, nsIViewManager* aViewManager,
UpdateViewsForTree(nsIFrame* aFrame,
nsFrameManager* aFrameManager,
nsChangeHint aChange)
{
@ -7671,19 +7670,19 @@ UpdateViewsForTree(nsIFrame* aFrame, nsIViewManager* aViewManager,
nsIFrame* outOfFlowFrame =
nsPlaceholderFrame::GetRealFrameForPlaceholder(child);
do {
DoApplyRenderingChangeToTree(outOfFlowFrame, aViewManager,
aFrameManager, aChange);
DoApplyRenderingChangeToTree(outOfFlowFrame, aFrameManager,
aChange);
} while ((outOfFlowFrame = outOfFlowFrame->GetNextContinuation()));
} else if (lists.CurrentID() == nsIFrame::kPopupList) {
DoApplyRenderingChangeToTree(child, aViewManager,
aFrameManager, aChange);
DoApplyRenderingChangeToTree(child, aFrameManager,
aChange);
} else { // regular frame
if ((child->GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER) &&
(aChange & nsChangeHint_RepaintFrame)) {
FrameLayerBuilder::InvalidateThebesLayerContents(child,
child->GetVisualOverflowRectRelativeToSelf());
}
UpdateViewsForTree(child, aViewManager, aFrameManager, aChange);
UpdateViewsForTree(child, aFrameManager, aChange);
}
}
}
@ -7692,7 +7691,6 @@ UpdateViewsForTree(nsIFrame* aFrame, nsIViewManager* aViewManager,
static void
DoApplyRenderingChangeToTree(nsIFrame* aFrame,
nsIViewManager* aViewManager,
nsFrameManager* aFrameManager,
nsChangeHint aChange)
{
@ -7704,7 +7702,7 @@ DoApplyRenderingChangeToTree(nsIFrame* aFrame,
// frame doesn't have a view, find the nearest containing view
// (adjusting r's coordinate system to reflect the nesting) and
// update there.
UpdateViewsForTree(aFrame, aViewManager, aFrameManager, aChange);
UpdateViewsForTree(aFrame, aFrameManager, aChange);
// if frame has view, will already be invalidated
if (aChange & nsChangeHint_RepaintFrame) {
@ -7767,25 +7765,18 @@ ApplyRenderingChangeToTree(nsPresContext* aPresContext,
NS_ASSERTION(aFrame, "root frame must paint");
}
nsIViewManager* viewManager = shell->GetViewManager();
// Trigger rendering updates by damaging this frame and any
// continuations of this frame.
// XXX this needs to detect the need for a view due to an opacity change and deal with it...
nsIViewManager::UpdateViewBatch batch(viewManager);
#ifdef DEBUG
gInApplyRenderingChangeToTree = true;
#endif
DoApplyRenderingChangeToTree(aFrame, viewManager, shell->FrameManager(),
aChange);
DoApplyRenderingChangeToTree(aFrame, shell->FrameManager(), aChange);
#ifdef DEBUG
gInApplyRenderingChangeToTree = false;
#endif
batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
}
/**
@ -7826,13 +7817,8 @@ InvalidateCanvasIfNeeded(nsIPresShell* presShell, nsIContent* node)
// XHTML or something), but chances are we want to. Play it safe.
// Invalidate the viewport.
// Wrap this in a DEFERRED view update batch so we don't try to
// flush out layout here
nsIViewManager::UpdateViewBatch batch(presShell->GetViewManager());
nsIFrame* rootFrame = presShell->GetRootFrame();
rootFrame->InvalidateFrameSubtree();
batch.EndUpdateViewBatch(NS_VMREFRESH_DEFERRED);
}
nsresult
@ -11599,7 +11585,7 @@ nsCSSFrameConstructor::RebuildAllStyleData(nsChangeHint aExtraHint)
return;
// Make sure that the viewmanager will outlive the presshell
nsIViewManager::UpdateViewBatch batch(mPresShell->GetViewManager());
nsCOMPtr<nsIViewManager> vm = mPresShell->GetViewManager();
// Processing the style changes could cause a flush that propagates to
// the parent frame and thus destroys the pres shell.
@ -11615,7 +11601,6 @@ nsCSSFrameConstructor::RebuildAllStyleData(nsChangeHint aExtraHint)
// so we can recalculate while maintaining rule tree immutability
nsresult rv = mPresShell->StyleSet()->BeginReconstruct();
if (NS_FAILED(rv)) {
batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
return;
}
@ -11650,7 +11635,6 @@ nsCSSFrameConstructor::RebuildAllStyleData(nsChangeHint aExtraHint)
// reconstructed will still have their old style context pointers
// until they are destroyed).
mPresShell->StyleSet()->EndReconstruct();
batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
}
void

View File

@ -1568,9 +1568,8 @@ DocumentViewerImpl::Destroy()
// The invalidate that removing this view causes is dropped because
// the Freeze call above sets painting to be suppressed for our
// document. So we do it ourselves and make it happen.
vm->UpdateViewNoSuppression(rootView,
rootView->GetBounds() - rootView->GetPosition(),
NS_VMREFRESH_NO_SYNC);
vm->InvalidateViewNoSuppression(rootView,
rootView->GetBounds() - rootView->GetPosition());
nsIView *rootViewParent = rootView->GetParent();
if (rootViewParent) {
@ -2827,8 +2826,6 @@ DocumentViewerImpl::SetTextZoom(float aTextZoom)
mTextZoom = aTextZoom;
nsIViewManager::UpdateViewBatch batch(GetViewManager());
// Set the text zoom on all children of mContainer (even if our zoom didn't
// change, our children's zoom may be different, though it would be unusual).
// Do this first, in case kids are auto-sizing and post reflow commands on
@ -2845,8 +2842,6 @@ DocumentViewerImpl::SetTextZoom(float aTextZoom)
// And do the external resources
mDocument->EnumerateExternalResources(SetExtResourceTextZoom, &ZoomInfo);
batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
return NS_OK;
}
@ -2868,8 +2863,6 @@ DocumentViewerImpl::SetMinFontSize(PRInt32 aMinFontSize)
mMinFontSize = aMinFontSize;
nsIViewManager::UpdateViewBatch batch(GetViewManager());
// Set the min font on all children of mContainer (even if our min font didn't
// change, our children's min font may be different, though it would be unusual).
// Do this first, in case kids are auto-sizing and post reflow commands on
@ -2886,8 +2879,6 @@ DocumentViewerImpl::SetMinFontSize(PRInt32 aMinFontSize)
mDocument->EnumerateExternalResources(SetExtResourceMinFontSize,
NS_INT32_TO_PTR(aMinFontSize));
batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
return NS_OK;
}
@ -2910,7 +2901,6 @@ DocumentViewerImpl::SetFullZoom(float aFullZoom)
nsCOMPtr<nsIPresShell> shell = pc->GetPresShell();
NS_ENSURE_TRUE(shell, NS_OK);
nsIViewManager::UpdateViewBatch batch(shell->GetViewManager());
if (!mPrintPreviewZoomed) {
mOriginalPrintPreviewScale = pc->GetPrintPreviewScale();
mPrintPreviewZoomed = true;
@ -2929,15 +2919,12 @@ DocumentViewerImpl::SetFullZoom(float aFullZoom)
nsRect rect(nsPoint(0, 0), rootFrame->GetSize());
rootFrame->Invalidate(rect);
}
batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
return NS_OK;
}
#endif
mPageZoom = aFullZoom;
nsIViewManager::UpdateViewBatch batch(GetViewManager());
struct ZoomInfo ZoomInfo = { aFullZoom };
CallChildren(SetChildFullZoom, &ZoomInfo);
@ -2949,8 +2936,6 @@ DocumentViewerImpl::SetFullZoom(float aFullZoom)
// And do the external resources
mDocument->EnumerateExternalResources(SetExtResourceFullZoom, &ZoomInfo);
batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
return NS_OK;
}

View File

@ -141,8 +141,8 @@ typedef struct CapturingContentInfo {
} CapturingContentInfo;
#define NS_IPRESSHELL_IID \
{ 0x4e23d557, 0x741a, 0x4fd0,\
{ 0x91, 0x52, 0x34, 0xe2, 0xb4, 0xef, 0xe8, 0x2e } }
{ 0x3ab5b116, 0x2d73, 0x431c, \
{ 0x9a, 0x4b, 0x6c, 0x91, 0x9e, 0x42, 0x45, 0xc3 } }
// Constants for ScrollContentIntoView() function
#define NS_PRESSHELL_SCROLL_TOP 0
@ -1148,6 +1148,7 @@ public:
virtual bool ShouldIgnoreInvalidation() = 0;
virtual void WillPaint(bool aWillSendDidPaint) = 0;
virtual void DidPaint() = 0;
virtual void ScheduleViewManagerFlush() = 0;
virtual void ClearMouseCaptureOnView(nsIView* aView) = 0;
virtual bool IsVisible() = 0;
virtual void DispatchSynthMouseMove(nsGUIEvent *aEvent, bool aFlushOnHoverChange) = 0;

View File

@ -1081,6 +1081,12 @@ nsPresContext::SetShell(nsIPresShell* aShell)
mAnimationManager->Disconnect();
mAnimationManager = nsnull;
}
if (IsRoot()) {
// Have to cancel our plugin geometry timer, because the
// callback for that depends on a non-null presshell.
static_cast<nsRootPresContext*>(this)->CancelUpdatePluginGeometryTimer();
}
}
}
@ -2354,6 +2360,7 @@ nsRootPresContext::~nsRootPresContext()
NS_ASSERTION(mRegisteredPlugins.Count() == 0,
"All plugins should have been unregistered");
CancelDidPaintTimer();
CancelUpdatePluginGeometryTimer();
}
void
@ -2594,6 +2601,9 @@ nsRootPresContext::UpdatePluginGeometry()
if (!mNeedsToUpdatePluginGeometry)
return;
mNeedsToUpdatePluginGeometry = false;
// Cancel out mUpdatePluginGeometryTimer so it doesn't do a random
// update when we don't actually want one.
CancelUpdatePluginGeometryTimer();
nsIFrame* f = mUpdatePluginGeometryForFrame;
if (f) {
@ -2615,33 +2625,10 @@ nsRootPresContext::UpdatePluginGeometry()
DidApplyPluginGeometryUpdates();
}
void
nsRootPresContext::SynchronousPluginGeometryUpdate()
static void
UpdatePluginGeometryCallback(nsITimer *aTimer, void *aClosure)
{
if (!mNeedsToUpdatePluginGeometry) {
// Nothing to do
return;
}
// Force synchronous paint
nsIPresShell* shell = GetPresShell();
if (!shell)
return;
nsIFrame* rootFrame = shell->GetRootFrame();
if (!rootFrame)
return;
nsCOMPtr<nsIWidget> widget = rootFrame->GetNearestWidget();
if (!widget)
return;
// Force synchronous paint of a single pixel, just to force plugin
// updates to be flushed. Doing plugin updates during paint is the best
// way to ensure that plugin updates are in sync with our content.
widget->Invalidate(nsIntRect(0,0,1,1), true);
// Update plugin geometry just in case that invalidate didn't work
// (e.g. if none of the widget is visible, it might not have processed
// a paint event). Normally this won't need to do anything.
UpdatePluginGeometry();
static_cast<nsRootPresContext*>(aClosure)->UpdatePluginGeometry();
}
void
@ -2651,15 +2638,23 @@ nsRootPresContext::RequestUpdatePluginGeometry(nsIFrame* aFrame)
return;
if (!mNeedsToUpdatePluginGeometry) {
// We'll update the plugin geometry during the next paint in this
// presContext (either from nsPresShell::WillPaint or from
// nsPresShell::DidPaint, depending on the platform) or on the next
// layout flush, whichever comes first. But we may not have anyone
// flush layout, and paints might get optimized away if the old
// plugin geometry covers the whole canvas, so set a backup timer to
// do this too. We want to make sure this won't fire before our
// normal paint notifications, if those would update the geometry,
// so set it for double the refresh driver interval.
mUpdatePluginGeometryTimer = do_CreateInstance("@mozilla.org/timer;1");
if (mUpdatePluginGeometryTimer) {
mUpdatePluginGeometryTimer->
InitWithFuncCallback(UpdatePluginGeometryCallback, this,
nsRefreshDriver::DefaultInterval() * 2,
nsITimer::TYPE_ONE_SHOT);
}
mNeedsToUpdatePluginGeometry = true;
// Dispatch a Gecko event to ensure plugin geometry gets updated
// XXX this really should be done through the refresh driver, once
// all painting happens in the refresh driver
nsCOMPtr<nsIRunnable> event =
NS_NewRunnableMethod(this, &nsRootPresContext::SynchronousPluginGeometryUpdate);
NS_DispatchToMainThread(event);
mUpdatePluginGeometryForFrame = aFrame;
mUpdatePluginGeometryForFrame->PresContext()->
SetContainsUpdatePluginGeometryFrame(true);

View File

@ -1269,14 +1269,6 @@ public:
virtual bool IsRoot() { return true; }
/**
* This method is called off an event to force the plugin geometry to
* be updated. First we try to paint, since updating plugin geometry
* during paint is best for keeping plugins in sync with content.
* But we also force geometry updates in case painting doesn't work.
*/
void SynchronousPluginGeometryUpdate();
/**
* Call this after reflow and scrolling to ensure that the geometry
* of any windowed plugins is updated. aFrame is the root of the
@ -1349,7 +1341,17 @@ protected:
nsRootPresContext* mPresContext;
};
friend class nsPresContext;
void CancelUpdatePluginGeometryTimer()
{
if (mUpdatePluginGeometryTimer) {
mUpdatePluginGeometryTimer->Cancel();
mUpdatePluginGeometryTimer = nsnull;
}
}
nsCOMPtr<nsITimer> mNotifyDidPaintTimer;
nsCOMPtr<nsITimer> mUpdatePluginGeometryTimer;
nsTHashtable<nsPtrHashKey<nsObjectFrame> > mRegisteredPlugins;
// if mNeedsToUpdatePluginGeometry is set, then this is the frame to
// use as the root of the subtree to search for plugin updates, or

View File

@ -1253,6 +1253,8 @@ PresShell::Destroy()
// before we destroy the frame manager, since apparently frame destruction
// sometimes spins the event queue when plug-ins are involved(!).
rd->RemoveLayoutFlushObserver(this);
rd->RevokeViewManagerFlush();
mResizeEvent.Revoke();
if (mAsyncResizeTimerIsActive) {
mAsyncResizeEventTimer->Cancel();
@ -2113,8 +2115,6 @@ PresShell::ResizeReflowIgnoreOverride(nscoord aWidth, nscoord aHeight)
if (!GetPresContext()->SupressingResizeReflow())
{
nsIViewManager::UpdateViewBatch batch(mViewManager);
// Have to make sure that the content notifications are flushed before we
// start messing with the frame model; otherwise we can get content doubling.
mDocument->FlushPendingNotifications(Flush_ContentAndNotify);
@ -2137,6 +2137,7 @@ PresShell::ResizeReflowIgnoreOverride(nscoord aWidth, nscoord aHeight)
// Kick off a top-down reflow
AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Reflow);
nsIViewManager::AutoDisableRefresh refreshBlocker(mViewManager);
mDirtyRoots.RemoveElement(rootFrame);
DoReflow(rootFrame, true);
@ -2144,8 +2145,6 @@ PresShell::ResizeReflowIgnoreOverride(nscoord aWidth, nscoord aHeight)
DidDoReflow(true);
}
batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
}
rootFrame = FrameManager()->GetRootFrame();
@ -2468,17 +2467,6 @@ PresShell::ScrollLine(bool aForward)
scrollFrame->ScrollBy(nsIntPoint(0, aForward ? lineCount : -lineCount),
nsIScrollableFrame::LINES,
nsIScrollableFrame::SMOOTH);
//NEW FOR LINES
// force the update to happen now, otherwise multiple scrolls can
// occur before the update is processed. (bug #7354)
// I'd use Composite here, but it doesn't always work.
// vm->Composite();
nsIViewManager* viewManager = GetViewManager();
if (viewManager) {
viewManager->ForceUpdate();
}
}
return NS_OK;
}
@ -2492,16 +2480,6 @@ PresShell::ScrollCharacter(bool aRight)
scrollFrame->ScrollBy(nsIntPoint(aRight ? 1 : -1, 0),
nsIScrollableFrame::LINES,
nsIScrollableFrame::SMOOTH);
//NEW FOR LINES
// force the update to happen now, otherwise multiple scrolls can
// occur before the update is processed. (bug #7354)
// I'd use Composite here, but it doesn't always work.
// vm->Composite();
nsIViewManager* viewManager = GetViewManager();
if (viewManager) {
viewManager->ForceUpdate();
}
}
return NS_OK;
}
@ -2979,7 +2957,6 @@ PresShell::RecreateFramesFor(nsIContent* aContent)
// to keep the number of entrypoints down.
NS_ASSERTION(mViewManager, "Should have view manager");
nsIViewManager::UpdateViewBatch batch(mViewManager);
// Have to make sure that the content notifications are flushed before we
// start messing with the frame model; otherwise we can get content doubling.
@ -2995,7 +2972,6 @@ PresShell::RecreateFramesFor(nsIContent* aContent)
nsresult rv = mFrameConstructor->ProcessRestyledFrames(changeList);
--mChangeNestCount;
batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
return rv;
}
@ -3633,6 +3609,18 @@ nsresult PresShell::GetLinkLocation(nsIDOMNode* aNode, nsAString& aLocationStrin
return NS_ERROR_FAILURE;
}
void
PresShell::ScheduleViewManagerFlush()
{
nsPresContext* presContext = GetPresContext();
if (presContext) {
presContext->RefreshDriver()->ScheduleViewManagerFlush();
}
if (mDocument) {
mDocument->SetNeedLayoutFlush();
}
}
void
PresShell::DispatchSynthMouseMove(nsGUIEvent *aEvent,
bool aFlushOnHoverChange)
@ -4003,7 +3991,7 @@ PresShell::FlushPendingNotifications(mozFlushType aType)
}
NS_ASSERTION(!isSafeToFlush || mViewManager, "Must have view manager");
// Make sure the view manager stays alive while batching view updates.
// Make sure the view manager stays alive.
nsCOMPtr<nsIViewManager> viewManagerDeathGrip = mViewManager;
if (isSafeToFlush && mViewManager) {
// Processing pending notifications can kill us, and some callers only
@ -4017,11 +4005,6 @@ PresShell::FlushPendingNotifications(mozFlushType aType)
}
}
// Style reresolves not in conjunction with reflows can't cause
// painting or geometry changes, so don't bother with view update
// batching if we only have style reresolve
nsIViewManager::UpdateViewBatch batch(mViewManager);
// We need to make sure external resource documents are flushed too (for
// example, svg filters that reference a filter in an external document
// need the frames in the external document to be constructed for the
@ -4114,15 +4097,11 @@ PresShell::FlushPendingNotifications(mozFlushType aType)
if (rootPresContext) {
rootPresContext->UpdatePluginGeometry();
}
}
PRUint32 updateFlags = NS_VMREFRESH_NO_SYNC;
if (aType >= Flush_Display) {
// Flushing paints, so perform the invalidates and drawing
// immediately
updateFlags = NS_VMREFRESH_IMMEDIATE;
if (!mIsDestroying) {
mViewManager->UpdateWidgetGeometry();
}
}
batch.EndUpdateViewBatch(updateFlags);
}
}
@ -7398,7 +7377,7 @@ PresShell::DoVerifyReflow()
// First synchronously render what we have so far so that we can
// see it.
nsIView* rootView = mViewManager->GetRootView();
mViewManager->UpdateView(rootView, NS_VMREFRESH_IMMEDIATE);
mViewManager->InvalidateView(rootView);
FlushPendingNotifications(Flush_Layout);
mInVerifyReflow = true;
@ -7445,6 +7424,7 @@ PresShell::ProcessReflowCommands(bool aInterruptible)
nsAutoScriptBlocker scriptBlocker;
WillDoReflow();
AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Reflow);
nsIViewManager::AutoDisableRefresh refreshBlocker(mViewManager);
do {
// Send an incremental reflow notification to the target frame.
@ -7593,7 +7573,6 @@ PresShell::Observe(nsISupports* aSubject,
// at interesting times during startup.
if (rootFrame) {
NS_ASSERTION(mViewManager, "View manager must exist");
nsIViewManager::UpdateViewBatch batch(mViewManager);
nsWeakFrame weakRoot(rootFrame);
// Have to make sure that the content notifications are flushed before we
@ -7618,7 +7597,6 @@ PresShell::Observe(nsISupports* aSubject,
--mChangeNestCount;
}
}
batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
}
return NS_OK;
}

View File

@ -330,6 +330,7 @@ public:
virtual bool ShouldIgnoreInvalidation();
virtual void WillPaint(bool aWillSendDidPaint);
virtual void DidPaint();
virtual void ScheduleViewManagerFlush();
virtual void DispatchSynthMouseMove(nsGUIEvent *aEvent, bool aFlushOnHoverChange);
virtual void ClearMouseCaptureOnView(nsIView* aView);
virtual bool IsVisible();

View File

@ -55,6 +55,7 @@
#include "jsapi.h"
#include "nsContentUtils.h"
#include "mozilla/Preferences.h"
#include "nsIViewManager.h"
using mozilla::TimeStamp;
using mozilla::TimeDuration;
@ -73,6 +74,13 @@ nsRefreshDriver::InitializeStatics()
"layout.frame_rate.precise",
false);
}
/* static */ PRInt32
nsRefreshDriver::DefaultInterval()
{
return NSToIntRound(1000.0 / DEFAULT_FRAME_RATE);
}
// Compute the interval to use for the refresh driver timer, in
// milliseconds
PRInt32
@ -112,6 +120,7 @@ nsRefreshDriver::nsRefreshDriver(nsPresContext *aPresContext)
mThrottled(false),
mTestControllingRefreshes(false),
mTimerIsPrecise(false),
mViewManagerFlushIsPending(false),
mLastTimerInterval(0)
{
mRequests.Init();
@ -270,6 +279,7 @@ nsRefreshDriver::ObserverCount() const
sum += mStyleFlushObservers.Length();
sum += mLayoutFlushObservers.Length();
sum += mFrameRequestCallbackDocs.Length();
sum += mViewManagerFlushIsPending;
return sum;
}
@ -431,6 +441,11 @@ nsRefreshDriver::Notify(nsITimer *aTimer)
EnsureTimerStarted(false);
}
if (mViewManagerFlushIsPending) {
mViewManagerFlushIsPending = false;
mPresContext->GetPresShell()->GetViewManager()->ProcessPendingUpdates();
}
if (mThrottled ||
(mTimerIsPrecise !=
(GetRefreshTimerType() == nsITimer::TYPE_REPEATING_PRECISE_CAN_SKIP))) {

View File

@ -176,6 +176,17 @@ public:
return mLayoutFlushObservers.Contains(aShell);
}
/**
* Remember whether our presshell's view manager needs a flush
*/
void ScheduleViewManagerFlush() {
mViewManagerFlushIsPending = true;
EnsureTimerStarted(false);
}
void RevokeViewManagerFlush() {
mViewManagerFlushIsPending = false;
}
/**
* Add a document for which we have nsIFrameRequestCallbacks
*/
@ -227,6 +238,11 @@ public:
mozFlushType aFlushType);
#endif
/**
* Default interval the refresh driver uses, in ms.
*/
static PRInt32 DefaultInterval();
private:
typedef nsTObserverArray<nsARefreshObserver*> ObserverArray;
typedef nsTHashtable<nsISupportsHashKey> RequestTable;
@ -265,6 +281,7 @@ private:
a precise timer. If mTimer is null, this boolean's value can be
anything. */
bool mTimerIsPrecise;
bool mViewManagerFlushIsPending;
// separate arrays for each flush type we support
ObserverArray mObservers[3];

View File

@ -387,15 +387,6 @@ nsComboboxControlFrame::SetFocus(bool aOn, bool aRepaint)
// rect to be drawn. This is much faster than ReResolvingStyle
// Bug 32920
Invalidate(nsRect(0,0,mRect.width,mRect.height));
// Make sure the content area gets updated for where the dropdown was
// This is only needed for embedding, the focus may go to
// the chrome that is not part of the Gecko system (Bug 83493)
// XXX this is rather inefficient
nsIViewManager* vm = PresContext()->GetPresShell()->GetViewManager();
if (vm) {
vm->UpdateAllViews(NS_VMREFRESH_NO_SYNC);
}
}
void

View File

@ -4644,22 +4644,15 @@ nsIFrame::InvalidateRoot(const nsRect& aDamageRect, PRUint32 aFlags)
}
}
PRUint32 flags =
(aFlags & INVALIDATE_IMMEDIATE) ? NS_VMREFRESH_IMMEDIATE : NS_VMREFRESH_NO_SYNC;
nsRect rect = aDamageRect;
nsRegion* excludeRegion = static_cast<nsRegion*>
(Properties().Get(DeferInvalidatesProperty()));
if (excludeRegion) {
flags = NS_VMREFRESH_DEFERRED;
if (aFlags & INVALIDATE_EXCLUDE_CURRENT_PAINT) {
nsRegion r;
r.Sub(rect, *excludeRegion);
if (r.IsEmpty())
return;
rect = r.GetBounds();
}
if (excludeRegion && (aFlags & INVALIDATE_EXCLUDE_CURRENT_PAINT)) {
nsRegion r;
r.Sub(rect, *excludeRegion);
if (r.IsEmpty())
return;
rect = r.GetBounds();
}
if (!(aFlags & INVALIDATE_NO_UPDATE_LAYER_TREE)) {
@ -4668,7 +4661,7 @@ nsIFrame::InvalidateRoot(const nsRect& aDamageRect, PRUint32 aFlags)
nsIView* view = GetView();
NS_ASSERTION(view, "This can only be called on frames with views");
view->GetViewManager()->UpdateViewNoSuppression(view, rect, flags);
view->GetViewManager()->InvalidateViewNoSuppression(view, rect);
}
void

View File

@ -1533,19 +1533,6 @@ nsHTMLFramesetFrame::MouseDrag(nsPresContext* aPresContext,
ENSURE_TRUE(weakFrame.IsAlive());
if (change != 0) {
mDrag.Reset(mDragger->mVertical, mDragger->mPrevNeighbor, change, this);
nsIFrame* parentFrame = GetParent();
if (!parentFrame) {
return;
}
// Update the view immediately (make drag appear snappier)
nsIViewManager* vm = aPresContext->GetPresShell()->GetViewManager();
if (vm) {
nsIView* root = vm->GetRootView();
if (root) {
vm->UpdateView(root, NS_VMREFRESH_IMMEDIATE);
}
}
}
}

View File

@ -1383,7 +1383,7 @@ void BuildTextRunsScanner::FlushFrames(bool aFlushLineBreaks, bool aSuppressTrai
mNextRunContextInfo |= nsTextFrameUtils::INCOMING_ARABICCHAR;
}
} else {
nsAutoTArray<PRUint8,BIG_TEXT_NODE_SIZE> buffer;
AutoFallibleTArray<PRUint8,BIG_TEXT_NODE_SIZE> buffer;
PRUint32 bufferSize = mMaxTextLength*(mDoubleByteText ? 2 : 1);
if (bufferSize < mMaxTextLength || bufferSize == PR_UINT32_MAX ||
!buffer.AppendElements(bufferSize)) {
@ -1825,12 +1825,12 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer)
if (mDoubleByteText) {
// Need to expand the text. First transform it into a temporary buffer,
// then expand.
nsAutoTArray<PRUint8,BIG_TEXT_NODE_SIZE> tempBuf;
if (!tempBuf.AppendElements(contentLength)) {
AutoFallibleTArray<PRUint8,BIG_TEXT_NODE_SIZE> tempBuf;
PRUint8* bufStart = tempBuf.AppendElements(contentLength);
if (!bufStart) {
DestroyUserData(userDataToDestroy);
return nsnull;
}
PRUint8* bufStart = tempBuf.Elements();
PRUint8* end = nsTextFrameUtils::TransformText(
reinterpret_cast<const PRUint8*>(frag->Get1b()) + contentStart, contentLength,
bufStart, compression, &mNextRunContextInfo, &builder, &analysisFlags);
@ -2029,11 +2029,13 @@ BuildTextRunsScanner::SetupLineBreakerContext(gfxTextRun *aTextRun)
{
AutoFallibleTArray<PRUint8,BIG_TEXT_NODE_SIZE> buffer;
PRUint32 bufferSize = mMaxTextLength*(mDoubleByteText ? 2 : 1);
if (bufferSize < mMaxTextLength || bufferSize == PR_UINT32_MAX ||
!buffer.AppendElements(bufferSize)) {
if (bufferSize < mMaxTextLength || bufferSize == PR_UINT32_MAX) {
return false;
}
void *textPtr = buffer.AppendElements(bufferSize);
if (!textPtr) {
return false;
}
void *textPtr = buffer.Elements();
gfxSkipCharsBuilder builder;
@ -2106,11 +2108,11 @@ BuildTextRunsScanner::SetupLineBreakerContext(gfxTextRun *aTextRun)
// Need to expand the text. First transform it into a temporary buffer,
// then expand.
AutoFallibleTArray<PRUint8,BIG_TEXT_NODE_SIZE> tempBuf;
if (!tempBuf.AppendElements(contentLength)) {
PRUint8* bufStart = tempBuf.AppendElements(contentLength);
if (!bufStart) {
DestroyUserData(userDataToDestroy);
return false;
}
PRUint8* bufStart = tempBuf.Elements();
PRUint8* end = nsTextFrameUtils::TransformText(
reinterpret_cast<const PRUint8*>(frag->Get1b()) + contentStart, contentLength,
bufStart, compression, &mNextRunContextInfo, &builder, &analysisFlags);
@ -5098,10 +5100,12 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx,
const nsCharClipDisplayItem::ClipEdges& aClipEdges)
{
// Figure out which selections control the colors to use for each character.
nsAutoTArray<SelectionDetails*,BIG_TEXT_NODE_SIZE> prevailingSelectionsBuffer;
if (!prevailingSelectionsBuffer.AppendElements(aContentLength))
AutoFallibleTArray<SelectionDetails*,BIG_TEXT_NODE_SIZE> prevailingSelectionsBuffer;
SelectionDetails** prevailingSelections =
prevailingSelectionsBuffer.AppendElements(aContentLength);
if (!prevailingSelections) {
return false;
SelectionDetails** prevailingSelections = prevailingSelectionsBuffer.Elements();
}
SelectionType allTypes = 0;
for (PRUint32 i = 0; i < aContentLength; ++i) {
@ -5221,10 +5225,12 @@ nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx,
return;
// Figure out which characters will be decorated for this selection.
nsAutoTArray<SelectionDetails*, BIG_TEXT_NODE_SIZE> selectedCharsBuffer;
if (!selectedCharsBuffer.AppendElements(aContentLength))
AutoFallibleTArray<SelectionDetails*, BIG_TEXT_NODE_SIZE> selectedCharsBuffer;
SelectionDetails** selectedChars =
selectedCharsBuffer.AppendElements(aContentLength);
if (!selectedChars) {
return;
SelectionDetails** selectedChars = selectedCharsBuffer.Elements();
}
for (PRUint32 i = 0; i < aContentLength; ++i) {
selectedChars[i] = nsnull;
}
@ -6600,7 +6606,7 @@ nsTextFrame::AddInlineMinWidthForFlow(nsRenderingContext *aRenderingContext,
PRUint32 start =
FindStartAfterSkippingWhitespace(&provider, aData, textStyle, &iter, flowEndInTextRun);
nsAutoTArray<bool,BIG_TEXT_NODE_SIZE> hyphBuffer;
AutoFallibleTArray<bool,BIG_TEXT_NODE_SIZE> hyphBuffer;
bool *hyphBreakBefore = nsnull;
if (hyphenating) {
hyphBreakBefore = hyphBuffer.AppendElements(flowEndInTextRun - start);

View File

@ -3,6 +3,10 @@
style="overflow: -moz-hidden-unscrollable;"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<html:input value="lime"/>
<button label="Credits" accesskey="C"/>
<!--
pointer-events: none so that our look doesn't depend on
mouse position
-->
<button label="Credits" accesskey="C" style="pointer-events: none"/>
</somenode>

View File

@ -10,5 +10,9 @@
input element. Not using -moz-hidden-unscrollable
causes this problem to show up for reasons unknown.
-->
<button label="Credits" accesskey="C"/>
<!--
pointer-events: none so that our look doesn't depend on
mouse position
-->
<button label="Credits" accesskey="C" style="pointer-events: none"/>
</somenode>

View File

@ -9,6 +9,7 @@ html, body {
display: -moz-box;
margin: 0; padding: 0;
width: 100%; height: 100%;
pointer-events: none;
}
body > div {

View File

@ -9,6 +9,8 @@ html, body {
display: -moz-box;
margin: 0; padding: 0;
width: 100%; height: 100%;
/* Disable pointer-events so we don't get weird hover artifacts */
pointer-events: none;
}
body > div {

View File

@ -0,0 +1,11 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<svg xmlns="http://www.w3.org/2000/svg">
<title>Reference to check whitespace handling</title>
<!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=717870 -->
<text x="10" y="50" font-size="50">A B</text>
</svg>

After

Width:  |  Height:  |  Size: 340 B

View File

@ -0,0 +1,23 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<svg xmlns="http://www.w3.org/2000/svg" class="reftest-wait" onload="m();">
<title>Testcase to check whitespace handling</title>
<!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=717870 -->
<text id="t" x="10" y="50" font-size="50">A </text>
<script>
function m()
{
// Force frame construction
document.documentElement.getBoundingClientRect();
// A dynamic change
document.getElementById("t").appendChild(document.createTextNode("B"));
document.documentElement.removeAttribute("class");
}
</script>
</svg>

After

Width:  |  Height:  |  Size: 691 B

View File

@ -99,6 +99,7 @@ include svg-integration/reftest.list
fails-if(/^Windows\x20NT\x205\.1/.test(http.oscpu)) == dynamic-text-04.svg dynamic-text-04-ref.svg # bug 421587 for WinXP
== dynamic-text-05.svg pass.svg
== dynamic-text-06.svg pass.svg
== dynamic-text-07.svg dynamic-text-07-ref.svg
== dynamic-textPath-01.svg dynamic-textPath-01-ref.svg
== dynamic-use-01.svg pass.svg
== dynamic-use-02.svg pass.svg

View File

@ -121,10 +121,16 @@ public:
return mContent->GetText()->GetLength() == 0;
}
void SetTrimLeadingWhitespace(bool aTrimLeadingWhitespace) {
mTrimLeadingWhitespace = aTrimLeadingWhitespace;
if (mTrimLeadingWhitespace != aTrimLeadingWhitespace) {
mTrimLeadingWhitespace = aTrimLeadingWhitespace;
ClearTextRun();
}
}
void SetTrimTrailingWhitespace(bool aTrimTrailingWhitespace) {
mTrimTrailingWhitespace = aTrimTrailingWhitespace;
if (mTrimTrailingWhitespace != aTrimTrailingWhitespace) {
mTrimTrailingWhitespace = aTrimTrailingWhitespace;
ClearTextRun();
}
}
bool EndsWithWhitespace() const;
bool IsAllWhitespace() const;
@ -193,7 +199,10 @@ public:
NS_IMETHOD_(nsSVGGlyphFrame *) GetFirstGlyphFrame();
NS_IMETHOD_(nsSVGGlyphFrame *) GetNextGlyphFrame();
NS_IMETHOD_(void) SetWhitespaceCompression(bool aCompressWhitespace) {
mCompressWhitespace = aCompressWhitespace;
if (mCompressWhitespace != aCompressWhitespace) {
mCompressWhitespace = aCompressWhitespace;
ClearTextRun();
}
}
protected:

View File

@ -298,9 +298,13 @@ nsSVGTextFrame::SetWhitespaceHandling(nsSVGGlyphFrame *aFrame)
{
SetWhitespaceCompression();
nsSVGGlyphFrame* firstFrame = aFrame;
bool trimLeadingWhitespace = true;
nsSVGGlyphFrame* lastNonWhitespaceFrame = aFrame;
// If the previous frame ended with whitespace
// then display of leading whitespace should be suppressed
// when we are compressing whitespace.
while (aFrame) {
if (!aFrame->IsAllWhitespace()) {
lastNonWhitespaceFrame = aFrame;
@ -312,6 +316,16 @@ nsSVGTextFrame::SetWhitespaceHandling(nsSVGGlyphFrame *aFrame)
aFrame = aFrame->GetNextGlyphFrame();
}
// When there is only whitespace left we need to trim off
// the end of the last frame that isn't entirely whitespace.
// Making sure that we reset earlier frames as they may once
// have been the last non-whitespace frame.
aFrame = firstFrame;
while (aFrame != lastNonWhitespaceFrame) {
aFrame->SetTrimTrailingWhitespace(false);
aFrame = aFrame->GetNextGlyphFrame();
}
lastNonWhitespaceFrame->SetTrimTrailingWhitespace(true);
}

View File

@ -562,7 +562,7 @@ void nsLayoutDebuggingTools::ForceRefresh()
return;
nsIView* root = vm->GetRootView();
if (root) {
vm->UpdateView(root, NS_VMREFRESH_IMMEDIATE);
vm->InvalidateView(root);
}
}

View File

@ -559,15 +559,6 @@ nsListBoxBodyFrame::ScrollByLines(PRInt32 aNumLines)
ScrollToIndex(scrollIndex);
// we have to do a sync update for mac because if we scroll too quickly
// w/out going back to the main event loop we can easily scroll the wrong
// bits and it looks like garbage (bug 63465).
// XXXbz is this seriously still needed?
// I'd use Composite here, but it doesn't always work.
// vm->Composite();
PresContext()->GetPresShell()->GetViewManager()->ForceUpdate();
return NS_OK;
}

View File

@ -593,25 +593,34 @@ abstract public class GeckoApp
mLastUri = lastHistoryEntry.mUri;
mLastTitle = lastHistoryEntry.mTitle;
Bitmap bitmap = mSoftwareLayerClient.getBitmap();
if (bitmap != null) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 0, bos);
mLastScreen = bos.toByteArray();
// Make a thumbnail for the given tab, if it's still selected
// NOTE: bitmap is recycled in updateThumbnail
if (tab == mThumbnailTab) {
if (mThumbnailTab.getURL().equals("about:home"))
mThumbnailTab.updateThumbnail(null);
else
mThumbnailTab.updateThumbnail(bitmap);
}
processThumbnail(tab, bitmap, bos.toByteArray());
} else {
mLastScreen = null;
GeckoAppShell.sendEventToGecko(
new GeckoEvent("Tab:Screenshot",
"{\"width\": \"" + mSoftwareLayerClient.getWidth() + "\", " +
"\"height\": \"" + mSoftwareLayerClient.getHeight() + "\", " +
"\"tabID\": \"" + tab.getId() + "\" }"));
}
}
}
}
void processThumbnail(Tab thumbnailTab, Bitmap bitmap, byte[] compressed) {
if (Tabs.getInstance().isSelectedTab(thumbnailTab))
mLastScreen = compressed;
if (thumbnailTab.getURL().equals("about:home")) {
thumbnailTab.updateThumbnail(null);
return;
}
if (bitmap == null)
bitmap = BitmapFactory.decodeByteArray(compressed, 0, compressed.length);
thumbnailTab.updateThumbnail(bitmap);
}
private void maybeCancelFaviconLoad(Tab tab) {
long faviconLoadId = tab.getFaviconLoadId();
@ -898,6 +907,10 @@ abstract public class GeckoApp
Log.i(LOGTAG, "Destroyed a tab");
int tabId = message.getInt("tabID");
handleCloseTab(tabId);
} else if (event.equals("Tab:ScreenshotData")) {
int tabId = message.getInt("tabID");
Tab tab = Tabs.getInstance().getTab(tabId);
processThumbnail(tab, null, Base64.decode(message.getString("data").substring(22), Base64.DEFAULT));
} else if (event.equals("Tab:Selected")) {
int tabId = message.getInt("tabID");
Log.i(LOGTAG, "Switched to tab: " + tabId);
@ -1534,6 +1547,7 @@ abstract public class GeckoApp
GeckoAppShell.registerGeckoEventListener("Tab:Added", GeckoApp.mAppContext);
GeckoAppShell.registerGeckoEventListener("Tab:Closed", GeckoApp.mAppContext);
GeckoAppShell.registerGeckoEventListener("Tab:Selected", GeckoApp.mAppContext);
GeckoAppShell.registerGeckoEventListener("Tab:ScreenshotData", GeckoApp.mAppContext);
GeckoAppShell.registerGeckoEventListener("Doorhanger:Add", GeckoApp.mAppContext);
GeckoAppShell.registerGeckoEventListener("Doorhanger:Remove", GeckoApp.mAppContext);
GeckoAppShell.registerGeckoEventListener("Menu:Add", GeckoApp.mAppContext);
@ -1770,6 +1784,7 @@ abstract public class GeckoApp
GeckoAppShell.unregisterGeckoEventListener("Tab:Added", GeckoApp.mAppContext);
GeckoAppShell.unregisterGeckoEventListener("Tab:Closed", GeckoApp.mAppContext);
GeckoAppShell.unregisterGeckoEventListener("Tab:Selected", GeckoApp.mAppContext);
GeckoAppShell.unregisterGeckoEventListener("Tab:ScreenshotData", GeckoApp.mAppContext);
GeckoAppShell.unregisterGeckoEventListener("Doorhanger:Add", GeckoApp.mAppContext);
GeckoAppShell.unregisterGeckoEventListener("Menu:Add", GeckoApp.mAppContext);
GeckoAppShell.unregisterGeckoEventListener("Menu:Remove", GeckoApp.mAppContext);

View File

@ -118,6 +118,13 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
mTileLayer = new MultiTileLayer(mCairoImage, TILE_SIZE);
}
public int getWidth() {
return mBufferSize.width;
}
public int getHeight() {
return mBufferSize.height;
}
protected void finalize() throws Throwable {
try {
@ -274,13 +281,19 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
if (mBuffer == null || mBufferSize.width <= 0 || mBufferSize.height <= 0)
return null;
try {
Bitmap b = Bitmap.createBitmap(mBufferSize.width, mBufferSize.height,
CairoUtils.cairoFormatTobitmapConfig(mFormat));
Bitmap b = null;
if (mTileLayer instanceof MultiTileLayer)
if (mTileLayer instanceof MultiTileLayer) {
b = Bitmap.createBitmap(mBufferSize.width, mBufferSize.height,
CairoUtils.cairoFormatTobitmapConfig(mFormat));
copyPixelsFromMultiTileLayer(b);
else
} else if (mTileLayer instanceof SingleTileLayer) {
b = Bitmap.createBitmap(mBufferSize.width, mBufferSize.height,
CairoUtils.cairoFormatTobitmapConfig(mFormat));
b.copyPixelsFromBuffer(mBuffer.asIntBuffer());
} else {
Log.w(LOGTAG, "getBitmap() called on a layer (" + mTileLayer + ") we don't know how to get a bitmap from");
}
return b;
} catch (OutOfMemoryError oom) {

View File

@ -208,6 +208,7 @@ var BrowserApp = {
Services.obs.addObserver(this, "Tab:Load", false);
Services.obs.addObserver(this, "Tab:Select", false);
Services.obs.addObserver(this, "Tab:Close", false);
Services.obs.addObserver(this, "Tab:Screenshot", false);
Services.obs.addObserver(this, "Session:Back", false);
Services.obs.addObserver(this, "Session:Forward", false);
Services.obs.addObserver(this, "Session:Reload", false);
@ -470,6 +471,14 @@ var BrowserApp = {
this._tabs.splice(this._tabs.indexOf(aTab), 1);
},
screenshotTab: function screenshotTab(aData) {
let json = JSON.parse(aData);
let tab = this.getTabForId(parseInt(json.tabID));
let width = parseInt(json.width);
let height = parseInt(json.height);
tab.screenshot(width, height);
},
selectTab: function selectTab(aTab) {
if (aTab != null) {
this.selectedTab = aTab;
@ -823,6 +832,8 @@ var BrowserApp = {
this.selectTab(this.getTabForId(parseInt(aData)));
} else if (aTopic == "Tab:Close") {
this.closeTab(this.getTabForId(parseInt(aData)));
} else if (aTopic == "Tab:Screenshot") {
this.screenshotTab(aData);
} else if (aTopic == "Browser:Quit") {
this.quit();
} else if (aTopic == "SaveAs:PDF") {
@ -1467,6 +1478,26 @@ Tab.prototype = {
this.updateTransform();
},
screenshot: function(aWidth, aHeight) {
if (!this.browser || !this.browser.contentWindow)
return;
let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
canvas.setAttribute("width", aWidth);
canvas.setAttribute("height", aHeight);
let ctx = canvas.getContext("2d");
ctx.drawWindow(this.browser.contentWindow, 0, 0, aWidth, aHeight, "rgb(255, 255, 255)");
let message = {
gecko: {
type: "Tab:ScreenshotData",
tabID: this.id,
width: aWidth,
height: aHeight,
data: canvas.toDataURL()
}
};
sendMessageToJava(message);
},
updateTransform: function() {
let hasZoom = (Math.abs(this._viewport.zoom - 1.0) >= 1e-6);
let x = this._viewport.offsetX + Math.round(-this.viewportExcess.x * this._viewport.zoom);

View File

@ -777,7 +777,7 @@ SpdySession::HandleSynStream(SpdySession *self)
NS_ABORT_IF_FALSE(self->mFrameControlType == CONTROL_TYPE_SYN_STREAM,
"wrong control type");
if (self->mFrameDataSize < 12) {
if (self->mFrameDataSize < 18) {
LOG3(("SpdySession::HandleSynStream %p SYN_STREAM too short data=%d",
self, self->mFrameDataSize));
return NS_ERROR_ILLEGAL_VALUE;
@ -785,9 +785,12 @@ SpdySession::HandleSynStream(SpdySession *self)
PRUint32 streamID =
PR_ntohl(reinterpret_cast<PRUint32 *>(self->mFrameBuffer.get())[2]);
PRUint32 associatedID =
PR_ntohl(reinterpret_cast<PRUint32 *>(self->mFrameBuffer.get())[3]);
LOG3(("SpdySession::HandleSynStream %p recv SYN_STREAM (push) for ID 0x%X.",
self, streamID));
LOG3(("SpdySession::HandleSynStream %p recv SYN_STREAM (push) "
"for ID 0x%X associated with 0x%X.",
self, streamID, associatedID));
if (streamID & 0x01) { // test for odd stream ID
LOG3(("SpdySession::HandleSynStream %p recvd SYN_STREAM id must be even.",
@ -802,6 +805,15 @@ SpdySession::HandleSynStream(SpdySession *self)
if (streamID >= kMaxStreamID)
self->mShouldGoAway = true;
// Need to decompress the headers even though we aren't using them yet in
// order to keep the compression context consistent for other syn_reply frames
nsresult rv = self->DownstreamUncompress(self->mFrameBuffer + 18,
self->mFrameDataSize - 10);
if (NS_FAILED(rv)) {
LOG(("SpdySession::HandleSynStream uncompress failed\n"));
return rv;
}
// todo populate cache. For now, just reject server push p3
self->GenerateRstStream(RST_REFUSED_STREAM, streamID);
self->ChangeDownstreamState(BUFFERING_FRAME_HEADER);
@ -872,8 +884,10 @@ SpdySession::HandleSynReply(SpdySession *self)
nsresult rv = self->DownstreamUncompress(self->mFrameBuffer + 14,
self->mFrameDataSize - 6);
if (NS_FAILED(rv))
if (NS_FAILED(rv)) {
LOG(("SpdySession::HandleSynReply uncompress failed\n"));
return rv;
}
Telemetry::Accumulate(Telemetry::SPDY_SYN_REPLY_SIZE,
self->mFrameDataSize - 6);

View File

@ -328,9 +328,6 @@ nsHttpChannel::Connect(bool firstTime)
return NS_ERROR_DOCUMENT_NOT_CACHED;
}
// check to see if authorization headers should be included
mAuthProvider->AddAuthorizationHeaders();
if (mLoadFlags & LOAD_NO_NETWORK_IO) {
return NS_ERROR_DOCUMENT_NOT_CACHED;
}
@ -3742,6 +3739,9 @@ nsHttpChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *context)
}
AddCookiesToRequest();
// check to see if authorization headers should be included
mAuthProvider->AddAuthorizationHeaders();
// notify "http-on-modify-request" observers
gHttpHandler->OnModifyRequest(this);

View File

@ -230,7 +230,6 @@ function handleLoad(aEvent) {
var pb = get_PBSvc();
if (!pb) { // Private Browsing might not be available
ok(true, "Private browsing service is not available");
SimpleTest.finish();
} else {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');

View File

@ -51,7 +51,6 @@ function handleLoad(aEvent) {
var pb = get_PBSvc();
if (!pb) { // Private Browsing might not be available
ok(true, "Private browsing service is not available");
SimpleTest.finish();
} else {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');

View File

@ -86,7 +86,7 @@
#endif
// Redefine the macros for platforms where SPS is supported.
#if defined(ANDROID) || defined(XP_UNIX) || defined(XP_MACOSX) || defined(XP_WIN)
#if defined(ANDROID) || defined(__linux__) || defined(XP_MACOSX) || defined(XP_WIN)
#include "sps_sampler.h"

View File

@ -48,8 +48,8 @@ class nsRegion;
class nsDeviceContext;
#define NS_IVIEWMANAGER_IID \
{ 0x1262a33f, 0xc19f, 0x4e5b, \
{ 0x85, 0x00, 0xab, 0xf3, 0x7d, 0xcf, 0x30, 0x1d } }
{ 0x540610a6, 0x4fdd, 0x4ae3, \
{ 0x9b, 0xdb, 0xa6, 0x4d, 0x8b, 0xca, 0x02, 0x0f } }
class nsIViewManager : public nsISupports
{
@ -116,23 +116,12 @@ public:
*/
NS_IMETHOD FlushDelayedResize(bool aDoReflow) = 0;
/**
* Called to force a redrawing of any dirty areas.
*/
// XXXbz why is this exposed? Shouldn't update view batches handle this?
// It's not like Composite() does what's expected inside a view update batch
// anyway, since dirty areas may not have been invalidated on the widget yet
// and widget changes may not have been propagated yet. Maybe this should
// call FlushPendingInvalidates()?
NS_IMETHOD Composite(void) = 0;
/**
* Called to inform the view manager that the entire area of a view
* is dirty and needs to be redrawn.
* @param aView view to paint. should be root view
* @param aUpdateFlags see bottom of nsIViewManager.h for description
*/
NS_IMETHOD UpdateView(nsIView *aView, PRUint32 aUpdateFlags) = 0;
NS_IMETHOD InvalidateView(nsIView *aView) = 0;
/**
* Called to inform the view manager that some portion of a view is dirty and
@ -140,17 +129,13 @@ public:
* space. Does not check for paint suppression.
* @param aView view to paint. should be root view
* @param rect rect to mark as damaged
* @param aUpdateFlags see bottom of nsIViewManager.h for description
*/
NS_IMETHOD UpdateViewNoSuppression(nsIView *aView, const nsRect &aRect,
PRUint32 aUpdateFlags) = 0;
NS_IMETHOD InvalidateViewNoSuppression(nsIView *aView, const nsRect &aRect) = 0;
/**
* Called to inform the view manager that it should redraw all views.
* @param aView view to paint. should be root view
* @param aUpdateFlags see bottom of nsIViewManager.h for description
* Called to inform the view manager that it should invalidate all views.
*/
NS_IMETHOD UpdateAllViews(PRUint32 aUpdateFlags) = 0;
NS_IMETHOD InvalidateAllViews() = 0;
/**
* Called to dispatch an event to the appropriate view. Often called
@ -273,76 +258,42 @@ public:
*/
NS_IMETHOD GetDeviceContext(nsDeviceContext *&aContext) = 0;
class UpdateViewBatch {
/**
* A stack class for disallowing changes that would enter painting. For
* example, popup widgets shouldn't be resized during reflow, since doing so
* might cause synchronous painting inside reflow which is forbidden.
* While refresh is disabled, widget geometry changes are deferred and will
* be handled later, either from the refresh driver or from an NS_WILL_PAINT
* event.
* We don't want to defer widget geometry changes all the time. Resizing a
* popup from script doesn't need to be deferred, for example, especially
* since popup widget geometry is observable from script and expected to
* update synchronously.
*/
class NS_STACK_CLASS AutoDisableRefresh {
public:
UpdateViewBatch() {}
/**
* prevents the view manager from refreshing. allows UpdateView()
* to notify widgets of damaged regions that should be repainted
* when the batch is ended. Call EndUpdateViewBatch on this object
* before it is destroyed
* @return error status
*/
UpdateViewBatch(nsIViewManager* aVM) {
AutoDisableRefresh(nsIViewManager* aVM) {
if (aVM) {
mRootVM = aVM->BeginUpdateViewBatch();
mRootVM = aVM->IncrementDisableRefreshCount();
}
}
~UpdateViewBatch() {
NS_ASSERTION(!mRootVM, "Someone forgot to call EndUpdateViewBatch!");
}
/**
* See the constructor, this lets you "fill in" a blank UpdateViewBatch.
*/
void BeginUpdateViewBatch(nsIViewManager* aVM) {
NS_ASSERTION(!mRootVM, "already started a batch!");
if (aVM) {
mRootVM = aVM->BeginUpdateViewBatch();
~AutoDisableRefresh() {
if (mRootVM) {
mRootVM->DecrementDisableRefreshCount();
}
}
/**
* allow the view manager to refresh any damaged areas accumulated
* after the BeginUpdateViewBatch() call. this may cause a
* synchronous paint to occur inside the call if aUpdateFlags
* NS_VMREFRESH_IMMEDIATE is set.
*
* If this is not the outermost view batch command, then this does
* nothing except that the specified flags are remembered. When the
* outermost batch finally ends, we merge together all the flags for the
* inner batches in the following way:
* -- If any batch specified NS_VMREFRESH_IMMEDIATE, then we use that flag
* (i.e. there is a synchronous paint under the last EndUpdateViewBatch)
* -- Otherwise if any batch specified NS_VMREFERSH_DEFERRED, then we use
* that flag (i.e. invalidation is deferred until the processing of an
* Invalidate PLEvent)
* -- Otherwise all batches specified NS_VMREFRESH_NO_SYNC and we honor
* that; all widgets are invalidated normally and will be painted the next
* time the toolkit chooses to update them.
*
* @param aUpdateFlags see bottom of nsIViewManager.h for
* description @return error status
*/
void EndUpdateViewBatch(PRUint32 aUpdateFlags) {
if (!mRootVM)
return;
mRootVM->EndUpdateViewBatch(aUpdateFlags);
mRootVM = nsnull;
}
private:
UpdateViewBatch(const UpdateViewBatch& aOther);
const UpdateViewBatch& operator=(const UpdateViewBatch& aOther);
AutoDisableRefresh(const AutoDisableRefresh& aOther);
const AutoDisableRefresh& operator=(const AutoDisableRefresh& aOther);
nsCOMPtr<nsIViewManager> mRootVM;
};
private:
friend class UpdateViewBatch;
virtual nsIViewManager* BeginUpdateViewBatch(void) = 0;
NS_IMETHOD EndUpdateViewBatch(PRUint32 aUpdateFlags) = 0;
private:
friend class AutoDisableRefresh;
virtual nsIViewManager* IncrementDisableRefreshCount() = 0;
virtual void DecrementDisableRefreshCount() = 0;
public:
/**
@ -351,16 +302,6 @@ public:
*/
NS_IMETHOD GetRootWidget(nsIWidget **aWidget) = 0;
/**
* Force update of view manager widget
* Callers should use UpdateView(view, NS_VMREFRESH_IMMEDIATE) in most cases instead
* @result error status
*/
// XXXbz Callers seem to be confused about this one... and it doesn't play
// right with view update batching at all (will miss updates). Maybe this
// should call FlushPendingInvalidates()?
NS_IMETHOD ForceUpdate() = 0;
/**
* Indicate whether the viewmanager is currently painting
*
@ -383,25 +324,19 @@ public:
* the nearest enclosing popup or the root view for the root document.
*/
static nsIView* GetDisplayRootFor(nsIView* aView);
/**
* Flush the accumulated dirty region to the widget and update widget
* geometry.
*/
virtual void ProcessPendingUpdates()=0;
/**
* Just update widget geometry without flushing the dirty region
*/
virtual void UpdateWidgetGeometry() = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIViewManager, NS_IVIEWMANAGER_IID)
// Paint timing mode flags
// intermediate: do no special timing processing; repaint when the
// toolkit issues an expose event (which will happen *before* PLEvent
// processing). This is essentially the default.
#define NS_VMREFRESH_NO_SYNC 0
// least immediate: we suppress invalidation, storing dirty areas in
// views, and post an Invalidate PLEvent. The Invalidate event gets
// processed after toolkit events such as window resize events!
// This is only usable with EndUpdateViewBatch and EnableRefresh.
#define NS_VMREFRESH_DEFERRED 0x0001
// most immediate: force a call to nsViewManager::Composite, which
// synchronously updates the window(s) right away before returning
#define NS_VMREFRESH_IMMEDIATE 0x0002
#endif // nsIViewManager_h___

View File

@ -351,7 +351,7 @@ void nsView::SetPosition(nscoord aX, nscoord aY)
NS_ASSERTION(GetParent() || (aX == 0 && aY == 0),
"Don't try to move the root widget to something non-zero");
ResetWidgetBounds(true, true, false);
ResetWidgetBounds(true, false);
}
void nsIView::SetInvalidationDimensions(const nsRect* aRect)
@ -359,22 +359,23 @@ void nsIView::SetInvalidationDimensions(const nsRect* aRect)
return Impl()->SetInvalidationDimensions(aRect);
}
void nsView::ResetWidgetBounds(bool aRecurse, bool aMoveOnly,
bool aInvalidateChangedSize) {
void nsView::ResetWidgetBounds(bool aRecurse, bool aForceSync)
{
if (mWindow) {
// If our view manager has refresh disabled, then do nothing; the view
// manager will set our position when refresh is reenabled. Just let it
// know that it has pending updates.
if (!mViewManager->IsRefreshEnabled()) {
if (!aForceSync) {
// Don't change widget geometry synchronously, since that can
// cause synchronous painting.
mViewManager->PostPendingUpdate();
return;
} else {
DoResetWidgetBounds(false, true);
}
return;
}
DoResetWidgetBounds(aMoveOnly, aInvalidateChangedSize);
} else if (aRecurse) {
if (aRecurse) {
// reposition any widgets under this view
for (nsView* v = GetFirstChild(); v; v = v->GetNextSibling()) {
v->ResetWidgetBounds(true, aMoveOnly, aInvalidateChangedSize);
v->ResetWidgetBounds(true, aForceSync);
}
}
}
@ -492,7 +493,7 @@ void nsView::SetDimensions(const nsRect& aRect, bool aPaint, bool aResizeWidget)
mDimBounds = dims;
if (aResizeWidget) {
ResetWidgetBounds(false, false, aPaint);
ResetWidgetBounds(false, false);
}
}

View File

@ -181,7 +181,7 @@ public:
void SetTopMost(bool aTopMost) { aTopMost ? mVFlags |= NS_VIEW_FLAG_TOPMOST : mVFlags &= ~NS_VIEW_FLAG_TOPMOST; }
bool IsTopMost() { return((mVFlags & NS_VIEW_FLAG_TOPMOST) != 0); }
void ResetWidgetBounds(bool aRecurse, bool aMoveOnly, bool aInvalidateChangedSize);
void ResetWidgetBounds(bool aRecurse, bool aForceSync);
void AssertNoWindow();
void NotifyEffectiveVisibilityChanged(bool aEffectivelyVisible);

View File

@ -80,21 +80,6 @@
#define NSCOORD_NONE PR_INT32_MIN
void
nsViewManager::PostInvalidateEvent()
{
NS_ASSERTION(IsRootVM(), "Caller screwed up");
if (!mInvalidateEvent.IsPending()) {
nsRefPtr<nsInvalidateEvent> ev = new nsInvalidateEvent(this);
if (NS_FAILED(NS_DispatchToCurrentThread(ev))) {
NS_WARNING("failed to dispatch nsInvalidateEvent");
} else {
mInvalidateEvent = ev;
}
}
}
#undef DEBUG_MOUSE_LOCATION
PRInt32 nsViewManager::mVMCount = 0;
@ -120,8 +105,8 @@ nsViewManager::nsViewManager()
// NOTE: we use a zeroing operator new, so all data members are
// assumed to be cleared here.
mHasPendingUpdates = false;
mHasPendingWidgetGeometryChanges = false;
mRecursiveRefreshPending = false;
mUpdateBatchFlags = 0;
}
nsViewManager::~nsViewManager()
@ -132,10 +117,6 @@ nsViewManager::~nsViewManager()
mRootView = nsnull;
}
// Make sure to revoke pending events for all viewmanagers, since some events
// are posted by a non-root viewmanager.
mInvalidateEvent.Revoke();
if (!IsRootVM()) {
// We have a strong ref to mRootViewManager
NS_RELEASE(mRootViewManager);
@ -361,9 +342,6 @@ void nsViewManager::Refresh(nsView *aView, nsIWidget *aWidget,
NS_ASSERTION(aView == nsView::GetViewFor(aWidget), "view widget mismatch");
NS_ASSERTION(aView->GetViewManager() == this, "wrong view manager");
if (! IsRefreshEnabled())
return;
// damageRegion is the damaged area, in twips, relative to the view origin
nsRegion damageRegion = aRegion.ToAppUnits(AppUnitsPerDevPixel());
// move region from widget coordinates into view coordinates
@ -396,10 +374,8 @@ void nsViewManager::Refresh(nsView *aView, nsIWidget *aWidget,
}
if (RootViewManager()->mRecursiveRefreshPending) {
// Unset this flag first, since if aUpdateFlags includes NS_VMREFRESH_IMMEDIATE
// we'll reenter this code from the UpdateAllViews call.
RootViewManager()->mRecursiveRefreshPending = false;
UpdateAllViews(0);
InvalidateAllViews();
}
}
@ -420,7 +396,8 @@ void nsViewManager::RenderViews(nsView *aView, nsIWidget *aWidget,
}
}
void nsViewManager::ProcessPendingUpdates(nsView* aView, bool aDoInvalidate)
void nsViewManager::ProcessPendingUpdatesForView(nsView* aView,
bool aFlushDirtyRegion)
{
NS_ASSERTION(IsRootVM(), "Updates will be missed");
@ -430,96 +407,87 @@ void nsViewManager::ProcessPendingUpdates(nsView* aView, bool aDoInvalidate)
}
if (aView->HasWidget()) {
aView->ResetWidgetBounds(false, false, true);
aView->ResetWidgetBounds(false, true);
}
// process pending updates in child view.
for (nsView* childView = aView->GetFirstChild(); childView;
childView = childView->GetNextSibling()) {
ProcessPendingUpdates(childView, aDoInvalidate);
ProcessPendingUpdatesForView(childView, aFlushDirtyRegion);
}
if (aDoInvalidate && aView->HasNonEmptyDirtyRegion()) {
// Push out updates after we've processed the children; ensures that
// damage is applied based on the final widget geometry
NS_ASSERTION(IsRefreshEnabled(), "Cannot process pending updates with refresh disabled");
nsRegion* dirtyRegion = aView->GetDirtyRegion();
if (dirtyRegion) {
nsView* nearestViewWithWidget = aView;
while (!nearestViewWithWidget->HasWidget() &&
nearestViewWithWidget->GetParent()) {
nearestViewWithWidget = nearestViewWithWidget->GetParent();
}
nsRegion r =
ConvertRegionBetweenViews(*dirtyRegion, aView, nearestViewWithWidget);
nsViewManager* widgetVM = nearestViewWithWidget->GetViewManager();
widgetVM->
UpdateWidgetArea(nearestViewWithWidget,
nearestViewWithWidget->GetWidget(), r, nsnull);
dirtyRegion->SetEmpty();
}
// Push out updates after we've processed the children; ensures that
// damage is applied based on the final widget geometry
if (aFlushDirtyRegion) {
FlushDirtyRegionToWidget(aView);
}
}
NS_IMETHODIMP nsViewManager::Composite()
void nsViewManager::FlushDirtyRegionToWidget(nsView* aView)
{
if (!IsRootVM()) {
return RootViewManager()->Composite();
}
ForceUpdate();
ClearUpdateCount();
if (!aView->HasNonEmptyDirtyRegion())
return;
return NS_OK;
nsRegion* dirtyRegion = aView->GetDirtyRegion();
nsView* nearestViewWithWidget = aView;
while (!nearestViewWithWidget->HasWidget() &&
nearestViewWithWidget->GetParent()) {
nearestViewWithWidget = nearestViewWithWidget->GetParent();
}
nsRegion r =
ConvertRegionBetweenViews(*dirtyRegion, aView, nearestViewWithWidget);
nsViewManager* widgetVM = nearestViewWithWidget->GetViewManager();
widgetVM->InvalidateWidgetArea(nearestViewWithWidget, r);
dirtyRegion->SetEmpty();
}
NS_IMETHODIMP nsViewManager::UpdateView(nsIView *aView, PRUint32 aUpdateFlags)
NS_IMETHODIMP nsViewManager::InvalidateView(nsIView *aView)
{
// Mark the entire view as damaged
return UpdateView(aView, aView->GetDimensions(), aUpdateFlags);
return InvalidateView(aView, aView->GetDimensions());
}
static void
AddDirtyRegion(nsView *aView, const nsRegion &aDamagedRegion)
{
nsRegion* dirtyRegion = aView->GetDirtyRegion();
if (!dirtyRegion)
return;
dirtyRegion->Or(*dirtyRegion, aDamagedRegion);
dirtyRegion->SimplifyOutward(8);
}
void
nsViewManager::PostPendingUpdate()
{
nsViewManager* rootVM = RootViewManager();
rootVM->mHasPendingUpdates = true;
rootVM->mHasPendingWidgetGeometryChanges = true;
if (rootVM->mPresShell) {
rootVM->mPresShell->ScheduleViewManagerFlush();
}
}
/**
* @param aWidget the widget for aWidgetView; in some cases the widget
* is being managed directly by the frame system, so aWidgetView->GetWidget()
* will return null but nsView::GetViewFor(aWidget) returns aWidgetview
* @param aDamagedRegion this region, relative to aWidgetView, is invalidated in
* every widget child of aWidgetView, plus aWidgetView's own widget
* @param aIgnoreWidgetView if non-null, the aIgnoreWidgetView's widget and its
* children are not updated.
*/
void
nsViewManager::UpdateWidgetArea(nsView *aWidgetView, nsIWidget* aWidget,
const nsRegion &aDamagedRegion,
nsView* aIgnoreWidgetView)
nsViewManager::InvalidateWidgetArea(nsView *aWidgetView,
const nsRegion &aDamagedRegion)
{
NS_ASSERTION(aWidgetView->GetViewManager() == this,
"UpdateWidgetArea called on view we don't own");
"InvalidateWidgetArea called on view we don't own");
nsIWidget* widget = aWidgetView->GetWidget();
#if 0
nsRect dbgBounds = aDamagedRegion.GetBounds();
printf("UpdateWidgetArea view:%X (%d) widget:%X region: %d, %d, %d, %d\n",
printf("InvalidateWidgetArea view:%X (%d) widget:%X region: %d, %d, %d, %d\n",
aWidgetView, aWidgetView->IsAttachedToTopLevel(),
aWidget, dbgBounds.x, dbgBounds.y, dbgBounds.width, dbgBounds.height);
widget, dbgBounds.x, dbgBounds.y, dbgBounds.width, dbgBounds.height);
#endif
if (!IsRefreshEnabled()) {
// accumulate this rectangle in the view's dirty region, so we can
// process it later.
nsRegion* dirtyRegion = aWidgetView->GetDirtyRegion();
if (!dirtyRegion) return;
dirtyRegion->Or(*dirtyRegion, aDamagedRegion);
// Don't let dirtyRegion grow beyond 8 rects
dirtyRegion->SimplifyOutward(8);
nsViewManager* rootVM = RootViewManager();
rootVM->mHasPendingUpdates = true;
rootVM->IncrementUpdateCount();
return;
// this should only happen at the top level, and this result
// should not be consumed by top-level callers, so it doesn't
// really matter what we return
}
// If the bounds don't overlap at all, there's nothing to do
nsRegion intersection;
intersection.And(aWidgetView->GetInvalidationDimensions(), aDamagedRegion);
@ -528,19 +496,14 @@ nsViewManager::UpdateWidgetArea(nsView *aWidgetView, nsIWidget* aWidget,
}
// If the widget is hidden, it don't cover nothing
if (aWidget) {
if (widget) {
bool visible;
aWidget->IsVisible(visible);
widget->IsVisible(visible);
if (!visible)
return;
}
if (aWidgetView == aIgnoreWidgetView) {
// the widget for aIgnoreWidgetView (and its children) should be treated as already updated.
return;
}
if (!aWidget) {
if (!widget) {
// 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.
@ -551,8 +514,8 @@ nsViewManager::UpdateWidgetArea(nsView *aWidgetView, nsIWidget* aWidget,
// accumulate the union of all the child widget areas, or at least
// some subset of that.
nsRegion children;
if (aWidget->GetTransparencyMode() != eTransparencyTransparent) {
for (nsIWidget* childWidget = aWidget->GetFirstChild();
if (widget->GetTransparencyMode() != eTransparencyTransparent) {
for (nsIWidget* childWidget = widget->GetFirstChild();
childWidget;
childWidget = childWidget->GetNextSibling()) {
nsView* view = nsView::GetViewFor(childWidget);
@ -591,12 +554,10 @@ nsViewManager::UpdateWidgetArea(nsView *aWidgetView, nsIWidget* aWidget,
leftOver.Sub(intersection, children);
if (!leftOver.IsEmpty()) {
NS_ASSERTION(IsRefreshEnabled(), "Can only get here with refresh enabled, I hope");
const nsRect* r;
for (nsRegionRectIterator iter(leftOver); (r = iter.Next());) {
nsIntRect bounds = ViewToWidget(aWidgetView, *r);
aWidget->Invalidate(bounds, false);
widget->Invalidate(bounds);
}
}
}
@ -615,8 +576,7 @@ ShouldIgnoreInvalidation(nsViewManager* aVM)
return false;
}
nsresult nsViewManager::UpdateView(nsIView *aView, const nsRect &aRect,
PRUint32 aUpdateFlags)
nsresult nsViewManager::InvalidateView(nsIView *aView, const nsRect &aRect)
{
// If painting is suppressed in the presshell or an ancestor drop all
// invalidates, it will invalidate everything when it unsuppresses.
@ -624,19 +584,18 @@ nsresult nsViewManager::UpdateView(nsIView *aView, const nsRect &aRect,
return NS_OK;
}
return UpdateViewNoSuppression(aView, aRect, aUpdateFlags);
return InvalidateViewNoSuppression(aView, aRect);
}
NS_IMETHODIMP nsViewManager::UpdateViewNoSuppression(nsIView *aView,
const nsRect &aRect,
PRUint32 aUpdateFlags)
NS_IMETHODIMP nsViewManager::InvalidateViewNoSuppression(nsIView *aView,
const nsRect &aRect)
{
NS_PRECONDITION(nsnull != aView, "null view");
nsView* view = static_cast<nsView*>(aView);
NS_ASSERTION(view->GetViewManager() == this,
"UpdateView called on view we don't own");
"InvalidateViewNoSuppression called on view we don't own");
nsRect damagedRect(aRect);
if (damagedRect.IsEmpty()) {
@ -652,42 +611,36 @@ NS_IMETHODIMP nsViewManager::UpdateViewNoSuppression(nsIView *aView,
PRInt32 rootAPD = displayRootVM->AppUnitsPerDevPixel();
PRInt32 APD = AppUnitsPerDevPixel();
damagedRect = damagedRect.ConvertAppUnitsRoundOut(APD, rootAPD);
displayRootVM->UpdateWidgetArea(displayRoot, displayRoot->GetWidget(),
nsRegion(damagedRect), nsnull);
RootViewManager()->IncrementUpdateCount();
// accumulate this rectangle in the view's dirty region, so we can
// process it later.
AddDirtyRegion(displayRoot, nsRegion(damagedRect));
if (!IsRefreshEnabled()) {
return NS_OK;
}
// See if we should do an immediate refresh or wait
if (aUpdateFlags & NS_VMREFRESH_IMMEDIATE) {
Composite();
}
// Schedule an invalidation flush with the refresh driver.
PostPendingUpdate();
return NS_OK;
}
NS_IMETHODIMP nsViewManager::UpdateAllViews(PRUint32 aUpdateFlags)
NS_IMETHODIMP nsViewManager::InvalidateAllViews()
{
if (RootViewManager() != this) {
return RootViewManager()->UpdateAllViews(aUpdateFlags);
return RootViewManager()->InvalidateAllViews();
}
UpdateViews(mRootView, aUpdateFlags);
InvalidateViews(mRootView);
return NS_OK;
}
void nsViewManager::UpdateViews(nsView *aView, PRUint32 aUpdateFlags)
void nsViewManager::InvalidateViews(nsView *aView)
{
// update this view.
UpdateView(aView, aUpdateFlags);
// Invalidate this view.
InvalidateView(aView);
// update all children as well.
// Invalidate all children as well.
nsView* childView = aView->GetFirstChild();
while (nsnull != childView) {
childView->GetViewManager()->UpdateViews(childView, aUpdateFlags);
childView->GetViewManager()->InvalidateViews(childView);
childView = childView->GetNextSibling();
}
}
@ -800,132 +753,74 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent,
break;
case NS_WILL_PAINT:
case NS_PAINT:
{
nsPaintEvent *event = static_cast<nsPaintEvent*>(aEvent);
if (!aView || !mContext)
break;
*aStatus = nsEventStatus_eConsumeNoDefault;
if (aEvent->message == NS_PAINT && event->region.IsEmpty())
break;
nsPaintEvent *event = static_cast<nsPaintEvent*>(aEvent);
NS_ASSERTION(static_cast<nsView*>(aView) ==
nsView::GetViewFor(event->widget),
"view/widget mismatch");
// The region is in device units, and it's in the coordinate space of
// its associated widget.
// Refresh the view
if (IsRefreshEnabled()) {
nsRefPtr<nsViewManager> rootVM = RootViewManager();
// If an ancestor widget was hidden and then shown, we could
// have a delayed resize to handle.
bool didResize = false;
for (nsViewManager *vm = this; vm;
vm = vm->mRootView->GetParent()
? vm->mRootView->GetParent()->GetViewManager()
: nsnull) {
if (vm->mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) &&
vm->mRootView->IsEffectivelyVisible() &&
mPresShell && mPresShell->IsVisible()) {
vm->FlushDelayedResize(true);
// Paint later.
vm->UpdateView(vm->mRootView, NS_VMREFRESH_NO_SYNC);
didResize = true;
// not sure if it's valid for us to claim that we
// ignored this, but we're going to do so anyway, since
// we didn't actually paint anything
*aStatus = nsEventStatus_eIgnore;
}
// If an ancestor widget was hidden and then shown, we could
// have a delayed resize to handle.
for (nsViewManager *vm = this; vm;
vm = vm->mRootView->GetParent()
? vm->mRootView->GetParent()->GetViewManager()
: nsnull) {
if (vm->mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) &&
vm->mRootView->IsEffectivelyVisible() &&
mPresShell && mPresShell->IsVisible()) {
vm->FlushDelayedResize(true);
vm->InvalidateView(vm->mRootView);
}
if (!didResize) {
//NS_ASSERTION(view->IsEffectivelyVisible(), "painting an invisible view");
// Notify view observers that we're about to paint.
// Make sure to not send WillPaint notifications while scrolling.
nsCOMPtr<nsIWidget> widget;
rootVM->GetRootWidget(getter_AddRefs(widget));
bool transparentWindow = false;
if (widget)
transparentWindow = widget->GetTransparencyMode() == eTransparencyTransparent;
nsView* view = static_cast<nsView*>(aView);
if (!transparentWindow) {
if (mPresShell) {
// Do an update view batch. Make sure not to do it DEFERRED,
// since that would effectively delay any invalidates that are
// triggered by the WillPaint notification (they'd happen when
// the invalid event fires, which is later than the reflow
// event would fire and could end up being after some timer
// events, leading to frame dropping in DHTML). Note that the
// observer may try to reenter this code from inside
// WillPaint() by trying to do a synchronous paint, but since
// refresh will be disabled it won't be able to do the paint.
// We should really sort out the rules on our synch painting
// api....
UpdateViewBatch batch(this);
rootVM->CallWillPaintOnObservers(event->willSendDidPaint);
batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
// Get the view pointer again since the code above might have
// destroyed it (bug 378273).
view = nsView::GetViewFor(aEvent->widget);
}
}
// Make sure to sync up any widget geometry changes we
// have pending before we paint.
if (rootVM->mHasPendingUpdates) {
rootVM->ProcessPendingUpdates(mRootView, false);
}
if (view && aEvent->message == NS_PAINT) {
Refresh(view, event->widget, event->region);
}
}
} else if (aEvent->message == NS_PAINT) {
// since we got an NS_PAINT event, we need to
// draw something so we don't get blank areas,
// unless there's no widget or it's transparent.
nsRegion rgn = event->region.ToAppUnits(AppUnitsPerDevPixel());
rgn.MoveBy(-aView->ViewToWidgetOffset());
RenderViews(static_cast<nsView*>(aView), event->widget, rgn,
event->region, true, event->willSendDidPaint);
// Clients like the editor can trigger multiple
// reflows during what the user perceives as a single
// edit operation, so it disables view manager
// refreshing until the edit operation is complete
// so that users don't see the intermediate steps.
//
// Unfortunately some of these reflows can trigger
// nsScrollPortView and nsScrollingView Scroll() calls
// which in most cases force an immediate BitBlt and
// synchronous paint to happen even if the view manager's
// refresh is disabled. (Bug 97674)
//
// Calling UpdateView() here, is necessary to add
// the exposed region specified in the synchronous paint
// event to the view's damaged region so that it gets
// painted properly when refresh is enabled.
//
// Note that calling UpdateView() here was deemed
// to have the least impact on performance, since the
// other alternative was to make Scroll() post an
// async paint event for the *entire* ScrollPort or
// ScrollingView's viewable area. (See bug 97674 for this
// alternate patch.)
UpdateView(aView, rgn.GetBounds(), NS_VMREFRESH_NO_SYNC);
}
// Flush things like reflows and plugin widget geometry updates by
// calling WillPaint on observer presShells.
nsRefPtr<nsViewManager> rootVM = RootViewManager();
if (mPresShell) {
rootVM->CallWillPaintOnObservers(event->willSendDidPaint);
}
// Flush view widget geometry updates and invalidations.
rootVM->ProcessPendingUpdates();
}
break;
case NS_PAINT:
{
if (!aView || !mContext)
break;
*aStatus = nsEventStatus_eConsumeNoDefault;
nsPaintEvent *event = static_cast<nsPaintEvent*>(aEvent);
nsView* view = static_cast<nsView*>(aView);
NS_ASSERTION(view == nsView::GetViewFor(event->widget),
"view/widget mismatch");
NS_ASSERTION(IsPaintingAllowed(),
"shouldn't be receiving paint events while painting is "
"disallowed!");
if (!event->didSendWillPaint) {
// Send NS_WILL_PAINT event ourselves.
nsPaintEvent willPaintEvent(true, NS_WILL_PAINT, event->widget);
willPaintEvent.willSendDidPaint = event->willSendDidPaint;
DispatchEvent(&willPaintEvent, view, aStatus);
// Get the view pointer again since NS_WILL_PAINT might have
// destroyed it during CallWillPaintOnObservers (bug 378273).
view = nsView::GetViewFor(event->widget);
}
if (!view || event->region.IsEmpty())
break;
// Paint.
Refresh(view, event->widget, event->region);
break;
}
@ -1176,7 +1071,7 @@ NS_IMETHODIMP nsViewManager::InsertChild(nsIView *aParent, nsIView *aChild, nsIV
//and mark this area as dirty if the view is visible...
if (nsViewVisibility_kHide != child->GetVisibility())
child->GetViewManager()->UpdateView(child, NS_VMREFRESH_NO_SYNC);
child->GetViewManager()->InvalidateView(child);
}
return NS_OK;
}
@ -1199,7 +1094,7 @@ NS_IMETHODIMP nsViewManager::RemoveChild(nsIView *aChild)
if (nsnull != parent) {
NS_ASSERTION(child->GetViewManager() == this ||
parent->GetViewManager() == this, "wrong view manager");
child->GetViewManager()->UpdateView(child, NS_VMREFRESH_NO_SYNC);
child->GetViewManager()->InvalidateView(child);
parent->RemoveChild(child);
}
@ -1221,9 +1116,8 @@ NS_IMETHODIMP nsViewManager::MoveViewTo(nsIView *aView, nscoord aX, nscoord aY)
nsView* parentView = view->GetParent();
if (parentView) {
nsViewManager* parentVM = parentView->GetViewManager();
parentVM->UpdateView(parentView, oldBounds, NS_VMREFRESH_NO_SYNC);
parentVM->UpdateView(parentView, view->GetBoundsInParentUnits(),
NS_VMREFRESH_NO_SYNC);
parentVM->InvalidateView(parentView, oldBounds);
parentVM->InvalidateView(parentView, view->GetBoundsInParentUnits());
}
}
}
@ -1231,34 +1125,33 @@ NS_IMETHODIMP nsViewManager::MoveViewTo(nsIView *aView, nscoord aX, nscoord aY)
}
void nsViewManager::InvalidateHorizontalBandDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut,
PRUint32 aUpdateFlags, nscoord aY1, nscoord aY2, bool aInCutOut) {
nscoord aY1, nscoord aY2, bool aInCutOut) {
nscoord height = aY2 - aY1;
if (aRect.x < aCutOut.x) {
nsRect r(aRect.x, aY1, aCutOut.x - aRect.x, height);
UpdateView(aView, r, aUpdateFlags);
InvalidateView(aView, r);
}
if (!aInCutOut && aCutOut.x < aCutOut.XMost()) {
nsRect r(aCutOut.x, aY1, aCutOut.width, height);
UpdateView(aView, r, aUpdateFlags);
InvalidateView(aView, r);
}
if (aCutOut.XMost() < aRect.XMost()) {
nsRect r(aCutOut.XMost(), aY1, aRect.XMost() - aCutOut.XMost(), height);
UpdateView(aView, r, aUpdateFlags);
InvalidateView(aView, r);
}
}
void nsViewManager::InvalidateRectDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut,
PRUint32 aUpdateFlags) {
void nsViewManager::InvalidateRectDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut) {
NS_ASSERTION(aView->GetViewManager() == this,
"InvalidateRectDifference called on view we don't own");
if (aRect.y < aCutOut.y) {
InvalidateHorizontalBandDifference(aView, aRect, aCutOut, aUpdateFlags, aRect.y, aCutOut.y, false);
InvalidateHorizontalBandDifference(aView, aRect, aCutOut, aRect.y, aCutOut.y, false);
}
if (aCutOut.y < aCutOut.YMost()) {
InvalidateHorizontalBandDifference(aView, aRect, aCutOut, aUpdateFlags, aCutOut.y, aCutOut.YMost(), true);
InvalidateHorizontalBandDifference(aView, aRect, aCutOut, aCutOut.y, aCutOut.YMost(), true);
}
if (aCutOut.YMost() < aRect.YMost()) {
InvalidateHorizontalBandDifference(aView, aRect, aCutOut, aUpdateFlags, aCutOut.YMost(), aRect.YMost(), false);
InvalidateHorizontalBandDifference(aView, aRect, aCutOut, aCutOut.YMost(), aRect.YMost(), false);
}
}
@ -1282,14 +1175,13 @@ NS_IMETHODIMP nsViewManager::ResizeView(nsIView *aView, const nsRect &aRect, boo
view->SetDimensions(aRect, true);
nsViewManager* parentVM = parentView->GetViewManager();
if (!aRepaintExposedAreaOnly) {
//Invalidate the union of the old and new size
UpdateView(view, aRect, NS_VMREFRESH_NO_SYNC);
parentVM->UpdateView(parentView, oldBounds, NS_VMREFRESH_NO_SYNC);
// Invalidate the union of the old and new size
InvalidateView(view, aRect);
parentVM->InvalidateView(parentView, oldBounds);
} else {
InvalidateRectDifference(view, aRect, oldDimensions, NS_VMREFRESH_NO_SYNC);
InvalidateRectDifference(view, aRect, oldDimensions);
nsRect newBounds = view->GetBoundsInParentUnits();
parentVM->InvalidateRectDifference(parentView, oldBounds, newBounds,
NS_VMREFRESH_NO_SYNC);
parentVM->InvalidateRectDifference(parentView, oldBounds, newBounds);
}
}
}
@ -1328,12 +1220,11 @@ NS_IMETHODIMP nsViewManager::SetViewVisibility(nsIView *aView, nsViewVisibility
nsView* parentView = view->GetParent();
if (parentView) {
parentView->GetViewManager()->
UpdateView(parentView, view->GetBoundsInParentUnits(),
NS_VMREFRESH_NO_SYNC);
InvalidateView(parentView, view->GetBoundsInParentUnits());
}
}
else {
UpdateView(view, NS_VMREFRESH_NO_SYNC);
InvalidateView(view);
}
}
}
@ -1341,37 +1232,6 @@ NS_IMETHODIMP nsViewManager::SetViewVisibility(nsIView *aView, nsViewVisibility
return NS_OK;
}
void nsViewManager::UpdateWidgetsForView(nsView* aView)
{
NS_PRECONDITION(aView, "Must have view!");
// No point forcing an update if invalidations have been suppressed.
if (!IsRefreshEnabled())
return;
nsWeakView parentWeakView = aView;
if (aView->HasWidget()) {
aView->GetWidget()->Update(); // Flushes Layout!
if (!parentWeakView.IsAlive()) {
return;
}
}
nsView* childView = aView->GetFirstChild();
while (childView) {
nsWeakView childWeakView = childView;
UpdateWidgetsForView(childView);
if (NS_LIKELY(childWeakView.IsAlive())) {
childView = childView->GetNextSibling();
}
else {
// The current view was destroyed - restart at the first child if the
// parent is still alive.
childView = parentWeakView.IsAlive() ? aView->GetFirstChild() : nsnull;
}
}
}
bool nsViewManager::IsViewInserted(nsView *aView)
{
if (mRootView == aView) {
@ -1415,7 +1275,7 @@ NS_IMETHODIMP nsViewManager::SetViewZIndex(nsIView *aView, bool aAutoZIndex, PRI
if (oldidx != aZIndex || oldTopMost != aTopMost ||
oldIsAuto != aAutoZIndex) {
UpdateView(view, NS_VMREFRESH_NO_SYNC);
InvalidateView(view);
}
return rv;
@ -1428,68 +1288,24 @@ NS_IMETHODIMP nsViewManager::GetDeviceContext(nsDeviceContext *&aContext)
return NS_OK;
}
void nsViewManager::TriggerRefresh(PRUint32 aUpdateFlags)
nsIViewManager*
nsViewManager::IncrementDisableRefreshCount()
{
if (!IsRootVM()) {
RootViewManager()->TriggerRefresh(aUpdateFlags);
return;
}
if (mUpdateBatchCnt > 0)
return;
// nested batching can combine IMMEDIATE with DEFERRED. Favour
// IMMEDIATE over DEFERRED and DEFERRED over NO_SYNC. We need to
// check for IMMEDIATE before checking mHasPendingUpdates, because
// the latter might be false as far as gecko is concerned but the OS
// might still have queued up expose events that it hasn't sent yet.
if (aUpdateFlags & NS_VMREFRESH_IMMEDIATE) {
FlushPendingInvalidates();
Composite();
} else if (!mHasPendingUpdates) {
// Nothing to do
} else if (aUpdateFlags & NS_VMREFRESH_DEFERRED) {
PostInvalidateEvent();
} else { // NO_SYNC
FlushPendingInvalidates();
}
}
nsIViewManager* nsViewManager::BeginUpdateViewBatch(void)
{
if (!IsRootVM()) {
return RootViewManager()->BeginUpdateViewBatch();
}
if (mUpdateBatchCnt == 0) {
mUpdateBatchFlags = 0;
return RootViewManager()->IncrementDisableRefreshCount();
}
++mUpdateBatchCnt;
++mRefreshDisableCount;
return this;
}
NS_IMETHODIMP nsViewManager::EndUpdateViewBatch(PRUint32 aUpdateFlags)
void
nsViewManager::DecrementDisableRefreshCount()
{
NS_ASSERTION(IsRootVM(), "Should only be called on root");
--mUpdateBatchCnt;
NS_ASSERTION(mUpdateBatchCnt >= 0, "Invalid batch count!");
if (mUpdateBatchCnt < 0)
{
mUpdateBatchCnt = 0;
return NS_ERROR_FAILURE;
}
mUpdateBatchFlags |= aUpdateFlags;
if (mUpdateBatchCnt == 0) {
TriggerRefresh(mUpdateBatchFlags);
}
return NS_OK;
--mRefreshDisableCount;
NS_ASSERTION(mRefreshDisableCount >= 0, "Invalid refresh disable count!");
}
NS_IMETHODIMP nsViewManager::GetRootWidget(nsIWidget **aWidget)
@ -1509,20 +1325,6 @@ NS_IMETHODIMP nsViewManager::GetRootWidget(nsIWidget **aWidget)
return NS_OK;
}
NS_IMETHODIMP nsViewManager::ForceUpdate()
{
if (!IsRootVM()) {
return RootViewManager()->ForceUpdate();
}
// Walk the view tree looking for widgets, and call Update() on each one
if (mRootView) {
UpdateWidgetsForView(mRootView);
}
return NS_OK;
}
nsIntRect nsViewManager::ViewToWidget(nsView *aView, const nsRect &aRect) const
{
NS_ASSERTION(aView->GetViewManager() == this, "wrong view manager");
@ -1547,26 +1349,38 @@ nsViewManager::IsPainting(bool& aIsPainting)
}
void
nsViewManager::FlushPendingInvalidates()
nsViewManager::ProcessPendingUpdates()
{
NS_ASSERTION(IsRootVM(), "Must be root VM for this to be called!");
NS_ASSERTION(mUpdateBatchCnt == 0, "Must not be in an update batch!");
if (!IsRootVM()) {
RootViewManager()->ProcessPendingUpdates();
return;
}
if (mHasPendingUpdates) {
ProcessPendingUpdates(mRootView, true);
ProcessPendingUpdatesForView(mRootView, true);
mHasPendingUpdates = false;
}
}
void
nsViewManager::UpdateWidgetGeometry()
{
if (!IsRootVM()) {
RootViewManager()->UpdateWidgetGeometry();
return;
}
if (mHasPendingWidgetGeometryChanges) {
ProcessPendingUpdatesForView(mRootView, false);
mHasPendingWidgetGeometryChanges = false;
}
}
void
nsViewManager::CallWillPaintOnObservers(bool aWillSendDidPaint)
{
NS_PRECONDITION(IsRootVM(), "Must be root VM for this to be called!");
NS_PRECONDITION(mUpdateBatchCnt > 0, "Must be in an update batch!");
#ifdef DEBUG
PRInt32 savedUpdateBatchCnt = mUpdateBatchCnt;
#endif
PRInt32 index;
for (index = 0; index < mVMCount; index++) {
nsViewManager* vm = (nsViewManager*)gViewManagers->ElementAt(index);
@ -1576,8 +1390,6 @@ nsViewManager::CallWillPaintOnObservers(bool aWillSendDidPaint)
nsCOMPtr<nsIPresShell> shell = vm->GetPresShell();
if (shell) {
shell->WillPaint(aWillSendDidPaint);
NS_ASSERTION(mUpdateBatchCnt == savedUpdateBatchCnt,
"Observer did not end view batch?");
}
}
}
@ -1604,24 +1416,6 @@ nsViewManager::CallDidPaintOnObservers()
}
}
void
nsViewManager::ProcessInvalidateEvent()
{
NS_ASSERTION(IsRootVM(),
"Incorrectly targeted invalidate event");
// If we're in the middle of an update batch, just repost the event,
// to be processed when the batch ends.
bool processEvent = (mUpdateBatchCnt == 0);
if (processEvent) {
FlushPendingInvalidates();
}
mInvalidateEvent.Forget();
if (!processEvent) {
// We didn't actually process this event... post a new one
PostInvalidateEvent();
}
}
NS_IMETHODIMP
nsViewManager::GetLastUserEventTime(PRUint32& aTime)
{

View File

@ -53,36 +53,27 @@
/**
Invalidation model:
1) Callers call into the view manager and ask it to update a view.
1) Callers call into the view manager and ask it to invalidate a view.
2) The view manager finds the "right" widget for the view, henceforth called
the root widget.
3) The view manager traverses descendants of the root widget and for each
one that needs invalidation either
one that needs invalidation stores the rect to invalidate on the widget's
view (batching).
a) Calls Invalidate() on the widget (no batching)
or
b) Stores the rect to invalidate on the widget's view (batching)
// XXXbz we want to change this a bit. See bug 243726
4) When batching, the call to end the batch either processes the pending
Invalidate() calls on the widgets or posts an event to do so.
4) The dirty region is flushed to the right widget when
ProcessPendingUpdates is called from the RefreshDriver.
It's important to note that widgets associated to views outside this view
manager can end up being invalidated during step 3. Therefore, the end of a
view update batch really needs to traverse the entire view tree, to ensure
that those invalidates happen.
To cope with this, invalidate event processing and view update batch
handling should only happen on the root viewmanager. This means the root
view manager is the only thing keeping track of mUpdateCnt. As a result,
Composite() calls should also be forwarded to the root view manager.
To cope with this, invalidation processing and should only happen on the
root viewmanager.
*/
class nsInvalidateEvent;
class nsViewManager : public nsIViewManager {
public:
nsViewManager();
@ -104,12 +95,9 @@ public:
NS_IMETHOD SetWindowDimensions(nscoord width, nscoord height);
NS_IMETHOD FlushDelayedResize(bool aDoReflow);
NS_IMETHOD Composite(void);
NS_IMETHOD UpdateView(nsIView *aView, PRUint32 aUpdateFlags);
NS_IMETHOD UpdateViewNoSuppression(nsIView *aView, const nsRect &aRect,
PRUint32 aUpdateFlags);
NS_IMETHOD UpdateAllViews(PRUint32 aUpdateFlags);
NS_IMETHOD InvalidateView(nsIView *aView);
NS_IMETHOD InvalidateViewNoSuppression(nsIView *aView, const nsRect &aRect);
NS_IMETHOD InvalidateAllViews();
NS_IMETHOD DispatchEvent(nsGUIEvent *aEvent,
nsIView* aTargetView, nsEventStatus* aStatus);
@ -137,27 +125,30 @@ public:
NS_IMETHOD GetDeviceContext(nsDeviceContext *&aContext);
virtual nsIViewManager* BeginUpdateViewBatch(void);
NS_IMETHOD EndUpdateViewBatch(PRUint32 aUpdateFlags);
virtual nsIViewManager* IncrementDisableRefreshCount();
virtual void DecrementDisableRefreshCount();
NS_IMETHOD GetRootWidget(nsIWidget **aWidget);
NS_IMETHOD ForceUpdate();
NS_IMETHOD IsPainting(bool& aIsPainting);
NS_IMETHOD GetLastUserEventTime(PRUint32& aTime);
void ProcessInvalidateEvent();
static PRUint32 gLastUserEventTime;
/* Update the cached RootViewManager pointer on this view manager. */
void InvalidateHierarchy();
virtual void ProcessPendingUpdates();
virtual void UpdateWidgetGeometry();
protected:
virtual ~nsViewManager();
private:
void FlushPendingInvalidates();
void ProcessPendingUpdates(nsView *aView, bool aDoInvalidate);
void ProcessPendingUpdatesForView(nsView *aView,
bool aFlushDirtyRegion = true);
void FlushDirtyRegionToWidget(nsView* aView);
/**
* Call WillPaint() on all view observers under this vm root.
*/
@ -165,13 +156,9 @@ private:
void CallDidPaintOnObservers();
void ReparentChildWidgets(nsIView* aView, nsIWidget *aNewWidget);
void ReparentWidgets(nsIView* aView, nsIView *aParent);
void UpdateWidgetArea(nsView *aWidgetView, nsIWidget* aWidget,
const nsRegion &aDamagedRegion,
nsView* aIgnoreWidgetView);
void InvalidateWidgetArea(nsView *aWidgetView, const nsRegion &aDamagedRegion);
void UpdateViews(nsView *aView, PRUint32 aUpdateFlags);
void TriggerRefresh(PRUint32 aUpdateFlags);
void InvalidateViews(nsView *aView);
// aView is the view for aWidget and aRegion is relative to aWidget.
void Refresh(nsView *aView, nsIWidget *aWidget, const nsIntRegion& aRegion);
@ -181,20 +168,14 @@ private:
const nsRegion& aRegion, const nsIntRegion& aIntRegion,
bool aPaintDefaultBackground, bool aWillSendDidPaint);
void InvalidateRectDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut, PRUint32 aUpdateFlags);
void InvalidateRectDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut);
void InvalidateHorizontalBandDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut,
PRUint32 aUpdateFlags, nscoord aY1, nscoord aY2, bool aInCutOut);
nscoord aY1, nscoord aY2, bool aInCutOut);
// Utilities
bool IsViewInserted(nsView *aView);
/**
* Function to recursively call Update() on all widgets belonging to
* a view or its kids.
*/
void UpdateWidgetsForView(nsView* aView);
/**
* Intersects aRect with aView's bounds and then transforms it from aView's
* coordinate system to the coordinate system of the widget attached to
@ -204,31 +185,6 @@ private:
void DoSetWindowDimensions(nscoord aWidth, nscoord aHeight);
// Safety helpers
void IncrementUpdateCount() {
NS_ASSERTION(IsRootVM(),
"IncrementUpdateCount called on non-root viewmanager");
++mUpdateCnt;
}
void DecrementUpdateCount() {
NS_ASSERTION(IsRootVM(),
"DecrementUpdateCount called on non-root viewmanager");
--mUpdateCnt;
}
PRInt32 UpdateCount() const {
NS_ASSERTION(IsRootVM(),
"DecrementUpdateCount called on non-root viewmanager");
return mUpdateCnt;
}
void ClearUpdateCount() {
NS_ASSERTION(IsRootVM(),
"DecrementUpdateCount called on non-root viewmanager");
mUpdateCnt = 0;
}
bool IsPainting() const {
return RootViewManager()->mPainting;
}
@ -237,18 +193,21 @@ private:
RootViewManager()->mPainting = aPainting;
}
nsresult UpdateView(nsIView *aView, const nsRect &aRect, PRUint32 aUpdateFlags);
nsresult InvalidateView(nsIView *aView, const nsRect &aRect);
public: // NOT in nsIViewManager, so private to the view module
nsView* GetRootViewImpl() const { return mRootView; }
nsViewManager* RootViewManager() const { return mRootViewManager; }
bool IsRootVM() const { return this == RootViewManager(); }
bool IsRefreshEnabled() { return RootViewManager()->mUpdateBatchCnt == 0; }
// Whether synchronous painting is allowed at the moment. For example,
// widget geometry changes can cause synchronous painting, so they need to
// be deferred while refresh is disabled.
bool IsPaintingAllowed() { return RootViewManager()->mRefreshDisableCount == 0; }
// Call this when you need to let the viewmanager know that it now has
// pending updates.
void PostPendingUpdate() { RootViewManager()->mHasPendingUpdates = true; }
void PostPendingUpdate();
PRUint32 AppUnitsPerDevPixel() const
{
@ -268,21 +227,16 @@ private:
// never null (if we have no ancestors, it will be |this|).
nsViewManager *mRootViewManager;
nsRevocableEventPtr<nsInvalidateEvent> mInvalidateEvent;
// The following members should not be accessed directly except by
// the root view manager. Some have accessor functions to enforce
// this, as noted.
// Use IncrementUpdateCount(), DecrementUpdateCount(), UpdateCount(),
// ClearUpdateCount() on the root viewmanager to access mUpdateCnt.
PRInt32 mUpdateCnt;
PRInt32 mUpdateBatchCnt;
PRUint32 mUpdateBatchFlags;
PRInt32 mRefreshDisableCount;
// Use IsPainting() and SetPainting() to access mPainting.
bool mPainting;
bool mRecursiveRefreshPending;
bool mHasPendingUpdates;
bool mHasPendingWidgetGeometryChanges;
bool mInScroll;
//from here to public should be static and locked... MMP
@ -290,24 +244,6 @@ private:
//list of view managers
static nsVoidArray *gViewManagers;
void PostInvalidateEvent();
};
class nsInvalidateEvent : public nsRunnable {
public:
nsInvalidateEvent(class nsViewManager *vm) : mViewManager(vm) {
NS_ASSERTION(mViewManager, "null parameter");
}
void Revoke() { mViewManager = nsnull; }
NS_IMETHOD Run() {
if (mViewManager)
mViewManager->ProcessInvalidateEvent();
return NS_OK;
}
protected:
class nsViewManager *mViewManager;
};
#endif /* nsViewManager_h___ */

View File

@ -590,20 +590,13 @@ nsWindow::IsEnabled(bool *aState)
}
NS_IMETHODIMP
nsWindow::Invalidate(const nsIntRect &aRect,
bool aIsSynchronous)
nsWindow::Invalidate(const nsIntRect &aRect)
{
AndroidGeckoEvent *event = new AndroidGeckoEvent(AndroidGeckoEvent::DRAW, aRect);
nsAppShell::gAppShell->PostEvent(event);
return NS_OK;
}
NS_IMETHODIMP
nsWindow::Update()
{
return NS_OK;
}
nsWindow*
nsWindow::FindTopLevel()
{

View File

@ -120,9 +120,7 @@ public:
NS_IMETHOD SetSizeMode(PRInt32 aMode);
NS_IMETHOD Enable(bool aState);
NS_IMETHOD IsEnabled(bool *aState);
NS_IMETHOD Invalidate(const nsIntRect &aRect,
bool aIsSynchronous);
NS_IMETHOD Update();
NS_IMETHOD Invalidate(const nsIntRect &aRect);
NS_IMETHOD SetFocus(bool aRaise = false);
NS_IMETHOD GetScreenBounds(nsIntRect &aRect);
virtual nsIntPoint WidgetToScreenOffset();

View File

@ -418,7 +418,7 @@ public:
NS_IMETHOD SetFocus(bool aRaise);
NS_IMETHOD GetBounds(nsIntRect &aRect);
NS_IMETHOD Invalidate(const nsIntRect &aRect, bool aIsSynchronous);
NS_IMETHOD Invalidate(const nsIntRect &aRect);
virtual void* GetNativeData(PRUint32 aDataType);
virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations);
@ -429,7 +429,6 @@ public:
{ return aStatus == nsEventStatus_eConsumeNoDefault; }
NS_IMETHOD DispatchEvent(nsGUIEvent* event, nsEventStatus & aStatus);
NS_IMETHOD Update();
virtual bool GetShouldAccelerate();
NS_IMETHOD SetCursor(nsCursor aCursor);

View File

@ -1398,7 +1398,7 @@ static void blinkRgn(RgnHandle rgn)
#endif
// Invalidate this component's visible area
NS_IMETHODIMP nsChildView::Invalidate(const nsIntRect &aRect, bool aIsSynchronous)
NS_IMETHODIMP nsChildView::Invalidate(const nsIntRect &aRect)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
@ -1408,10 +1408,7 @@ NS_IMETHODIMP nsChildView::Invalidate(const nsIntRect &aRect, bool aIsSynchronou
NSRect r;
nsCocoaUtils::GeckoRectToNSRect(aRect, r);
if (aIsSynchronous) {
[mView displayRect:r];
}
else if ([NSView focusView]) {
if ([NSView focusView]) {
// if a view is focussed (i.e. being drawn), then postpone the invalidate so that we
// don't lose it.
[mView setNeedsPendingDisplayInRect:r];
@ -1442,15 +1439,6 @@ inline PRUint16 COLOR8TOCOLOR16(PRUint8 color8)
return (color8 << 8) | color8; /* (color8 * 257) == (color8 * 0x0101) */
}
// The OS manages repaints well enough on its own, so we don't have to
// flush them out here. In other words, the OS will automatically call
// displayIfNeeded at the appropriate times, so we don't need to do it
// ourselves. See bmo bug 459319.
NS_IMETHODIMP nsChildView::Update()
{
return NS_OK;
}
#pragma mark -
nsresult nsChildView::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
@ -2520,6 +2508,7 @@ NSEvent* gLastDragMouseDownEvent = nil;
#endif
// Create the event so we can fill in its region
nsPaintEvent paintEvent(true, NS_PAINT, mGeckoChild);
paintEvent.didSendWillPaint = true;
nsIntRect boundingRect =
nsIntRect(aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height);

View File

@ -252,8 +252,7 @@ public:
NS_IMETHOD SetTitle(const nsAString& aTitle);
NS_IMETHOD Invalidate(const nsIntRect &aRect, bool aIsSynchronous);
NS_IMETHOD Update();
NS_IMETHOD Invalidate(const nsIntRect &aRect);
virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations);
virtual LayerManager* GetLayerManager(PLayersChild* aShadowManager = nsnull,
LayersBackend aBackendHint = LayerManager::LAYERS_NONE,

View File

@ -1279,18 +1279,10 @@ NS_IMETHODIMP nsCocoaWindow::SetTitle(const nsAString& aTitle)
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHODIMP nsCocoaWindow::Invalidate(const nsIntRect & aRect, bool aIsSynchronous)
NS_IMETHODIMP nsCocoaWindow::Invalidate(const nsIntRect & aRect)
{
if (mPopupContentView)
return mPopupContentView->Invalidate(aRect, aIsSynchronous);
return NS_OK;
}
NS_IMETHODIMP nsCocoaWindow::Update()
{
if (mPopupContentView)
return mPopupContentView->Update();
return mPopupContentView->Invalidate(aRect);
return NS_OK;
}

View File

@ -116,7 +116,7 @@ nsNativeThemeGTK::RefreshWidgetWindow(nsIFrame* aFrame)
if (!vm)
return;
vm->UpdateAllViews(NS_VMREFRESH_NO_SYNC);
vm->InvalidateAllViews();
}
static bool IsFrameContentNodeInNamespace(nsIFrame *aFrame, PRUint32 aNamespace)

View File

@ -1695,8 +1695,7 @@ nsWindow::SetCursor(imgIContainer* aCursor,
}
NS_IMETHODIMP
nsWindow::Invalidate(const nsIntRect &aRect,
bool aIsSynchronous)
nsWindow::Invalidate(const nsIntRect &aRect)
{
if (!mGdkWindow)
return NS_OK;
@ -1707,30 +1706,14 @@ nsWindow::Invalidate(const nsIntRect &aRect,
rect.width = aRect.width;
rect.height = aRect.height;
LOGDRAW(("Invalidate (rect) [%p]: %d %d %d %d (sync: %d)\n", (void *)this,
rect.x, rect.y, rect.width, rect.height, aIsSynchronous));
LOGDRAW(("Invalidate (rect) [%p]: %d %d %d %d\n", (void *)this,
rect.x, rect.y, rect.width, rect.height));
gdk_window_invalidate_rect(mGdkWindow, &rect, FALSE);
if (aIsSynchronous)
gdk_window_process_updates(mGdkWindow, FALSE);
return NS_OK;
}
NS_IMETHODIMP
nsWindow::Update()
{
if (!mGdkWindow)
return NS_OK;
LOGDRAW(("Update [%p] %p\n", this, mGdkWindow));
gdk_window_process_updates(mGdkWindow, FALSE);
// Send the updates to the server.
gdk_display_flush(gdk_window_get_display(mGdkWindow));
return NS_OK;
}
void*
nsWindow::GetNativeData(PRUint32 aDataType)
{

View File

@ -173,9 +173,7 @@ public:
NS_IMETHOD SetCursor(nsCursor aCursor);
NS_IMETHOD SetCursor(imgIContainer* aCursor,
PRUint32 aHotspotX, PRUint32 aHotspotY);
NS_IMETHOD Invalidate(const nsIntRect &aRect,
bool aIsSynchronous);
NS_IMETHOD Update();
NS_IMETHOD Invalidate(const nsIntRect &aRect);
virtual void* GetNativeData(PRUint32 aDataType);
NS_IMETHOD SetTitle(const nsAString& aTitle);
NS_IMETHOD SetIcon(const nsAString& aIconSpec);

View File

@ -737,13 +737,15 @@ class nsPaintEvent : public nsGUIEvent
public:
nsPaintEvent(bool isTrusted, PRUint32 msg, nsIWidget *w)
: nsGUIEvent(isTrusted, msg, w, NS_PAINT_EVENT),
willSendDidPaint(false)
willSendDidPaint(false),
didSendWillPaint(false)
{
}
// area that needs repainting
nsIntRegion region;
bool willSendDidPaint;
bool didSendWillPaint;
};
/**

View File

@ -118,8 +118,8 @@ typedef nsEventStatus (* EVENT_CALLBACK)(nsGUIEvent *event);
#endif
#define NS_IWIDGET_IID \
{ 0x6ca77c11, 0xade7, 0x4715, \
{ 0x82, 0xe0, 0xfe, 0xae, 0x42, 0xca, 0x5b, 0x1f } }
{ 0xba20ac65, 0xb2a6, 0x4052, \
{ 0xa4, 0xcb, 0x65, 0x40, 0xf8, 0x87, 0x9c, 0x55 } }
/*
* Window shadow styles
* Also used for the -moz-window-shadow CSS property
@ -1021,21 +1021,10 @@ class nsIWidget : public nsISupports {
NS_IMETHOD MakeFullScreen(bool aFullScreen) = 0;
/**
* Invalidate a specified rect for a widget and repaints it.
*
* @param aIsSynchronouse true then repaint synchronously. If false repaint later.
* @see #Update()
* Invalidate a specified rect for a widget so that it will be repainted
* later.
*/
NS_IMETHOD Invalidate(const nsIntRect & aRect, bool aIsSynchronous) = 0;
/**
* Force a synchronous repaint of the window if there are dirty rects.
*
* @see Invalidate()
*/
NS_IMETHOD Update() = 0;
NS_IMETHOD Invalidate(const nsIntRect & aRect) = 0;
enum LayerManagerPersistence
{

View File

@ -617,28 +617,12 @@ NS_METHOD nsWindow::SetFocus(bool aRaise)
//-----------------------------------------------------------------------------
NS_METHOD nsWindow::Invalidate(const nsIntRect& aRect, bool aIsSynchronous)
NS_METHOD nsWindow::Invalidate(const nsIntRect& aRect)
{
if (mWnd) {
RECTL rcl = {aRect.x, aRect.y, aRect.x + aRect.width, aRect.y + aRect.height};
NS2PM(rcl);
WinInvalidateRect(mWnd, &rcl, false);
#if 0
if (aIsSynchronous) {
Update();
}
#endif
}
return NS_OK;
}
//-----------------------------------------------------------------------------
// Force a synchronous repaint of the window.
NS_IMETHODIMP nsWindow::Update()
{
if (mWnd) {
WinUpdateWindow(mWnd);
}
return NS_OK;
}

View File

@ -175,9 +175,7 @@ public:
NS_IMETHOD Show(bool aState);
NS_IMETHOD IsVisible(bool& aState);
NS_IMETHOD SetFocus(bool aRaise);
NS_IMETHOD Invalidate(const nsIntRect& aRect,
bool aIsSynchronous);
NS_IMETHOD Update();
NS_IMETHOD Invalidate(const nsIntRect& aRect);
gfxASurface* GetThebesSurface();
virtual void* GetNativeData(PRUint32 aDataType);
virtual void FreeNativeData(void* aDatum, PRUint32 aDataType);

View File

@ -751,11 +751,10 @@ nsWindow::SetCursor(imgIContainer* aCursor,
}
NS_IMETHODIMP
nsWindow::Invalidate(const nsIntRect &aRect,
bool aIsSynchronous)
nsWindow::Invalidate(const nsIntRect &aRect)
{
LOGDRAW(("Invalidate (rect) [%p,%p]: %d %d %d %d (sync: %d)\n", (void *)this,
(void*)mWidget,aRect.x, aRect.y, aRect.width, aRect.height, aIsSynchronous));
LOGDRAW(("Invalidate (rect) [%p,%p]: %d %d %d %d\n", (void *)this,
(void*)mWidget,aRect.x, aRect.y, aRect.width, aRect.height));
if (!mWidget)
return NS_OK;
@ -764,19 +763,6 @@ nsWindow::Invalidate(const nsIntRect &aRect,
mWidget->update(aRect.x, aRect.y, aRect.width, aRect.height);
// QGraphicsItems cannot trigger a repaint themselves, so we start it on the view
if (aIsSynchronous) {
QWidget *widget = GetViewWidget();
if (widget)
widget->repaint();
}
return NS_OK;
}
NS_IMETHODIMP
nsWindow::Update()
{
return NS_OK;
}

View File

@ -173,9 +173,7 @@ public:
NS_IMETHOD GetHasTransparentBackground(bool& aTransparent);
NS_IMETHOD HideWindowChrome(bool aShouldHide);
NS_IMETHOD MakeFullScreen(bool aFullScreen);
NS_IMETHOD Invalidate(const nsIntRect &aRect,
bool aIsSynchronous);
NS_IMETHOD Update();
NS_IMETHOD Invalidate(const nsIntRect &aRect);
virtual void* GetNativeData(PRUint32 aDataType);
NS_IMETHOD SetTitle(const nsAString& aTitle);

View File

@ -1241,8 +1241,12 @@ NS_METHOD nsWindow::Show(bool bState)
}
#ifdef MOZ_XUL
if (!wasVisible && bState)
Invalidate(syncInvalidate);
if (!wasVisible && bState) {
Invalidate();
if (syncInvalidate) {
::UpdateWindow(mWnd);
}
}
#endif
return NS_OK;
@ -1448,7 +1452,7 @@ NS_METHOD nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, bool aRepaint)
}
if (aRepaint)
Invalidate(false);
Invalidate();
return NS_OK;
}
@ -1487,7 +1491,7 @@ NS_METHOD nsWindow::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeig
}
if (aRepaint)
Invalidate(false);
Invalidate();
return NS_OK;
}
@ -1978,7 +1982,7 @@ nsWindow::ResetLayout()
OnResize(evRect);
// Invalidate and update
Invalidate(false);
Invalidate();
}
// Internally track the caption status via a window property. Required
@ -2656,8 +2660,7 @@ NS_IMETHODIMP nsWindow::HideWindowChrome(bool aShouldHide)
**************************************************************/
// Invalidate this component visible area
NS_METHOD nsWindow::Invalidate(bool aIsSynchronous,
bool aEraseBackground,
NS_METHOD nsWindow::Invalidate(bool aEraseBackground,
bool aUpdateNCArea,
bool aIncludeChildren)
{
@ -2669,7 +2672,6 @@ NS_METHOD nsWindow::Invalidate(bool aIsSynchronous,
debug_DumpInvalidate(stdout,
this,
nsnull,
aIsSynchronous,
nsCAutoString("noname"),
(PRInt32) mWnd);
#endif // WIDGET_DEBUG_OUTPUT
@ -2678,9 +2680,6 @@ NS_METHOD nsWindow::Invalidate(bool aIsSynchronous,
if (aEraseBackground) {
flags |= RDW_ERASE;
}
if (aIsSynchronous) {
flags |= RDW_UPDATENOW;
}
if (aUpdateNCArea) {
flags |= RDW_FRAME;
}
@ -2693,7 +2692,7 @@ NS_METHOD nsWindow::Invalidate(bool aIsSynchronous,
}
// Invalidate this component visible area
NS_METHOD nsWindow::Invalidate(const nsIntRect & aRect, bool aIsSynchronous)
NS_METHOD nsWindow::Invalidate(const nsIntRect & aRect)
{
if (mWnd)
{
@ -2701,7 +2700,6 @@ NS_METHOD nsWindow::Invalidate(const nsIntRect & aRect, bool aIsSynchronous)
debug_DumpInvalidate(stdout,
this,
&aRect,
aIsSynchronous,
nsCAutoString("noname"),
(PRInt32) mWnd);
#endif // WIDGET_DEBUG_OUTPUT
@ -2714,10 +2712,6 @@ NS_METHOD nsWindow::Invalidate(const nsIntRect & aRect, bool aIsSynchronous)
rect.bottom = aRect.y + aRect.height;
VERIFY(::InvalidateRect(mWnd, &rect, FALSE));
if (aIsSynchronous) {
VERIFY(::UpdateWindow(mWnd));
}
}
return NS_OK;
}
@ -2757,7 +2751,7 @@ nsWindow::MakeFullScreen(bool aFullScreen)
if (visible) {
Show(true);
Invalidate(false);
Invalidate();
}
// Notify the taskbar that we have exited full screen mode.
@ -2774,26 +2768,6 @@ nsWindow::MakeFullScreen(bool aFullScreen)
return rv;
}
/**************************************************************
*
* SECTION: nsIWidget::Update
*
* Force a synchronous repaint of the window.
*
**************************************************************/
NS_IMETHODIMP nsWindow::Update()
{
nsresult rv = NS_OK;
// updates can come through for windows no longer holding an mWnd during
// deletes triggered by JavaScript in buttons with mouse feedback
if (mWnd)
VERIFY(::UpdateWindow(mWnd));
return rv;
}
/**************************************************************
*
* SECTION: Native data storage
@ -4678,7 +4652,7 @@ bool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam,
// Invalidate the window so that the repaint will
// pick up the new theme.
Invalidate(true, true, true, true);
Invalidate(true, true, true);
}
break;
@ -5357,7 +5331,7 @@ bool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam,
BroadcastMsg(mWnd, WM_DWMCOMPOSITIONCHANGED);
DispatchStandardEvent(NS_THEMECHANGED);
UpdateGlass();
Invalidate(true, true, true, true);
Invalidate(true, true, true);
break;
#endif
@ -7246,7 +7220,7 @@ nsWindow::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
r.Sub(bounds, configuration.mBounds);
r.MoveBy(-bounds.x,
-bounds.y);
w->Invalidate(r.GetBounds(), false);
w->Invalidate(r.GetBounds());
}
}
rv = w->SetWindowClipRegion(configuration.mClipRegion, false);
@ -7466,7 +7440,7 @@ bool nsWindow::OnResize(nsIntRect &aWindowRect)
#ifdef CAIRO_HAS_D2D_SURFACE
if (mD2DWindowSurface) {
mD2DWindowSurface = NULL;
Invalidate(false);
Invalidate();
}
#endif

View File

@ -146,12 +146,10 @@ public:
virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations);
NS_IMETHOD MakeFullScreen(bool aFullScreen);
NS_IMETHOD HideWindowChrome(bool aShouldHide);
NS_IMETHOD Invalidate(bool aIsSynchronous,
bool aEraseBackground = false,
NS_IMETHOD Invalidate(bool aEraseBackground = false,
bool aUpdateNCArea = false,
bool aIncludeChildren = false);
NS_IMETHOD Invalidate(const nsIntRect & aRect, bool aIsSynchronous);
NS_IMETHOD Update();
NS_IMETHOD Invalidate(const nsIntRect & aRect);
virtual void* GetNativeData(PRUint32 aDataType);
virtual void FreeNativeData(void * data, PRUint32 aDataType);
NS_IMETHOD SetTitle(const nsAString& aTitle);

View File

@ -312,6 +312,7 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32 aNestingLevel)
#endif
event.region = GetRegionToPaint(forceRepaint, ps, hDC);
event.willSendDidPaint = true;
event.didSendWillPaint = true;
if (!event.region.IsEmpty() && mEventCallback)
{
@ -576,7 +577,7 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32 aNestingLevel)
// When our device was removed, we should have gfxWindowsPlatform
// check if its render mode is up to date!
gfxWindowsPlatform::GetPlatform()->UpdateRenderMode();
Invalidate(false);
Invalidate();
}
}
break;
@ -587,7 +588,7 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32 aNestingLevel)
gfxWindowsPlatform::GetPlatform()->UpdateRenderMode();
LayerManagerD3D10 *layerManagerD3D10 = static_cast<mozilla::layers::LayerManagerD3D10*>(GetLayerManager());
if (layerManagerD3D10->device() != gfxWindowsPlatform::GetPlatform()->GetD3D10Device()) {
Invalidate(false);
Invalidate();
} else {
result = DispatchWindowEvent(&event, eventStatus);
}

View File

@ -56,7 +56,7 @@ InvalidateRegion(nsIWidget* aWidget, const nsIntRegion& aRegion)
{
nsIntRegionRectIterator it(aRegion);
while(const nsIntRect* r = it.Next()) {
aWidget->Invalidate(*r, false/*async*/);
aWidget->Invalidate(*r);
}
}
@ -228,25 +228,20 @@ PuppetWidget::SetFocus(bool aRaise)
}
NS_IMETHODIMP
PuppetWidget::Invalidate(const nsIntRect& aRect, bool aIsSynchronous)
PuppetWidget::Invalidate(const nsIntRect& aRect)
{
#ifdef DEBUG
debug_DumpInvalidate(stderr, this, &aRect, aIsSynchronous,
debug_DumpInvalidate(stderr, this, &aRect,
nsCAutoString("PuppetWidget"), nsnull);
#endif
if (mChild) {
return mChild->Invalidate(aRect, aIsSynchronous);
return mChild->Invalidate(aRect);
}
mDirtyRegion.Or(mDirtyRegion, aRect);
if (mDirtyRegion.IsEmpty()) {
return NS_OK;
} else if (aIsSynchronous) {
DispatchPaintEvent();
return NS_OK;
} else if (!mPaintTask.IsPending()) {
if (!mDirtyRegion.IsEmpty() && !mPaintTask.IsPending()) {
mPaintTask = new PaintTask(this);
return NS_DispatchToCurrentThread(mPaintTask.get());
}
@ -254,19 +249,6 @@ PuppetWidget::Invalidate(const nsIntRect& aRect, bool aIsSynchronous)
return NS_OK;
}
NS_IMETHODIMP
PuppetWidget::Update()
{
if (mChild) {
return mChild->Update();
}
if (mDirtyRegion.IsEmpty()) {
return NS_OK;
}
return DispatchPaintEvent();
}
void
PuppetWidget::InitEvent(nsGUIEvent& event, nsIntPoint* aPoint)
{

View File

@ -123,9 +123,7 @@ public:
virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
{ return NS_OK; }
NS_IMETHOD Invalidate(const nsIntRect& aRect, bool aIsSynchronous);
NS_IMETHOD Update();
NS_IMETHOD Invalidate(const nsIntRect& aRect);
// This API is going away, steer clear.
virtual void Scroll(const nsIntPoint& aDelta,

View File

@ -1469,7 +1469,6 @@ nsBaseWidget::debug_DumpPaintEvent(FILE * aFileOut,
nsBaseWidget::debug_DumpInvalidate(FILE * aFileOut,
nsIWidget * aWidget,
const nsIntRect * aRect,
bool aIsSynchronous,
const nsCAutoString & aWidgetName,
PRInt32 aWindowID)
{
@ -1501,10 +1500,6 @@ nsBaseWidget::debug_DumpInvalidate(FILE * aFileOut,
" rect=%-15s",
"none");
}
fprintf(aFileOut,
" sync=%s",
(const char *) (aIsSynchronous ? "yes" : "no "));
fprintf(aFileOut,"\n");
}

View File

@ -297,7 +297,6 @@ protected:
static void debug_DumpInvalidate(FILE * aFileOut,
nsIWidget * aWidget,
const nsIntRect * aRect,
bool aIsSynchronous,
const nsCAutoString & aWidgetName,
PRInt32 aWindowID);

View File

@ -68,7 +68,6 @@ EXPORTS = \
nsThread.h \
nsProcess.h \
nsEventQueue.h \
nsThreadUtilsInternal.h \
$(NULL)
EXPORTS_mozilla = \

View File

@ -44,7 +44,6 @@
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "prlog.h"
#include "nsThreadUtilsInternal.h"
#include "nsIObserverService.h"
#include "mozilla/HangMonitor.h"
#include "mozilla/Services.h"
@ -81,8 +80,6 @@ static PRLogModuleInfo *sLog = PR_NewLogModule("nsThread");
NS_DECL_CI_INTERFACE_GETTER(nsThread)
nsIThreadObserver* nsThread::sGlobalObserver;
namespace mozilla {
// Fun fact: Android's GCC won't convert bool* to PRInt32*, so we can't
@ -506,6 +503,11 @@ nsThread::Shutdown()
PR_JoinThread(mThread);
mThread = nsnull;
// We hold strong references to our event observers, and once the thread is
// shut down the observers can't easily unregister themselves. Do it here
// to avoid leaking.
ClearObservers();
#ifdef DEBUG
{
MutexAutoLock lock(mLock);
@ -612,11 +614,6 @@ nsThread::ProcessNextEvent(bool mayWait, bool *result)
}
}
bool notifyGlobalObserver = (sGlobalObserver != nsnull);
if (notifyGlobalObserver)
sGlobalObserver->OnProcessNextEvent(this, mayWait && !ShuttingDown(),
mRunningEvent);
nsCOMPtr<nsIThreadObserver> obs = mObserver;
if (obs)
obs->OnProcessNextEvent(this, mayWait && !ShuttingDown(), mRunningEvent);
@ -672,9 +669,6 @@ nsThread::ProcessNextEvent(bool mayWait, bool *result)
if (obs)
obs->AfterProcessNextEvent(this, mRunningEvent);
if (notifyGlobalObserver && sGlobalObserver)
sGlobalObserver->AfterProcessNextEvent(this, mRunningEvent);
return rv;
}
@ -839,18 +833,3 @@ nsThreadSyncDispatch::Run()
}
return NS_OK;
}
nsresult
NS_SetGlobalThreadObserver(nsIThreadObserver* aObserver)
{
if (aObserver && nsThread::sGlobalObserver) {
return NS_ERROR_NOT_AVAILABLE;
}
if (!NS_IsMainThread()) {
return NS_ERROR_UNEXPECTED;
}
nsThread::sGlobalObserver = aObserver;
return NS_OK;
}

View File

@ -77,8 +77,8 @@ public:
// nsIThreadManager::NewThread.
bool ShutdownRequired() { return mShutdownRequired; }
// The global thread observer
static nsIThreadObserver* sGlobalObserver;
// Clear the observer list.
void ClearObservers() { mEventObservers.Clear(); }
private:
friend class nsThreadShutdownEvent;

View File

@ -176,6 +176,7 @@ nsThreadManager::Shutdown()
// main thread is special we do it manually here after we're sure all events
// have been processed.
mMainThread->SetObserver(nsnull);
mMainThread->ClearObservers();
// Release main thread object.
mMainThread = nsnull;

View File

@ -1,61 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla code.
*
* The Initial Developer of the Original Code is the Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Boris Zbarsky <bzbarsky@mit.edu>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsThreadUtilsInternal_h_
#define nsThreadUtilsInternal_h_
#ifdef MOZILLA_INTERNAL_API
class nsIThreadObserver;
/**
* Function to set a "global" thread observer that all threads will notify when
* they process an event. This observer will not be notified when events are
* posted to threads. Only one global observer can be set at a time; an
* attempt to change the value without setting it to null first will throw.
* This function does NOT take a reference to the observer; the caller of this
* function is responsible for setting the observer to null when it goes away.
* This method may only be called on the main thread; attempts to do it on
* other threads will return an error.
*/
extern nsresult
NS_SetGlobalThreadObserver(nsIThreadObserver* aObserver);
#endif // MOZILLA_INTERNAL_API
#endif // nsThreadUtilsInternal_h_