Merge inbound to m-c.

This commit is contained in:
Ryan VanderMeulen 2013-06-11 15:01:22 -04:00
commit a07587452c
36 changed files with 380 additions and 411 deletions

View File

@ -32,7 +32,6 @@ public:
FrameMetrics()
: mCompositionBounds(0, 0, 0, 0)
, mContentRect(0, 0, 0, 0)
, mDisplayPort(0, 0, 0, 0)
, mCriticalDisplayPort(0, 0, 0, 0)
, mViewport(0, 0, 0, 0)
@ -51,7 +50,6 @@ public:
bool operator==(const FrameMetrics& aOther) const
{
return mCompositionBounds.IsEqualEdges(aOther.mCompositionBounds) &&
mContentRect.IsEqualEdges(aOther.mContentRect) &&
mDisplayPort.IsEqualEdges(aOther.mDisplayPort) &&
mCriticalDisplayPort.IsEqualEdges(aOther.mCriticalDisplayPort) &&
mViewport.IsEqualEdges(aOther.mViewport) &&
@ -122,17 +120,6 @@ public:
// metric as they do not have a displayport set. See bug 775452.
LayerIntRect mCompositionBounds;
// |mScrollableRect|, stored in layer pixels. DECPRECATED, DO NOT USE.
//
// This is valid on any layer where |mScrollableRect| is, though it may be
// more lazily maintained than |mScrollableRect|. That is, when
// |mScrollableRect| is updated, this may lag. For this reason, it's better to
// use |mScrollableRect| for any control logic.
//
// FIXME/bug 785929: Is this really necessary? Can it not be calculated from
// |mScrollableRect| whenever it's needed?
LayerIntRect mContentRect;
// ---------------------------------------------------------------------------
// The following metrics are all in CSS pixels. They are not in any uniform
// space, so each is explained separately.

View File

@ -411,15 +411,14 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer, const gfx3DMatr
metrics.mScrollOffset, layerPixelRatioX, layerPixelRatioY);
if (mIsFirstPaint) {
mContentRect = metrics.mContentRect;
mContentRect = metrics.mScrollableRect;
SetFirstPaintViewport(scrollOffsetLayerPixels,
layerPixelRatioX,
mContentRect,
metrics.mScrollableRect);
mContentRect);
mIsFirstPaint = false;
} else if (!metrics.mContentRect.IsEqualEdges(mContentRect)) {
mContentRect = metrics.mContentRect;
SetPageRect(metrics.mScrollableRect);
} else if (!metrics.mScrollableRect.IsEqualEdges(mContentRect)) {
mContentRect = metrics.mScrollableRect;
SetPageRect(mContentRect);
}
// We synchronise the viewport information with Java after sending the above
@ -470,26 +469,27 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer, const gfx3DMatr
gfxPoint fixedOffset;
gfxSize scaleDiff;
LayerRect content = LayerRect::FromCSSRect(mContentRect,
1 / aRootTransform.GetXScale(),
1 / aRootTransform.GetYScale());
// If the contents can fit entirely within the widget area on a particular
// dimenson, we need to translate and scale so that the fixed layers remain
// dimension, we need to translate and scale so that the fixed layers remain
// within the page boundaries.
if (mContentRect.width * tempScaleDiffX < metrics.mCompositionBounds.width) {
if (mContentRect.width * scaleX < metrics.mCompositionBounds.width) {
fixedOffset.x = -metricsScrollOffset.x;
scaleDiff.width = std::min(1.0f, metrics.mCompositionBounds.width / (float)mContentRect.width);
scaleDiff.width = std::min(1.0f, metrics.mCompositionBounds.width / content.width);
} else {
fixedOffset.x = clamped(scrollOffset.x / tempScaleDiffX, (float)mContentRect.x,
mContentRect.XMost() - metrics.mCompositionBounds.width / tempScaleDiffX) -
metricsScrollOffset.x;
fixedOffset.x = clamped(scrollOffset.x / tempScaleDiffX, content.x,
content.XMost() - metrics.mCompositionBounds.width / tempScaleDiffX) - metricsScrollOffset.x;
scaleDiff.width = tempScaleDiffX;
}
if (mContentRect.height * tempScaleDiffY < metrics.mCompositionBounds.height) {
if (mContentRect.height * scaleY < metrics.mCompositionBounds.height) {
fixedOffset.y = -metricsScrollOffset.y;
scaleDiff.height = std::min(1.0f, metrics.mCompositionBounds.height / (float)mContentRect.height);
scaleDiff.height = std::min(1.0f, metrics.mCompositionBounds.height / content.height);
} else {
fixedOffset.y = clamped(scrollOffset.y / tempScaleDiffY, (float)mContentRect.y,
mContentRect.YMost() - metrics.mCompositionBounds.height / tempScaleDiffY) -
metricsScrollOffset.y;
fixedOffset.y = clamped(scrollOffset.y / tempScaleDiffY, content.y,
content.YMost() - metrics.mCompositionBounds.height / tempScaleDiffY) - metricsScrollOffset.y;
scaleDiff.height = tempScaleDiffY;
}
@ -552,11 +552,10 @@ AsyncCompositionManager::TransformShadowTree(TimeStamp aCurrentFrame)
void
AsyncCompositionManager::SetFirstPaintViewport(const LayerIntPoint& aOffset,
float aZoom,
const LayerIntRect& aPageRect,
const CSSRect& aCssPageRect)
{
#ifdef MOZ_WIDGET_ANDROID
AndroidBridge::Bridge()->SetFirstPaintViewport(aOffset, aZoom, aPageRect, aCssPageRect);
AndroidBridge::Bridge()->SetFirstPaintViewport(aOffset, aZoom, aCssPageRect);
#endif
}

View File

@ -116,7 +116,6 @@ private:
void SetFirstPaintViewport(const LayerIntPoint& aOffset,
float aZoom,
const LayerIntRect& aPageRect,
const CSSRect& aCssPageRect);
void SetPageRect(const CSSRect& aCssPageRect);
void SyncViewportInfo(const LayerIntRect& aDisplayPort,
@ -163,7 +162,7 @@ private:
void DetachRefLayers();
TargetConfig mTargetConfig;
LayerIntRect mContentRect;
CSSRect mContentRect;
nsRefPtr<LayerManagerComposite> mLayerManager;
// When this flag is set, the next composition will be the first for a

View File

@ -251,15 +251,17 @@ ThebesLayerComposite::GetCompositionBounds()
// Get the content document bounds, in screen-space.
const FrameMetrics& metrics = scrollableLayer->GetFrameMetrics();
const LayerIntSize& contentSize = metrics.mContentRect.Size();
const LayerIntRect content = LayerIntRect::FromCSSRectRounded(metrics.mScrollableRect,
1 / scaleX,
1 / scaleY);
gfx::Point scrollOffset =
gfx::Point((metrics.mScrollOffset.x * metrics.LayersPixelsPerCSSPixel().width) / scaleX,
(metrics.mScrollOffset.y * metrics.LayersPixelsPerCSSPixel().height) / scaleY);
const nsIntPoint contentOrigin(
metrics.mContentRect.x - NS_lround(scrollOffset.x),
metrics.mContentRect.y - NS_lround(scrollOffset.y));
content.x - NS_lround(scrollOffset.x),
content.y - NS_lround(scrollOffset.y));
gfxRect contentRect = gfxRect(contentOrigin.x, contentOrigin.y,
contentSize.width, contentSize.height);
content.width, content.height);
gfxRect contentBounds = scrollableLayer->GetEffectiveTransform().
TransformBounds(contentRect);

View File

@ -832,19 +832,6 @@ void AsyncPanZoomController::ScrollBy(const gfx::Point& aOffset) {
mFrameMetrics = metrics;
}
void AsyncPanZoomController::SetPageRect(const CSSRect& aCSSPageRect) {
FrameMetrics metrics = mFrameMetrics;
gfxFloat resolution = CalculateResolution(mFrameMetrics).width;
// The page rect is the css page rect scaled by the current zoom.
// Round the page rect so we don't get any truncation, then get the nsIntRect
// from this.
metrics.mContentRect = LayerRect::FromCSSRectRoundOut(aCSSPageRect, resolution, resolution);
metrics.mScrollableRect = aCSSPageRect;
mFrameMetrics = metrics;
}
void AsyncPanZoomController::ScaleWithFocus(float aZoom,
const nsIntPoint& aFocus) {
float zoomFactor = aZoom / mFrameMetrics.mZoom.width;
@ -852,10 +839,6 @@ void AsyncPanZoomController::ScaleWithFocus(float aZoom,
SetZoomAndResolution(aZoom);
// Force a recalculation of the page rect based on the new zoom and the
// current CSS page rect (which is unchanged since it's not affected by zoom).
SetPageRect(mFrameMetrics.mScrollableRect);
// If the new scale is very small, we risk multiplying in huge rounding
// errors, so don't bother adjusting the scroll offset.
if (resolution >= 0.01f) {
@ -1272,12 +1255,9 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFr
mFrameMetrics = aViewportFrame;
SetPageRect(mFrameMetrics.mScrollableRect);
mState = NOTHING;
} else if (!mFrameMetrics.mScrollableRect.IsEqualEdges(aViewportFrame.mScrollableRect)) {
mFrameMetrics.mScrollableRect = aViewportFrame.mScrollableRect;
SetPageRect(mFrameMetrics.mScrollableRect);
}
if (needContentRepaint) {

View File

@ -198,12 +198,6 @@ public:
// These methods can be called from any thread.
//
/**
* Sets the CSS page rect, and calculates a new page rect based on the zoom
* level of the current metrics and the passed in CSS page rect.
*/
void SetPageRect(const CSSRect& aCSSPageRect);
/**
* Sets the DPI of the device for use within panning and zooming logic. It is
* a platform responsibility to set this on initialization of this class and

View File

@ -1074,7 +1074,6 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
{
WriteParam(aMsg, aParam.mScrollableRect);
WriteParam(aMsg, aParam.mViewport);
WriteParam(aMsg, aParam.mContentRect);
WriteParam(aMsg, aParam.mScrollOffset);
WriteParam(aMsg, aParam.mDisplayPort);
WriteParam(aMsg, aParam.mCriticalDisplayPort);
@ -1091,7 +1090,6 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
{
return (ReadParam(aMsg, aIter, &aResult->mScrollableRect) &&
ReadParam(aMsg, aIter, &aResult->mViewport) &&
ReadParam(aMsg, aIter, &aResult->mContentRect) &&
ReadParam(aMsg, aIter, &aResult->mScrollOffset) &&
ReadParam(aMsg, aIter, &aResult->mDisplayPort) &&
ReadParam(aMsg, aIter, &aResult->mCriticalDisplayPort) &&

View File

@ -1377,7 +1377,7 @@ IonCompile(JSContext *cx, JSScript *script,
AutoFlushCache afc("IonCompile");
types::AutoEnterCompilation enterCompiler(cx, CompilerOutputKind(executionMode));
if (!enterCompiler.init(script, false, 0))
if (!enterCompiler.init(script))
return AbortReason_Disable;
AutoTempAllocatorRooter root(cx, temp);

View File

@ -3409,6 +3409,16 @@ IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target)
RootedScript calleeScript(cx, target->nonLazyScript());
BaselineInspector inspector(cx, target->nonLazyScript());
// Improve type information of |this| when not set.
if (callInfo.constructing() && !callInfo.thisArg()->resultTypeSet()) {
types::StackTypeSet *types = types::TypeScript::ThisTypes(calleeScript);
MTypeBarrier *barrier = MTypeBarrier::New(callInfo.thisArg(), cloneTypeSet(types), Bailout_Normal);
current->add(barrier);
MUnbox *unbox = MUnbox::New(barrier, MIRType_Object, MUnbox::Infallible);
current->add(unbox);
callInfo.setThis(unbox);
}
// Start inlining.
LifoAlloc *alloc = GetIonContext()->temp->lifoAlloc();
CompileInfo *info = alloc->new_<CompileInfo>(calleeScript.get(), target,

View File

@ -406,6 +406,8 @@ VirtualRegisterOfPayload(MDefinition *mir)
if (!inner->isConstant() && inner->type() != MIRType_Double)
return inner->virtualRegister();
}
if (mir->isTypeBarrier())
return VirtualRegisterOfPayload(mir->getOperand(0));
return mir->virtualRegister() + VREG_DATA_OFFSET;
}

View File

@ -2324,49 +2324,15 @@ StackTypeSet::propertyNeedsBarrier(JSContext *cx, jsid id)
return false;
}
enum RecompileKind {
RECOMPILE_CHECK_MONITORED,
RECOMPILE_CHECK_BARRIERS,
RECOMPILE_NONE
};
/*
* Whether all jitcode for a given pc was compiled with monitoring or barriers.
* If we reanalyze the script after generating jitcode, new monitoring and
* barriers will be added which may be duplicating information available when
* the script was originally compiled, and which should not invalidate that
* compilation.
*/
static inline bool
JITCodeHasCheck(JSScript *script, jsbytecode *pc, RecompileKind kind)
{
if (kind == RECOMPILE_NONE)
return false;
if (script->hasAnyIonScript() ||
script->isIonCompilingOffThread() ||
script->isParallelIonCompilingOffThread())
{
return false;
}
return true;
}
/*
* Force recompilation of any jitcode for script at pc, or of any other script
* Force recompilation of any jitcode for the script, or of any other script
* which this script was inlined into.
*/
static inline void
AddPendingRecompile(JSContext *cx, JSScript *script, jsbytecode *pc,
RecompileKind kind = RECOMPILE_NONE)
AddPendingRecompile(JSContext *cx, JSScript *script)
{
/*
* Trigger recompilation of the script itself, if code was not previously
* compiled with the specified information.
*/
if (!JITCodeHasCheck(script, pc, kind))
cx->compartment()->types.addPendingRecompile(cx, script, pc);
/* Trigger recompilation of the script itself. */
cx->compartment()->types.addPendingRecompile(cx, script);
/*
* Remind Ion not to save the compile code if generating type
@ -2422,7 +2388,7 @@ class TypeConstraintFreezeStack : public TypeConstraint
* not disable it on future changes to the type set.
*/
RootedScript script(cx, script_);
AddPendingRecompile(cx, script, NULL);
AddPendingRecompile(cx, script);
}
};
@ -2793,17 +2759,8 @@ TypeCompartment::processPendingRecompiles(FreeOp *fop)
JS_ASSERT(!pending->empty());
#ifdef JS_ION
for (unsigned i = 0; i < pending->length(); i++) {
CompilerOutput &co = *(*pending)[i].compilerOutput(*this);
switch (co.kind()) {
case CompilerOutput::Ion:
case CompilerOutput::ParallelIon:
break;
}
}
ion::Invalidate(*this, fop, *pending);
#endif /* JS_ION */
#endif
fop->delete_(pending);
}
@ -2915,7 +2872,7 @@ TypeCompartment::addPendingRecompile(JSContext *cx, const RecompileInfo &info)
}
void
TypeCompartment::addPendingRecompile(JSContext *cx, JSScript *script, jsbytecode *pc)
TypeCompartment::addPendingRecompile(JSContext *cx, JSScript *script)
{
JS_ASSERT(script);
if (!constrainedOutputs)
@ -2965,7 +2922,7 @@ TypeCompartment::monitorBytecode(JSContext *cx, JSScript *script, uint32_t offse
code.monitoredTypes = true;
AddPendingRecompile(cx, script, pc, RECOMPILE_CHECK_MONITORED);
AddPendingRecompile(cx, script);
}
void
@ -3053,7 +3010,7 @@ ScriptAnalysis::addTypeBarrier(JSContext *cx, const jsbytecode *pc, TypeSet *tar
* if any of the barriers is ever violated).
*/
RootedScript script(cx, script_);
AddPendingRecompile(cx, script, const_cast<jsbytecode*>(pc), RECOMPILE_CHECK_BARRIERS);
AddPendingRecompile(cx, script);
}
/* Ignore duplicate barriers. */
@ -3112,7 +3069,7 @@ ScriptAnalysis::addSingletonTypeBarrier(JSContext *cx, const jsbytecode *pc, Typ
if (!code.typeBarriers) {
/* Trigger recompilation as for normal type barriers. */
RootedScript script(cx, script_);
AddPendingRecompile(cx, script, const_cast<jsbytecode*>(pc), RECOMPILE_CHECK_BARRIERS);
AddPendingRecompile(cx, script);
}
InferSpew(ISpewOps, "singletonTypeBarrier: #%u:%05u: %sT%p%s %p %s",
@ -3163,8 +3120,6 @@ TypeCompartment::print(JSContext *cx, bool force)
printf("%u", typeCounts[count]);
}
printf(" (%u over)\n", typeCountOver);
printf("Recompilations: %u\n", recompilations);
}
/////////////////////////////////////////////////////////////////////
@ -5549,7 +5504,7 @@ types::MarkIteratorUnknownSlow(JSContext *cx)
result->next = script->types->dynamicList;
script->types->dynamicList = result;
AddPendingRecompile(cx, script, NULL);
AddPendingRecompile(cx, script);
if (!script->hasAnalysis() || !script->analysis()->ranInference())
return;
@ -5662,42 +5617,7 @@ types::TypeDynamicResult(JSContext *cx, JSScript *script, jsbytecode *pc, Type t
result->next = script->types->dynamicList;
script->types->dynamicList = result;
/*
* New type information normally requires all code in the entire script to
* be recompiled, as changes to types can flow through variables etc. into
* other chunks in the compiled script.
*
* We can do better than this, though, when we can prove the new type will
* only be visible at certain points in the script. Namely, for arithmetic
* operations which might produce doubles and are then passed to an
* expression that cancels out integer overflow, i.e.'OP & -1' or 'OP | 0',
* the new type will only affect OP and the bitwise operation.
*
* This can prevent a significant amount of recompilation in scripts which
* use these operations extensively, principally autotranslated code.
*/
jsbytecode *ignorePC = pc + GetBytecodeLength(pc);
if (*ignorePC == JSOP_POP) {
/* Value is ignored. */
} else if (*ignorePC == JSOP_INT8 && GET_INT8(ignorePC) == -1) {
ignorePC += JSOP_INT8_LENGTH;
if (*ignorePC != JSOP_BITAND)
ignorePC = NULL;
} else if (*ignorePC == JSOP_ZERO) {
ignorePC += JSOP_ZERO_LENGTH;
if (*ignorePC != JSOP_BITOR)
ignorePC = NULL;
} else {
ignorePC = NULL;
}
if (ignorePC) {
AddPendingRecompile(cx, script, pc);
AddPendingRecompile(cx, script, ignorePC);
} else {
AddPendingRecompile(cx, script, NULL);
}
AddPendingRecompile(cx, script);
if (script->hasAnalysis() && script->analysis()->ranInference()) {
TypeSet *pushed = script->analysis()->pushedTypes(pc, 0);

View File

@ -1291,10 +1291,7 @@ struct CompilerOutput
// but, for portability, bitfields are limited to bool, int, and
// unsigned int. You should really use the accessor below.
unsigned kindInt : 2;
bool constructing : 1;
bool barriers : 1;
bool pendingRecompilation : 1;
uint32_t chunkIndex:27;
CompilerOutput();
@ -1364,14 +1361,6 @@ struct TypeCompartment
/* Pending recompilations to perform before execution of JIT code can resume. */
Vector<RecompileInfo> *pendingRecompiles;
/*
* Number of recompilation events and inline frame expansions that have
* occurred in this compartment. If these change, code should not count on
* compiled code or the current stack being intact.
*/
unsigned recompilations;
unsigned frameExpansions;
/*
* Script currently being compiled. All constraints which look for type
* changes inducing recompilation are keyed to this script. Note: script
@ -1433,7 +1422,7 @@ struct TypeCompartment
/* Mark a script as needing recompilation once inference has finished. */
void addPendingRecompile(JSContext *cx, const RecompileInfo &info);
void addPendingRecompile(JSContext *cx, JSScript *script, jsbytecode *pc);
void addPendingRecompile(JSContext *cx, JSScript *script);
/* Monitor future effects on a bytecode. */
void monitorBytecode(JSContext *cx, JSScript *script, uint32_t offset,

View File

@ -92,10 +92,7 @@ namespace types {
inline
CompilerOutput::CompilerOutput()
: script(NULL),
kindInt(Ion),
constructing(false),
barriers(false),
chunkIndex(false)
kindInt(Ion)
{
}
@ -394,14 +391,11 @@ struct AutoEnterCompilation
JS_ASSERT(info.outputIndex == RecompileInfo::NoCompilerRunning);
}
bool init(JSScript *script, bool constructing, unsigned chunkIndex)
bool init(JSScript *script)
{
CompilerOutput co;
co.script = script;
co.setKind(kind);
co.constructing = constructing;
co.barriers = cx->zone()->compileBarriers();
co.chunkIndex = chunkIndex;
// This flag is used to prevent adding the current compiled script in
// the list of compiler output which should be invalided. This is

View File

@ -936,6 +936,10 @@ BailoutExplanation(ParallelBailoutCause cause)
return "unsupported string comparison";
case ParallelBailoutUnsupportedSparseArray:
return "unsupported sparse array";
case ParallelBailoutRequestedGC:
return "requested GC";
case ParallelBailoutRequestedZoneGC:
return "requested zone GC";
default:
return "no known reason";
}
@ -1445,6 +1449,8 @@ ForkJoinShared::check(ForkJoinSlice &slice)
// AutoRendezvous autoRendezvous(slice);
// if (!js_HandleExecutionInterrupt(cx_))
// return setAbortFlag(true);
slice.bailoutRecord->setCause(ParallelBailoutInterrupt,
NULL, NULL, NULL);
setAbortFlag(false);
return false;
}
@ -1641,6 +1647,8 @@ void
ForkJoinSlice::requestGC(JS::gcreason::Reason reason)
{
shared->requestGC(reason);
bailoutRecord->setCause(ParallelBailoutRequestedGC,
NULL, NULL, NULL);
shared->setAbortFlag(false);
}
@ -1648,6 +1656,8 @@ void
ForkJoinSlice::requestZoneGC(JS::Zone *zone, JS::gcreason::Reason reason)
{
shared->requestZoneGC(zone, reason);
bailoutRecord->setCause(ParallelBailoutRequestedZoneGC,
NULL, NULL, NULL);
shared->setAbortFlag(false);
}

View File

@ -258,6 +258,8 @@ enum ParallelBailoutCause {
ParallelBailoutUnsupported,
ParallelBailoutUnsupportedStringComparison,
ParallelBailoutUnsupportedSparseArray,
ParallelBailoutRequestedGC,
ParallelBailoutRequestedZoneGC,
};
struct ParallelBailoutTrace {

View File

@ -1012,6 +1012,11 @@ nsXPCWrappedJSClass::CheckForException(XPCCallContext & ccx,
!strcmp(aPropertyName, "getInterface")) {
reportable = false;
}
// More special case, see bug 877760.
if (e_result == NS_ERROR_XPC_JSOBJECT_HAS_NO_FUNCTION_NAMED) {
reportable = false;
}
}
// Try to use the error reporter set on the context to handle this

View File

@ -83,12 +83,6 @@ struct LayerPixel {
return RoundToInt(FromCSSRect(aRect, aResolutionX, aResolutionY));
}
static gfx::IntRectTyped<LayerPixel> FromCSSRectRoundOut(const CSSRect& aRect, float aResolutionX, float aResolutionY) {
gfx::RectTyped<LayerPixel> scaled(aRect.x, aRect.y, aRect.width, aRect.height);
scaled.ScaleInverseRoundOut(aResolutionX, aResolutionY);
return gfx::IntRectTyped<LayerPixel>(scaled.x, scaled.y, scaled.width, scaled.height);
}
static CSSIntRect ToCSSIntRectRoundIn(const gfx::IntRectTyped<LayerPixel>& aRect, float aResolutionX, float aResolutionY) {
gfx::IntRectTyped<CSSPixel> ret(aRect.x, aRect.y, aRect.width, aRect.height);
ret.ScaleInverseRoundIn(aResolutionX, aResolutionY);

View File

@ -652,22 +652,12 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
contentBounds.width += scrollableFrame->GetScrollPortRect().width;
contentBounds.height += scrollableFrame->GetScrollPortRect().height;
metrics.mScrollableRect = CSSRect::FromAppUnits(contentBounds);
nsIntRect contentRect = contentBounds.ScaleToNearestPixels(
aContainerParameters.mXScale, aContainerParameters.mYScale, auPerDevPixel);
// I'm not sure what units contentRect is really in, hence FromUnknownRect
metrics.mContentRect = LayerIntRect::FromUnknownRect(mozilla::gfx::IntRect(
contentRect.x, contentRect.y, contentRect.width, contentRect.height));
nsPoint scrollPosition = scrollableFrame->GetScrollPosition();
metrics.mScrollOffset = CSSPoint::FromAppUnits(scrollPosition);
}
else {
nsRect contentBounds = aForFrame->GetRect();
metrics.mScrollableRect = CSSRect::FromAppUnits(contentBounds);
nsIntRect contentRect = contentBounds.ScaleToNearestPixels(
aContainerParameters.mXScale, aContainerParameters.mYScale, auPerDevPixel);
// I'm not sure what units contentRect is really in, hence FromUnknownRect
metrics.mContentRect = LayerIntRect::FromUnknownRect(mozilla::gfx::IntRect(
contentRect.x, contentRect.y, contentRect.width, contentRect.height));
}
metrics.mScrollId = aScrollId;

View File

@ -416,8 +416,8 @@ BuildViewMap(ViewMap& oldContentViews, ViewMap& newContentViews,
NSIntPixelsToAppUnits(viewport.width, auPerDevPixel) * aXScale,
NSIntPixelsToAppUnits(viewport.height, auPerDevPixel) * aYScale);
view->mContentSize = nsSize(
NSIntPixelsToAppUnits(metrics.mContentRect.width, auPerDevPixel) * aXScale,
NSIntPixelsToAppUnits(metrics.mContentRect.height, auPerDevPixel) * aYScale);
NSFloatPixelsToAppUnits(metrics.mScrollableRect.width, auPerCSSPixel) * aXScale,
NSFloatPixelsToAppUnits(metrics.mScrollableRect.height, auPerCSSPixel) * aYScale);
newContentViews[scrollId] = view;
}

View File

@ -493,10 +493,7 @@ nsSliderFrame::HandleEvent(nsPresContext* aPresContext,
case NS_TOUCH_END:
case NS_MOUSE_BUTTON_UP:
if (aEvent->message == NS_TOUCH_END ||
static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton ||
(static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eMiddleButton &&
gMiddlePref)) {
if (ShouldScrollForEvent(aEvent)) {
// stop capturing
AddListener();
DragThumb(false);
@ -511,19 +508,7 @@ nsSliderFrame::HandleEvent(nsPresContext* aPresContext,
//return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
return NS_OK;
} else if ((aEvent->message == NS_MOUSE_BUTTON_DOWN &&
static_cast<nsMouseEvent*>(aEvent)->button ==
nsMouseEvent::eLeftButton &&
#ifdef XP_MACOSX
// On Mac the option key inverts the scroll-to-here preference.
(static_cast<nsMouseEvent*>(aEvent)->IsAlt() != GetScrollToClick())) ||
#else
(static_cast<nsMouseEvent*>(aEvent)->IsShift() != GetScrollToClick())) ||
#endif
(gMiddlePref && aEvent->message == NS_MOUSE_BUTTON_DOWN &&
static_cast<nsMouseEvent*>(aEvent)->button ==
nsMouseEvent::eMiddleButton) ||
(aEvent->message == NS_TOUCH_START && GetScrollToClick())) {
} else if (ShouldScrollToClickForEvent(aEvent)) {
nsPoint eventPoint;
if (!GetEventPoint(aEvent, eventPoint)) {
return NS_OK;
@ -573,26 +558,22 @@ nsSliderFrame::HandleEvent(nsPresContext* aPresContext,
bool
nsSliderFrame::GetScrollToClick()
{
// if there is no parent scrollbar, check the movetoclick attribute. If set
// to true, always scroll to the click point. If false, never do this.
// Otherwise, the default is true on Mac and false on other platforms.
if (GetScrollbar() == this)
#ifdef XP_MACOSX
return !mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::movetoclick,
nsGkAtoms::_false, eCaseMatters);
// if there was no scrollbar, always scroll on click
bool scrollToClick = false;
int32_t scrollToClickMetric;
nsresult rv = LookAndFeel::GetInt(LookAndFeel::eIntID_ScrollToClick,
&scrollToClickMetric);
if (NS_SUCCEEDED(rv) && scrollToClickMetric == 1)
scrollToClick = true;
return scrollToClick;
if (GetScrollbar() != this) {
return LookAndFeel::GetInt(LookAndFeel::eIntID_ScrollToClick, false);
}
if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::movetoclick,
nsGkAtoms::_true, eCaseMatters)) {
return true;
}
if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::movetoclick,
nsGkAtoms::_false, eCaseMatters)) {
return false;
}
#ifdef XP_MACOSX
return true;
#else
return mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::movetoclick,
nsGkAtoms::_true, eCaseMatters);
return false;
#endif
}
@ -842,37 +823,24 @@ nsSliderFrame::StartDrag(nsIDOMEvent* aEvent)
nsGkAtoms::_true, eCaseMatters))
return NS_OK;
bool isHorizontal = IsHorizontal();
bool scrollToClick = false;
nsCOMPtr<nsIDOMMouseEvent> mouseEvent(do_QueryInterface(aEvent));
if (mouseEvent) {
uint16_t button = 0;
mouseEvent->GetButton(&button);
if (!(button == 0 || (button == 1 && gMiddlePref)))
return NS_OK;
#ifndef XP_MACOSX
// On Mac there's no scroll-to-here when clicking the thumb
mouseEvent->GetShiftKey(&scrollToClick);
if (button != 0) {
scrollToClick = true;
}
#endif
}
nsGUIEvent *event = static_cast<nsGUIEvent*>(aEvent->GetInternalNSEvent());
if (!ShouldScrollForEvent(event)) {
return NS_OK;
}
nsPoint pt;
if (!GetEventPoint(event, pt)) {
return NS_OK;
}
bool isHorizontal = IsHorizontal();
nscoord pos = isHorizontal ? pt.x : pt.y;
// If shift click or middle button, first
// place the middle of the slider thumb under the click
// If we should scroll-to-click, first place the middle of the slider thumb
// under the mouse.
nsCOMPtr<nsIContent> scrollbar;
nscoord newpos = pos;
bool scrollToClick = ShouldScrollToClickForEvent(event);
if (scrollToClick) {
// adjust so that the middle of the thumb is placed under the click
nsIFrame* thumbFrame = mFrames.FirstChild();
@ -969,24 +937,92 @@ nsSliderFrame::RemoveListener()
RemoveSystemEventListener(NS_LITERAL_STRING("mousedown"), mMediator, false);
}
bool
nsSliderFrame::ShouldScrollForEvent(nsGUIEvent* aEvent)
{
switch (aEvent->message) {
case NS_TOUCH_START:
case NS_TOUCH_END:
return true;
case NS_MOUSE_BUTTON_DOWN:
case NS_MOUSE_BUTTON_UP: {
uint16_t button = static_cast<nsMouseEvent*>(aEvent)->button;
return (button == nsMouseEvent::eLeftButton) ||
(button == nsMouseEvent::eMiddleButton && gMiddlePref);
}
default:
return false;
}
}
bool
nsSliderFrame::ShouldScrollToClickForEvent(nsGUIEvent* aEvent)
{
if (!ShouldScrollForEvent(aEvent)) {
return false;
}
if (aEvent->message == NS_TOUCH_START) {
return GetScrollToClick();
}
if (aEvent->message != NS_MOUSE_BUTTON_DOWN) {
return false;
}
#ifdef XP_MACOSX
// On Mac, clicking the scrollbar thumb should never scroll to click.
if (IsEventOverThumb(aEvent)) {
return false;
}
#endif
nsMouseEvent* mouseEvent = static_cast<nsMouseEvent*>(aEvent);
if (mouseEvent->button == nsMouseEvent::eLeftButton) {
#ifdef XP_MACOSX
bool invertPref = mouseEvent->IsAlt();
#else
bool invertPref = mouseEvent->IsShift();
#endif
return GetScrollToClick() != invertPref;
}
return true;
}
bool
nsSliderFrame::IsEventOverThumb(nsGUIEvent* aEvent)
{
nsIFrame* thumbFrame = mFrames.FirstChild();
if (!thumbFrame) {
return false;
}
nsPoint eventPoint;
if (!GetEventPoint(aEvent, eventPoint)) {
return false;
}
bool isHorizontal = IsHorizontal();
nsRect thumbRect = thumbFrame->GetRect();
nscoord eventPos = isHorizontal ? eventPoint.x : eventPoint.y;
nscoord thumbStart = isHorizontal ? thumbRect.x : thumbRect.y;
nscoord thumbEnd = isHorizontal ? thumbRect.XMost() : thumbRect.YMost();
return eventPos >= thumbStart && eventPos < thumbEnd;
}
NS_IMETHODIMP
nsSliderFrame::HandlePress(nsPresContext* aPresContext,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus)
{
if (aEvent->message == NS_TOUCH_START && GetScrollToClick()) {
if (!ShouldScrollForEvent(aEvent) || ShouldScrollToClickForEvent(aEvent)) {
return NS_OK;
}
if (aEvent->message == NS_MOUSE_BUTTON_DOWN) {
#ifdef XP_MACOSX
// On Mac the option key inverts the scroll-to-here preference.
if (((nsMouseEvent *)aEvent)->IsAlt() != GetScrollToClick()) {
#else
if (((nsMouseEvent *)aEvent)->IsShift() != GetScrollToClick()) {
#endif
return NS_OK;
}
if (IsEventOverThumb(aEvent)) {
return NS_OK;
}
nsIFrame* thumbFrame = mFrames.FirstChild();

View File

@ -127,6 +127,9 @@ private:
bool GetScrollToClick();
nsIFrame* GetScrollbar();
bool ShouldScrollForEvent(nsGUIEvent* aEvent);
bool ShouldScrollToClickForEvent(nsGUIEvent* aEvent);
bool IsEventOverThumb(nsGUIEvent* aEvent);
void PageUpDown(nscoord change);
void SetCurrentThumbPosition(nsIContent* aScrollbar, nscoord aNewPos, bool aIsSmooth,

View File

@ -553,18 +553,17 @@ public class GeckoLayerClient implements LayerView.Listener, PanZoomTarget
* this function is invoked on; and this function will always be called prior to syncViewportInfo.
*/
public void setFirstPaintViewport(float offsetX, float offsetY, float zoom,
float pageLeft, float pageTop, float pageRight, float pageBottom,
float cssPageLeft, float cssPageTop, float cssPageRight, float cssPageBottom) {
synchronized (getLock()) {
ImmutableViewportMetrics currentMetrics = getViewportMetrics();
Tab tab = Tabs.getInstance().getSelectedTab();
RectF cssPageRect = new RectF(cssPageLeft, cssPageTop, cssPageRight, cssPageBottom);
final ImmutableViewportMetrics newMetrics = currentMetrics
.setViewportOrigin(offsetX, offsetY)
.setZoomFactor(zoom)
.setPageRect(new RectF(pageLeft, pageTop, pageRight, pageBottom),
new RectF(cssPageLeft, cssPageTop, cssPageRight, cssPageBottom))
.setPageRect(RectUtils.scale(cssPageRect, zoom), cssPageRect)
.setIsRTL(tab.getIsRTL());
// Since we have switched to displaying a different document, we need to update any
// viewport-related state we have lying around. This includes mGeckoViewport and
@ -690,9 +689,8 @@ public class GeckoLayerClient implements LayerView.Listener, PanZoomTarget
boolean isFirstPaint)
{
if (isFirstPaint) {
RectF pageRect = RectUtils.scale(new RectF(cssPageLeft, cssPageTop, cssPageRight, cssPageBottom), zoom);
setFirstPaintViewport(offsetX, offsetY, zoom, pageRect.left, pageRect.top, pageRect.right,
pageRect.bottom, cssPageLeft, cssPageTop, cssPageRight, cssPageBottom);
setFirstPaintViewport(offsetX, offsetY, zoom,
cssPageLeft, cssPageTop, cssPageRight, cssPageBottom);
}
return syncViewportInfo(x, y, width, height, resolution, layersUpdated);

View File

@ -30,12 +30,12 @@ public class testMasterPassword extends PixelTest {
// Look for the 'Settings' menu if this device/OS uses it
selectMenuItem("Settings");
if (dev.type.equals("tablet")) {
mSolo.waitForText("Privacy & Security");
waitForText("Privacy & Security");
mSolo.clickOnText("Privacy & Security");
}
mSolo.waitForText("^Use master password$");
waitForText("^Use master password$");
mSolo.clickOnText("^Use master password$");
mSolo.waitForText("^Create Master Password$");
waitForText("^Create Master Password$");
// Verify that the OK button is not activated until both fields are filled
closeTabletKeyboard();
@ -59,9 +59,9 @@ public class testMasterPassword extends PixelTest {
mSolo.clearEditText(1);
mSolo.clickOnEditText(1);
mActions.sendKeys(password);
mSolo.waitForText("^Cancel$");
waitForText("^Cancel$");
mSolo.clickOnText("^Cancel$");
mSolo.waitForText("^Use master password$");
waitForText("^Use master password$");
mSolo.clickOnText("^Use master password$");
mAsserter.ok(mSolo.waitForText("^Create Master Password$"), "Checking if no password was set if the action was canceled", "No password was set");
@ -72,16 +72,15 @@ public class testMasterPassword extends PixelTest {
mActions.sendKeys(password);
// Verify that the input characters are converted to dots automatically
mAsserter.ok(mSolo.waitForText("."), "waiting to convert the letters in dots", "The letters are converted in dots");
mAsserter.ok(waitForText("."), "waiting to convert the letters in dots", "The letters are converted in dots");
mSolo.clickOnButton("OK");
// Verify that the Master Password was set
mSolo.waitForText("^Use master password$");
waitForText("^Use master password$");
mSolo.clickOnText("^Use master password$");
mAsserter.ok(mSolo.searchText("Remove Master Password"), "Checking if the password is enabled", "The password is enabled");
closeTabletKeyboard();
mActions.sendSpecialKey(Actions.SpecialKey.BACK); // Go back to settings menu
mSolo.waitForText("^Settings$");
clickOnButton("Cancel"); // Go back to settings menu
waitForText("^Settings$");
mActions.sendSpecialKey(Actions.SpecialKey.BACK);// Close the Settings Menu
}
@ -90,12 +89,12 @@ public class testMasterPassword extends PixelTest {
// Look for the 'Settings' menu if this device/OS uses it
selectMenuItem("Settings");
if (dev.type.equals("tablet")) {
mSolo.waitForText("Privacy & Security");
waitForText("Privacy & Security");
mSolo.clickOnText("Privacy & Security");
}
mSolo.waitForText("^Use master password$");
waitForText("^Use master password$");
mSolo.clickOnText("^Use master password$");
mSolo.waitForText("^Remove Master Password$");
waitForText("^Remove Master Password$");
// Verify that the OK button is not activated if the password field is empty
closeTabletKeyboard();
@ -115,11 +114,10 @@ public class testMasterPassword extends PixelTest {
mSolo.clickOnButton("OK");
// Verify that the Master Password was disabled
mSolo.waitForText("^Use master password$");
waitForText("^Use master password$");
mSolo.clickOnText("^Use master password$");
mAsserter.ok(mSolo.waitForText("^Create Master Password$"), "Checking if the password is disabled", "The password is disabled");
toggleVKB(); // Close the VKB
mActions.sendSpecialKey(Actions.SpecialKey.BACK); // Close the Master Password menu
mAsserter.ok(waitForText("^Create Master Password$"), "Checking if the password is disabled", "The password is disabled");
clickOnButton("Cancel"); // Go back to settings menu
}
public void editPasswordField(int i, String password) {
@ -131,7 +129,7 @@ public class testMasterPassword extends PixelTest {
public void noDoorhangerDisplayed(String LOGIN_URL) {
mSolo.waitForText("Browser Blank Page 01 | Enter Search or Address");
loadUrl(LOGIN_URL);
mAsserter.is(mSolo.waitForText("Save password for"), false, "Doorhanger notification is hidden");
mAsserter.is(waitForText("Save password for"), false, "Doorhanger notification is hidden");
}
public void doorhangerDisplayed(String LOGIN_URL) {
@ -153,25 +151,37 @@ public class testMasterPassword extends PixelTest {
// Look for the 'Settings' menu if this device/OS uses it
selectMenuItem("Settings");
if (dev.type.equals("tablet")) {
mSolo.waitForText("Privacy & Security");
waitForText("Privacy & Security");
mSolo.clickOnText("Privacy & Security");
}
// Clear private data
mSolo.waitForText("^Clear private data$");
waitForText("^Clear private data$");
mSolo.clickOnText("^Clear private data$");
mSolo.waitForText("^Clear data$");
mSolo.clickOnText("^Clear data$");
mAsserter.ok(mSolo.waitForText("^Private data cleared$"), "Waiting for private data to be cleared", "Private data is cleared");
waitForText("Browsing & download history"); // Make sure the Clear private data pop-up is displayed
Actions.EventExpecter clearPrivateDataEventExpecter = mActions.expectGeckoEvent("Sanitize:Finished");
if (mSolo.searchText("Clear data") && !mSolo.searchText("Cookies")) {
mSolo.clickOnText("^Clear data$");
clearPrivateDataEventExpecter.blockForEvent();
} else { // For some reason the pop-up was not opened
if (mSolo.searchText("Cookies")) {
mSolo.clickOnText("^Clear private data$");
waitForText("Browsing & download history"); // Make sure the Clear private data pop-up is displayed
mSolo.clickOnText("^Clear data$");
clearPrivateDataEventExpecter.blockForEvent();
} else {
mAsserter.ok(false, "Something happened and the clear data dialog could not be opened", "Failed to clear data");
}
}
// Check that the Master Password isn't disabled by clearing private data
mSolo.waitForText("^Use master password$");
waitForText("^Use master password$");
mSolo.clickOnText("^Use master password$");
mAsserter.ok(mSolo.searchText("^Remove Master Password$"), "Checking if the master password was disabled by clearing private data", "The master password is not disabled by clearing private data");
closeTabletKeyboard();
mActions.sendSpecialKey(Actions.SpecialKey.BACK);// Close the Master Password menu
mSolo.waitForText("^Settings$");
clickOnButton("Cancel"); // Close the Master Password menu
waitForText("^Settings$");
mActions.sendSpecialKey(Actions.SpecialKey.BACK);// Close the Settings Menu
waitForText("Browser Blank Page 01"); // Make sure the Settings Menu has been closed
}
public void verifyLoginPage(String password, String badPassword) {
@ -206,7 +216,7 @@ public class testMasterPassword extends PixelTest {
mSolo.clickOnButton(item);
doorhangerDisplayed(LOGIN_URL);// Check that the doorhanger is displayed again
mSolo.clickOnButton(item);
mSolo.waitForText("Browser Blank Page 01");
waitForText("Browser Blank Page 01");
}
}
}

View File

@ -430,8 +430,6 @@ nsOutputStreamTransport::IsNonBlocking(bool *result)
// nsStreamTransportService
//-----------------------------------------------------------------------------
bool nsStreamTransportService::sHasBeenShutdown = false;
nsStreamTransportService::~nsStreamTransportService()
{
NS_ASSERTION(!mPool, "thread pool wasn't shutdown");
@ -440,11 +438,6 @@ nsStreamTransportService::~nsStreamTransportService()
nsresult
nsStreamTransportService::Init()
{
if (sHasBeenShutdown) {
// Prevent any attempt at resurrection
// (see bug 845190)
return NS_ERROR_NOT_AVAILABLE;
}
mPool = do_CreateInstance(NS_THREADPOOL_CONTRACTID);
NS_ENSURE_STATE(mPool);
@ -515,7 +508,7 @@ nsStreamTransportService::Observe(nsISupports *subject, const char *topic,
const PRUnichar *data)
{
NS_ASSERTION(strcmp(topic, "xpcom-shutdown-threads") == 0, "oops");
sHasBeenShutdown = true;
if (mPool) {
mPool->Shutdown();
mPool = nullptr;

View File

@ -27,10 +27,4 @@ private:
~nsStreamTransportService();
nsCOMPtr<nsIThreadPool> mPool;
/**
* |true| if we have shutdown once already, in which
* case we should reject any attempt to resurrect.
*/
static bool sHasBeenShutdown;
};

View File

@ -111,11 +111,6 @@ let clone = function clone(object, refs = noRefs) {
return result;
};
/**
* A shared constant used to normalize a set of options to nothing.
*/
const noOptions = {};
let worker = new PromiseWorker(
"resource://gre/modules/osfile/osfile_async_worker.js", LOG);
let Scheduler = {
@ -313,7 +308,7 @@ File.prototype = {
* @resolves {number} The number of bytes effectively read.
* @rejects {OS.File.Error}
*/
readTo: function readTo(buffer, options = noOptions) {
readTo: function readTo(buffer, options = {}) {
// If |buffer| is a typed array and there is no |bytes| options, we
// need to extract the |byteLength| now, as it will be lost by
// communication
@ -351,7 +346,7 @@ File.prototype = {
*
* @return {number} The number of bytes actually written.
*/
write: function write(buffer, options = noOptions) {
write: function write(buffer, options = {}) {
// If |buffer| is a typed array and there is no |bytes| options,
// we need to extract the |byteLength| now, as it will be lost
// by communication
@ -652,7 +647,7 @@ File.exists = function exists(path) {
* @return {promise}
* @resolves {number} The number of bytes actually written.
*/
File.writeAtomic = function writeAtomic(path, buffer, options = noOptions) {
File.writeAtomic = function writeAtomic(path, buffer, options = {}) {
// Copy |options| to avoid modifying the original object but preserve the
// reference to |outExecutionDuration| option if it is passed.
options = clone(options, ["outExecutionDuration"]);

View File

@ -16,9 +16,6 @@ if (typeof Components != "undefined") {
let LOG = exports.OS.Shared.LOG.bind(OS.Shared, "Shared front-end");
const noOptions = {};
/**
* Code shared by implementations of File.
*
@ -80,7 +77,7 @@ AbstractFile.prototype = {
* @return {number} The number of bytes actually read, which may be
* less than |bytes| if the file did not contain that many bytes left.
*/
readTo: function readTo(buffer, options = noOptions) {
readTo: function readTo(buffer, options = {}) {
let {ptr, bytes} = AbstractFile.normalizeToPointer(buffer, options.bytes);
let pos = 0;
while (pos < bytes) {
@ -112,7 +109,7 @@ AbstractFile.prototype = {
*
* @return {number} The number of bytes actually written.
*/
write: function write(buffer, options = noOptions) {
write: function write(buffer, options = {}) {
let {ptr, bytes} = AbstractFile.normalizeToPointer(buffer, options.bytes);
@ -340,7 +337,7 @@ AbstractFile.read = function read(path, bytes) {
* @return {number} The number of bytes actually written.
*/
AbstractFile.writeAtomic =
function writeAtomic(path, buffer, options = noOptions) {
function writeAtomic(path, buffer, options = {}) {
// Verify that path is defined and of the correct type
if (typeof path != "string" || path == "") {

View File

@ -166,10 +166,6 @@
throw_on_negative("flush", UnixFile.fsync(this.fd));
};
// Constant used to normalize options.
const noOptions = {};
// The default unix mode for opening (0600)
const DEFAULT_UNIX_MODE = 384;
@ -216,7 +212,7 @@
* @return {File} A file object.
* @throws {OS.File.Error} If the file could not be opened.
*/
File.open = function Unix_open(path, mode, options = noOptions) {
File.open = function Unix_open(path, mode, options = {}) {
let omode = options.unixMode || DEFAULT_UNIX_MODE;
let flags;
if (options.unixFlags) {
@ -287,7 +283,7 @@
* - {bool} ignoreAbsent If |true|, do not fail if the
* directory does not exist yet.
*/
File.removeEmptyDir = function removeEmptyDir(path, options = noOptions) {
File.removeEmptyDir = function removeEmptyDir(path, options = {}) {
let result = UnixFile.rmdir(path);
if (result == -1) {
if (options.ignoreAbsent && ctypes.errno == Const.ENOENT) {
@ -316,7 +312,7 @@
* - {bool} ignoreExisting If |true|, do not fail if the
* directory already exists.
*/
File.makeDir = function makeDir(path, options = noOptions) {
File.makeDir = function makeDir(path, options = {}) {
let omode = options.unixMode || DEFAULT_UNIX_MODE_DIR;
let result = UnixFile.mkdir(path, omode);
if (result != -1 ||
@ -383,7 +379,7 @@
// This implementation uses |copyfile(3)|, from the BSD library.
// Adding copying of hierarchies and/or attributes is just a flag
// away.
File.copy = function copyfile(sourcePath, destPath, options = noOptions) {
File.copy = function copyfile(sourcePath, destPath, options = {}) {
let flags = Const.COPYFILE_DATA;
if (options.noOverwrite) {
flags |= Const.COPYFILE_EXCL;
@ -421,7 +417,7 @@
let pump_buffer = null;
// An implementation of |pump| using |read|/|write|
let pump_userland = function pump_userland(source, dest, options = noOptions) {
let pump_userland = function pump_userland(source, dest, options = {}) {
let bufSize = options.bufSize || 4096;
let nbytes = options.nbytes || Infinity;
if (!pump_buffer || pump_buffer.length < bufSize) {
@ -457,7 +453,7 @@
const BUFSIZE = 1 << 17;
// An implementation of |pump| using |splice| (for Linux/Android)
pump = function pump_splice(source, dest, options = noOptions) {
pump = function pump_splice(source, dest, options = {}) {
let nbytes = options.nbytes || Infinity;
let pipe = [];
throw_on_negative("pump", UnixFile.pipe(pipe));
@ -521,7 +517,7 @@
// Implement |copy| using |pump|.
// This implementation would require some work before being able to
// copy directories
File.copy = function copy(sourcePath, destPath, options = noOptions) {
File.copy = function copy(sourcePath, destPath, options = {}) {
let source, dest;
let result;
try {
@ -546,7 +542,7 @@
// Implement |move| using |rename| (wherever possible) or |copy|
// (if files are on distinct devices).
File.move = function move(sourcePath, destPath, options = noOptions) {
File.move = function move(sourcePath, destPath, options = {}) {
// An implementation using |rename| whenever possible or
// |File.pump| when required, for other Unices.
// It can move directories on one file system, not
@ -795,7 +791,7 @@
*
* @return {File.Information}
*/
File.stat = function stat(path, options = noOptions) {
File.stat = function stat(path, options = {}) {
if (options.unixNoFollowingLinks) {
throw_on_negative("stat", UnixFile.lstat(path, gStatDataPtr));
} else {

View File

@ -188,9 +188,6 @@
throw_on_zero("flush", WinFile.FlushFileBuffers(this.fd));
};
// Constant used to normalize options.
const noOptions = {};
// The default sharing mode for opening files: files are not
// locked against being reopened for reading/writing or against
// being deleted by the same process or another process.
@ -255,7 +252,7 @@
* @return {File} A file object.
* @throws {OS.File.Error} If the file could not be opened.
*/
File.open = function Win_open(path, mode = noOptions, options = noOptions) {
File.open = function Win_open(path, mode = {}, options = {}) {
let share = options.winShare || DEFAULT_SHARE;
let security = options.winSecurity || null;
let flags = options.winFlags || DEFAULT_FLAGS;
@ -347,7 +344,7 @@
* - {bool} ignoreAbsent If |true|, do not fail if the
* directory does not exist yet.
*/
File.removeEmptyDir = function removeEmptyDir(path, options = noOptions) {
File.removeEmptyDir = function removeEmptyDir(path, options = {}) {
let result = WinFile.RemoveDirectory(path);
if (!result) {
if (options.ignoreAbsent &&
@ -372,7 +369,7 @@
* - {bool} ignoreExisting If |true|, do not fail if the
* directory already exists.
*/
File.makeDir = function makeDir(path, options = noOptions) {
File.makeDir = function makeDir(path, options = {}) {
let security = options.winSecurity || null;
let result = WinFile.CreateDirectory(path, security);
if (result ||
@ -406,7 +403,7 @@
* is unspecified. Metadata may or may not be copied with the file. The
* behavior may not be the same across all platforms.
*/
File.copy = function copy(sourcePath, destPath, options = noOptions) {
File.copy = function copy(sourcePath, destPath, options = {}) {
throw_on_zero("copy",
WinFile.CopyFile(sourcePath, destPath, options.noOverwrite || false)
);
@ -438,7 +435,7 @@
* is unspecified. Metadata may or may not be moved with the file. The
* behavior may not be the same across all platforms.
*/
File.move = function move(sourcePath, destPath, options = noOptions) {
File.move = function move(sourcePath, destPath, options = {}) {
let flags = 0;
if (!options.noCopy) {
flags = Const.MOVEFILE_COPY_ALLOWED;

View File

@ -7,3 +7,5 @@ tail =
[test_osfile_async.js]
[test_profiledir.js]
[test_logging.js]
# bug 845190 - thread pool wasn't shutdown assertions
skip-if = os == "win" && debug

View File

@ -5,6 +5,8 @@ firefox-appdir = browser
[test_nocache.js]
[test_645970.js]
# Bug 845190: Too many intermittent assertions on Linux (ASSERTION: thread pool wasn't shutdown)
skip-if = debug && os == "linux"
[test_identifiers.js]
[test_init_async_multiple.js]
[test_init_async_multiple_then_sync.js]

View File

@ -2114,13 +2114,13 @@ AndroidBridge::IsTablet()
}
void
AndroidBridge::SetFirstPaintViewport(const LayerIntPoint& aOffset, float aZoom, const LayerIntRect& aPageRect, const CSSRect& aCssPageRect)
AndroidBridge::SetFirstPaintViewport(const LayerIntPoint& aOffset, float aZoom, const CSSRect& aCssPageRect)
{
AndroidGeckoLayerClient *client = mLayerClient;
if (!client)
return;
client->SetFirstPaintViewport(aOffset, aZoom, aPageRect, aCssPageRect);
client->SetFirstPaintViewport(aOffset, aZoom, aCssPageRect);
}
void

View File

@ -371,7 +371,7 @@ public:
void EnableNetworkNotifications();
void DisableNetworkNotifications();
void SetFirstPaintViewport(const LayerIntPoint& aOffset, float aZoom, const LayerIntRect& aPageRect, const CSSRect& aCssPageRect);
void SetFirstPaintViewport(const LayerIntPoint& aOffset, float aZoom, const CSSRect& aCssPageRect);
void SetPageRect(const CSSRect& aCssPageRect);
void SyncViewportInfo(const LayerIntRect& aDisplayPort, float aDisplayResolution, bool aLayersUpdated,
ScreenPoint& aScrollOffset, float& aScaleX, float& aScaleY,

View File

@ -351,7 +351,7 @@ AndroidGeckoLayerClient::InitGeckoLayerClientClass(JNIEnv *jEnv)
jGeckoLayerClientClass = getClassGlobalRef("org/mozilla/gecko/gfx/GeckoLayerClient");
jSetFirstPaintViewport = getMethod("setFirstPaintViewport", "(FFFFFFFFFFF)V");
jSetFirstPaintViewport = getMethod("setFirstPaintViewport", "(FFFFFFF)V");
jSetPageRect = getMethod("setPageRect", "(FFFF)V");
jSyncViewportInfoMethod = getMethod("syncViewportInfo",
"(IIIIFZ)Lorg/mozilla/gecko/gfx/ViewTransform;");
@ -863,7 +863,7 @@ AndroidProgressiveUpdateData::Init(jobject jobj)
}
void
AndroidGeckoLayerClient::SetFirstPaintViewport(const LayerIntPoint& aOffset, float aZoom, const LayerIntRect& aPageRect, const CSSRect& aCssPageRect)
AndroidGeckoLayerClient::SetFirstPaintViewport(const LayerIntPoint& aOffset, float aZoom, const CSSRect& aCssPageRect)
{
NS_ASSERTION(!isNull(), "SetFirstPaintViewport called on null layer client!");
JNIEnv *env = GetJNIForThread(); // this is called on the compositor thread
@ -872,7 +872,6 @@ AndroidGeckoLayerClient::SetFirstPaintViewport(const LayerIntPoint& aOffset, flo
AutoLocalJNIFrame jniFrame(env, 0);
return env->CallVoidMethod(wrapped_obj, jSetFirstPaintViewport, (float)aOffset.x, (float)aOffset.y, aZoom,
(float)aPageRect.x, (float)aPageRect.y, (float)aPageRect.XMost(), (float)aPageRect.YMost(),
aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost());
}

View File

@ -269,7 +269,7 @@ public:
AndroidGeckoLayerClient() {}
AndroidGeckoLayerClient(jobject jobj) { Init(jobj); }
void SetFirstPaintViewport(const LayerIntPoint& aOffset, float aZoom, const LayerIntRect& aPageRect, const CSSRect& aCssPageRect);
void SetFirstPaintViewport(const LayerIntPoint& aOffset, float aZoom, const CSSRect& aCssPageRect);
void SetPageRect(const CSSRect& aCssPageRect);
void SyncViewportInfo(const LayerIntRect& aDisplayPort, float aDisplayResolution, bool aLayersUpdated,
ScreenPoint& aScrollOffset, float& aScaleX, float& aScaleY,

View File

@ -46,14 +46,12 @@
#include "nsIDOMWheelEvent.h"
#include "mozilla/Preferences.h"
#include <os2im.h>
#include <algorithm> // std::max
using namespace mozilla;
using namespace mozilla::widget;
//=============================================================================
// Macros
//=============================================================================
// Drag and Drop
// d&d flags - actions that might cause problems during d&d
@ -124,17 +122,16 @@ using namespace mozilla::widget;
// make these methods seem more appropriate in context
#define PM2NS_PARENT NS2PM_PARENT
#define PM2NS NS2PM
// used to identify plugin widgets (copied from nsPluginNativeWindowOS2.cpp)
#define NS_PLUGIN_WINDOW_PROPERTY_ASSOCIATION \
"MozillaPluginWindowPropertyAssociation"
// name of the window class used to clip plugins
#define kClipWndClass "nsClipWnd"
// IME caret not exist
#define NO_IME_CARET (static_cast<ULONG>(-1))
//-----------------------------------------------------------------------------
// Debug
#ifdef DEBUG_FOCUS
#define DEBUGFOCUS(what) fprintf(stderr, "[%8x] %8lx (%02d) "#what"\n", \
(int)this, mWnd, mWindowIdentifier)
@ -2460,50 +2457,35 @@ bool nsWindow::OnQueryConvertPos(MPARAM mp1, MRESULT& mresult)
pCursorPos->xRight = pCursorPos->xLeft + caret.mReply.mRect.width;
pCursorPos->yTop = pCursorPos->yBottom + caret.mReply.mRect.height;
NS2PM(*pCursorPos);
mresult = (MRESULT)QCP_CONVERT;
return true;
}
bool nsWindow::ImeResultString(HIMI himi)
{
PCHAR pBuf;
ULONG ulBufLen;
// Get a buffer size
ulBufLen = 0;
if (spfnImGetResultString(himi, IMR_RESULT_RESULTSTRING, NULL, &ulBufLen))
return false;
nsAutoTArray<CHAR, 64> compositionStringA;
compositionStringA.SetCapacity(ulBufLen / sizeof(CHAR));
pBuf = new CHAR[ulBufLen];
if (!pBuf)
return false;
if (spfnImGetResultString(himi, IMR_RESULT_RESULTSTRING, pBuf,
&ulBufLen)) {
delete pBuf;
if (spfnImGetResultString(himi, IMR_RESULT_RESULTSTRING,
compositionStringA.Elements(), &ulBufLen)) {
return false;
}
if (!mIsComposing) {
mLastDispatchedCompositionString.Truncate();
nsCompositionEvent start(true, NS_COMPOSITION_START, this);
InitEvent(start);
DispatchWindowEvent(&start);
mIsComposing = true;
}
nsAutoChar16Buffer outBuf;
int32_t outBufLen;
MultiByteToWideChar(0, pBuf, ulBufLen, outBuf, outBufLen);
delete pBuf;
MultiByteToWideChar(0, compositionStringA.Elements(), ulBufLen,
outBuf, outBufLen);
nsAutoString compositionString(outBuf.Elements());
if (mLastDispatchedCompositionString != compositionString) {
nsCompositionEvent update(true, NS_COMPOSITION_UPDATE, this);
InitEvent(update);
@ -2523,50 +2505,59 @@ bool nsWindow::ImeResultString(HIMI himi)
DispatchWindowEvent(&end);
mIsComposing = false;
mLastDispatchedCompositionString.Truncate();
return true;
}
static uint32_t
PlatformToNSAttr(uint8_t aAttr)
{
switch (aAttr)
{
case CP_ATTR_INPUT_ERROR:
case CP_ATTR_INPUT:
return NS_TEXTRANGE_RAWINPUT;
case CP_ATTR_CONVERTED:
return NS_TEXTRANGE_CONVERTEDTEXT;
case CP_ATTR_TARGET_NOTCONVERTED:
return NS_TEXTRANGE_SELECTEDRAWTEXT;
case CP_ATTR_TARGET_CONVERTED:
return NS_TEXTRANGE_SELECTEDCONVERTEDTEXT;
default:
MOZ_NOT_REACHED("unknown attribute");
return NS_TEXTRANGE_RAWINPUT;
}
}
bool nsWindow::ImeConversionString(HIMI himi)
{
PCHAR pBuf;
ULONG ulBufLen;
// Get a buffer size
ulBufLen = 0;
if (spfnImGetConversionString(himi, IMR_CONV_CONVERSIONSTRING, NULL,
&ulBufLen))
return false;
nsAutoTArray<CHAR, 64> compositionStringA;
compositionStringA.SetCapacity(ulBufLen / sizeof(CHAR));
pBuf = new CHAR[ulBufLen];
if (!pBuf)
return false;
if (spfnImGetConversionString(himi, IMR_CONV_CONVERSIONSTRING, pBuf,
&ulBufLen)) {
delete pBuf;
if (spfnImGetConversionString(himi, IMR_CONV_CONVERSIONSTRING,
compositionStringA.Elements(), &ulBufLen)) {
return false;
}
if (!mIsComposing) {
mLastDispatchedCompositionString.Truncate();
nsCompositionEvent start(true, NS_COMPOSITION_START, this);
InitEvent(start);
DispatchWindowEvent(&start);
mIsComposing = true;
}
nsAutoChar16Buffer outBuf;
int32_t outBufLen;
MultiByteToWideChar(0, pBuf, ulBufLen, outBuf, outBufLen);
delete pBuf;
MultiByteToWideChar(0, compositionStringA.Elements(), ulBufLen,
outBuf, outBufLen);
nsAutoString compositionString(outBuf.Elements());
// Is a conversion string changed ?
if (mLastDispatchedCompositionString != compositionString) {
nsCompositionEvent update(true, NS_COMPOSITION_UPDATE, this);
@ -2575,22 +2566,103 @@ bool nsWindow::ImeConversionString(HIMI himi)
mLastDispatchedCompositionString = compositionString;
DispatchWindowEvent(&update);
}
nsAutoTArray<nsTextRange, 4> textRanges;
if (!compositionString.IsEmpty()) {
bool oneClause = false;
ulBufLen = 0;
if (spfnImGetConversionString(himi, IMR_CONV_CONVERSIONCLAUSE, 0,
&ulBufLen)) {
oneClause = true; // Assume that there is only one clause
}
ULONG ulClauseCount = std::max(2UL, ulBufLen / sizeof(ULONG));
nsAutoTArray<ULONG, 4> clauseOffsets;
nsAutoTArray<UCHAR, 4> clauseAttr;
ULONG ulCursorPos;
clauseOffsets.SetCapacity(ulClauseCount);
clauseAttr.SetCapacity(ulClauseCount);
if (spfnImGetConversionString(himi, IMR_CONV_CONVERSIONCLAUSE,
clauseOffsets.Elements(), &ulBufLen)) {
oneClause = true; // Assume that there is only one clause
}
// Korean IME does not provide clause and cursor infomation
// Or if getting a clause inforamtion was failed
if (ulBufLen == 0 && !oneClause) {
ulCursorPos = compositionString.Length();
oneClause = true;
} else {
while (!oneClause) {
ulBufLen = 0;
if (spfnImGetConversionString(himi, IMR_CONV_CONVERSIONATTR, 0,
&ulBufLen)) {
oneClause = true;
break;
}
nsAutoTArray<UCHAR, 64> attr;
attr.SetCapacity(ulBufLen / sizeof(UCHAR));
if (spfnImGetConversionString(himi, IMR_CONV_CONVERSIONATTR,
attr.Elements(), &ulBufLen)) {
oneClause = true;
break;
}
// Assume that all the conversion attribute in a clause are same
for (ULONG i = 0; i < ulClauseCount - 1; ++i) {
clauseAttr[i] = attr[clauseOffsets[i]];
}
// Convert ANSI string offsets to Unicode string offsets
clauseOffsets[0] = 0;
for (ULONG i = 1; i < ulClauseCount - 1; ++i) {
MultiByteToWideChar(0,
compositionStringA.Elements(), clauseOffsets[i],
outBuf, outBufLen);
clauseOffsets[i] = outBufLen;
}
break;
}
ulBufLen = sizeof(ULONG);
if (spfnImGetConversionString(himi, IMR_CONV_CURSORPOS, &ulCursorPos,
&ulBufLen)) {
ulCursorPos = NO_IME_CARET;
} else {
// Convert ANSI string position to Unicode string position
MultiByteToWideChar(0, compositionStringA.Elements(), ulCursorPos,
outBuf, outBufLen);
ulCursorPos = outBufLen;
}
}
if (oneClause) {
ulClauseCount = 2;
clauseOffsets[0] = 0;
clauseOffsets[1] = compositionString.Length();
clauseAttr[0] = NS_TEXTRANGE_SELECTEDRAWTEXT;
}
nsTextRange newRange;
newRange.mStartOffset = 0;
newRange.mEndOffset = compositionString.Length();
newRange.mRangeType = NS_TEXTRANGE_SELECTEDRAWTEXT;
textRanges.AppendElement(newRange);
newRange.mStartOffset = compositionString.Length();
newRange.mEndOffset = newRange.mStartOffset;
newRange.mRangeType = NS_TEXTRANGE_CARETPOSITION;
textRanges.AppendElement(newRange);
for (ULONG i = 0; i < ulClauseCount - 1; ++i) {
newRange.mStartOffset = clauseOffsets[i];
newRange.mEndOffset = clauseOffsets[i + 1];
newRange.mRangeType = PlatformToNSAttr(clauseAttr[i]);
textRanges.AppendElement(newRange);
}
if (ulCursorPos != NO_IME_CARET) {
newRange.mStartOffset = newRange.mEndOffset = ulCursorPos;
newRange.mRangeType = NS_TEXTRANGE_CARETPOSITION;
textRanges.AppendElement(newRange);
}
}
nsTextEvent text(true, NS_TEXT_TEXT, this);
InitEvent(text);
text.theText = compositionString;