mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c tip to m-i
This commit is contained in:
commit
94e66a942e
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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');
|
||||
|
||||
|
37
content/html/content/test/test_bug717819.html
Normal file
37
content/html/content/test/test_bug717819.html
Normal 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>
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
||||
/************************************************************************/
|
||||
|
@ -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) */
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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?");
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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))) {
|
||||
|
@ -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];
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -9,6 +9,7 @@ html, body {
|
||||
display: -moz-box;
|
||||
margin: 0; padding: 0;
|
||||
width: 100%; height: 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
body > div {
|
||||
|
@ -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 {
|
||||
|
11
layout/reftests/svg/dynamic-text-07-ref.svg
Normal file
11
layout/reftests/svg/dynamic-text-07-ref.svg
Normal 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 |
23
layout/reftests/svg/dynamic-text-07.svg
Normal file
23
layout/reftests/svg/dynamic-text-07.svg
Normal 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 |
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -562,7 +562,7 @@ void nsLayoutDebuggingTools::ForceRefresh()
|
||||
return;
|
||||
nsIView* root = vm->GetRootView();
|
||||
if (root) {
|
||||
vm->UpdateView(root, NS_VMREFRESH_IMMEDIATE);
|
||||
vm->InvalidateView(root);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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');
|
||||
|
||||
|
@ -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');
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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___
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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___ */
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -297,7 +297,6 @@ protected:
|
||||
static void debug_DumpInvalidate(FILE * aFileOut,
|
||||
nsIWidget * aWidget,
|
||||
const nsIntRect * aRect,
|
||||
bool aIsSynchronous,
|
||||
const nsCAutoString & aWidgetName,
|
||||
PRInt32 aWindowID);
|
||||
|
||||
|
@ -68,7 +68,6 @@ EXPORTS = \
|
||||
nsThread.h \
|
||||
nsProcess.h \
|
||||
nsEventQueue.h \
|
||||
nsThreadUtilsInternal.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS_mozilla = \
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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_
|
Loading…
Reference in New Issue
Block a user