mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge inbound to m-c.
This commit is contained in:
commit
a07587452c
@ -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.
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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) &&
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -258,6 +258,8 @@ enum ParallelBailoutCause {
|
||||
ParallelBailoutUnsupported,
|
||||
ParallelBailoutUnsupportedStringComparison,
|
||||
ParallelBailoutUnsupportedSparseArray,
|
||||
ParallelBailoutRequestedGC,
|
||||
ParallelBailoutRequestedZoneGC,
|
||||
};
|
||||
|
||||
struct ParallelBailoutTrace {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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"]);
|
||||
|
@ -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 == "") {
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user