Merge from mozilla-central

This commit is contained in:
Ehsan Akhgari 2012-04-23 19:24:10 -04:00
commit b6247f2495
50 changed files with 1124 additions and 290 deletions

View File

@ -1152,3 +1152,8 @@ pref("full-screen-api.enabled", true);
// number of startup crashes that can occur before starting into safe mode automatically
// (this pref has no effect if more than 6 hours have passed since the last crash)
pref("toolkit.startup.max_resumed_crashes", 2);
// The maximum amount of decoded image data we'll willingly keep around (we
// might keep around more than this, but we'll try to get down to this value).
// (This is intentionally on the high side; see bug 746055.)
pref("image.mem.max_decoded_image_kb", 256000);

View File

@ -54,6 +54,11 @@ function e(id) {
return document.getElementById(id);
}
function requestFullscreen(element) {
element.focus();
element.mozRequestFullScreen();
}
function begin() {
addListener("change", change1);
e("fse").mozRequestFullScreen();
@ -65,7 +70,7 @@ function change1() {
is(document.mozFullScreenElement, e("fse"), "Body should be FSE");
// Request full-screen from element not descendent from current FSE.
e("non-fse").mozRequestFullScreen();
requestFullscreen(e("non-fse"));
}
function error1() {
@ -73,7 +78,7 @@ function error1() {
addListener("change", change2);
is(document.mozFullScreenElement, e("fse"), "FSE should not change");
var iframe = e("subdoc");
iframe.contentDocument.body.mozRequestFullScreen();
requestFullscreen(iframe.contentDocument.body);
}
function change2() {
@ -96,14 +101,14 @@ function change4() {
removeListener("change", change4);
is(document.mozFullScreenElement, null, "Should have left full-screen entirely");
addListener("change", change5);
e("fse").mozRequestFullScreen();
requestFullscreen(e("fse"));
}
function change5() {
removeListener("change", change5);
addListener("change", change6);
is(document.mozFullScreenElement, e("fse"), "FSE should be e('fse')");
e("fse-inner").mozRequestFullScreen();
requestFullscreen(e("fse-inner"));
}
function change6() {

View File

@ -2317,26 +2317,3 @@ nsDOMWindowUtils::GetPlugins(JSContext* cx, jsval* aPlugins)
*aPlugins = OBJECT_TO_JSVAL(jsPlugins);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SetScrollPositionClampingScrollPortSize(float aWidth, float aHeight)
{
if (!IsUniversalXPConnectCapable()) {
return NS_ERROR_DOM_SECURITY_ERR;
}
if (!(aWidth >= 0.0 && aHeight >= 0.0)) {
return NS_ERROR_ILLEGAL_VALUE;
}
nsIPresShell* presShell = GetPresShell();
if (!presShell) {
return NS_ERROR_FAILURE;
}
presShell->SetScrollPositionClampingScrollPortSize(
nsPresContext::CSSPixelsToAppUnits(aWidth),
nsPresContext::CSSPixelsToAppUnits(aHeight));
return NS_OK;
}

View File

@ -70,7 +70,7 @@ interface nsIDOMFile;
interface nsIFile;
interface nsIDOMTouch;
[scriptable, uuid(66a68858-df38-40e1-a792-fda04ebcc084)]
[scriptable, uuid(c7f303a1-4f7b-4d38-a192-c3f0e25dadb1)]
interface nsIDOMWindowUtils : nsISupports {
/**
@ -1110,12 +1110,4 @@ interface nsIDOMWindowUtils : nsISupports {
*/
[implicit_jscontext]
readonly attribute jsval plugins;
/**
* Set the scrollport size for the purposes of clamping scroll positions for
* the root scroll frame of this document to be (aWidth,aHeight) in CSS pixels.
*
* The caller of this method must have UniversalXPConnect privileges.
*/
void setScrollPositionClampingScrollPortSize(in float aWidth, in float aHeight);
};

View File

@ -0,0 +1,336 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GFX_TILEDLAYERBUFFER_H
#define GFX_TILEDLAYERBUFFER_H
#define TILEDLAYERBUFFER_TILE_SIZE 256
// Debug defines
//#define FORCE_BASICTILEDTHEBESLAYER
//#define GFX_TILEDLAYER_DEBUG_OVERLAY
//#define GFX_TILEDLAYER_PREF_WARNINGS
#include "nsRect.h"
#include "nsRegion.h"
#include "nsTArray.h"
namespace mozilla {
namespace layers {
// An abstract implementation of a tile buffer. This code covers the logic of
// moving and reusing tiles and leaves the validation up to the implementor. To
// avoid the overhead of virtual dispatch, we employ the curiously recurring
// template pattern.
//
// This tile buffer stores a valid region, which defines the areas that have
// up-to-date content. The contents of tiles within this region will be reused
// from paint to paint. It also stores the region that was modified in the last
// paint operation; this is useful when one tiled layer buffer shadows another
// (as in an off-main-thread-compositing scenario), so that the shadow tiled
// layer buffer can correctly reflect the updates of the master layer buffer.
//
// The associated Tile may be of any type as long as the derived class can
// validate and return tiles of that type. Tiles will be frequently copied, so
// the tile type should be a reference or some other type with an efficient
// copy constructor.
//
// It is required that the derived class specify the base class as a friend. It
// must also implement the following public method:
//
// Tile GetPlaceholderTile() const;
//
// Returns a temporary placeholder tile used as a marker. This placeholder tile
// must never be returned by validateTile and must be == to every instance
// of a placeholder tile.
//
// Additionally, it must implement the following protected methods:
//
// Tile ValidateTile(Tile aTile, const nsIntPoint& aTileOrigin,
// const nsIntRegion& aDirtyRect);
//
// Validates the dirtyRect. The returned Tile will replace the tile.
//
// void ReleaseTile(Tile aTile);
//
// Destroys the given tile.
//
// void SwapTiles(Tile& aTileA, Tile& aTileB);
//
// Swaps two tiles.
template<typename Derived, typename Tile>
class TiledLayerBuffer
{
public:
TiledLayerBuffer()
: mRetainedWidth(0)
, mRetainedHeight(0)
{}
~TiledLayerBuffer() {}
// Given a tile origin aligned to a multiple of GetTileLength(),
// return the tile that describes that region.
// NOTE: To get the valid area of that tile you must intersect
// (aTileOrigin.x, aTileOrigin.y, GetTileLength(), GetTileLength())
// and GetValidRegion() to get the area of the tile that is valid.
Tile GetTile(const nsIntPoint& aTileOrigin) const;
// Given a tile x, y relative to the top left of the layer, this function
// will return the tile for
// (x*GetTileLength(), y*GetTileLength(), GetTileLength(), GetTileLength())
Tile GetTile(int x, int y) const;
uint16_t GetTileLength() const { return TILEDLAYERBUFFER_TILE_SIZE; }
const nsIntRegion& GetValidRegion() const { return mValidRegion; }
const nsIntRegion& GetLastPaintRegion() const { return mLastPaintRegion; }
void SetLastPaintRegion(const nsIntRegion& aLastPaintRegion) {
mLastPaintRegion = aLastPaintRegion;
}
// Rounds the given coordinate down to the nearest tile boundary.
int RoundDownToTileEdge(int aX) const { return aX - aX % GetTileLength(); }
protected:
// The implementor should call Update() to change
// the new valid region. This implementation will call
// validateTile on each tile that is dirty, which is left
// to the implementor.
void Update(const nsIntRegion& aNewValidRegion, const nsIntRegion& aPaintRegion);
nsIntRegion mValidRegion;
nsIntRegion mLastPaintRegion;
/**
* mRetainedTiles is a rectangular buffer of mRetainedWidth x mRetainedHeight
* stored as column major with the same origin as mValidRegion.GetBounds().
* Any tile that does not intersect mValidRegion is a PlaceholderTile.
* Only the region intersecting with mValidRegion should be read from a tile,
* another other region is assumed to be uninitialized.
*/
nsTArray<Tile> mRetainedTiles;
int mRetainedWidth; // in tiles
int mRetainedHeight; // in tiles
private:
TiledLayerBuffer(const TiledLayerBuffer&) MOZ_DELETE;
const Derived& AsDerived() const { return *static_cast<const Derived*>(this); }
Derived& AsDerived() { return *static_cast<Derived*>(this); }
bool IsPlaceholder(Tile aTile) const { return aTile == AsDerived().GetPlaceholderTile(); }
};
class BasicTiledLayerBuffer;
// Shadow layers may implement this interface in order to be notified when a
// tiled layer buffer is updated.
class TiledLayerComposer
{
public:
/**
* Update the current retained layer with the updated layer data.
* The BasicTiledLayerBuffer is expected to be in the ReadLock state
* prior to this being called. aTiledBuffer is copy constructed and
* is retained until it has been uploaded/copyed and unlocked.
*/
virtual void PaintedTiledLayerBuffer(const BasicTiledLayerBuffer* aTiledBuffer) = 0;
};
template<typename Derived, typename Tile> Tile
TiledLayerBuffer<Derived, Tile>::GetTile(const nsIntPoint& aTileOrigin) const
{
// TODO Cache firstTileOriginX/firstTileOriginY
// Find the tile x/y of the first tile and the target tile relative to the (0, 0)
// origin, the difference is the tile x/y relative to the start of the tile buffer.
int firstTileX = mValidRegion.GetBounds().x / GetTileLength();
int firstTileY = mValidRegion.GetBounds().y / GetTileLength();
return GetTile(aTileOrigin.x / GetTileLength() - firstTileX,
aTileOrigin.y / GetTileLength() - firstTileY);
}
template<typename Derived, typename Tile> Tile
TiledLayerBuffer<Derived, Tile>::GetTile(int x, int y) const
{
int index = x * mRetainedHeight + y;
return mRetainedTiles.SafeElementAt(index, AsDerived().GetPlaceholderTile());
}
template<typename Derived, typename Tile> void
TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
const nsIntRegion& aPaintRegion)
{
nsTArray<Tile> newRetainedTiles;
nsTArray<Tile>& oldRetainedTiles = mRetainedTiles;
const nsIntRect oldBound = mValidRegion.GetBounds();
const nsIntRect newBound = aNewValidRegion.GetBounds();
const nsIntPoint oldBufferOrigin(RoundDownToTileEdge(oldBound.x),
RoundDownToTileEdge(oldBound.y));
const nsIntPoint newBufferOrigin(RoundDownToTileEdge(newBound.x),
RoundDownToTileEdge(newBound.y));
const nsIntRegion& oldValidRegion = mValidRegion;
const nsIntRegion& newValidRegion = aNewValidRegion;
const int oldRetainedHeight = mRetainedHeight;
// Pass 1: Recycle valid content from the old buffer
// Recycle tiles from the old buffer that contain valid regions.
// Insert placeholders tiles if we have no valid area for that tile
// which we will allocate in pass 2.
// TODO: Add a tile pool to reduce new allocation
int tileX = 0;
int tileY;
// Iterate over the new drawing bounds in steps of tiles.
for (int x = newBound.x; x < newBound.XMost(); tileX++) {
// Compute tileRect(x,y,width,height) in layer space coordinate
// giving us the rect of the tile that hits the newBounds.
int width = GetTileLength() - x % GetTileLength();
if (x + width > newBound.XMost()) {
width = newBound.x + newBound.width - x;
}
tileY = 0;
for (int y = newBound.y; y < newBound.YMost(); tileY++) {
int height = GetTileLength() - y % GetTileLength();
if (y + height > newBound.y + newBound.height) {
height = newBound.y + newBound.height - y;
}
const nsIntRect tileRect(x,y,width,height);
if (oldValidRegion.Intersects(tileRect) && newValidRegion.Intersects(tileRect)) {
// This old tiles contains some valid area so move it to the new tile
// buffer. Replace the tile in the old buffer with a placeholder
// to leave the old buffer index unaffected.
int tileX = (x - oldBufferOrigin.x) / GetTileLength();
int tileY = (y - oldBufferOrigin.y) / GetTileLength();
int index = tileX * oldRetainedHeight + tileY;
NS_ABORT_IF_FALSE(!IsPlaceholder(oldRetainedTiles.
SafeElementAt(index, AsDerived().GetPlaceholderTile())),
"Expected tile");
Tile tileWithPartialValidContent = oldRetainedTiles[index];
newRetainedTiles.AppendElement(tileWithPartialValidContent);
oldRetainedTiles[index] = AsDerived().GetPlaceholderTile();
} else {
// This tile is either:
// 1) Outside the new valid region and will simply be an empty
// placeholder forever.
// 2) The old buffer didn't have any data for this tile. We postpone
// the allocation of this tile after we've reused any tile with
// valid content because then we know we can safely recycle
// with taking from a tile that has recyclable content.
newRetainedTiles.AppendElement(AsDerived().GetPlaceholderTile());
}
y += height;
}
x += width;
}
// Keep track of the number of horizontal/vertical tiles
// in the buffer so that we can easily look up a tile.
mRetainedWidth = tileX;
mRetainedHeight = tileY;
NS_ABORT_IF_FALSE(aNewValidRegion.Contains(aPaintRegion), "Painting a region outside the visible region");
#ifdef DEBUG
nsIntRegion oldAndPainted(oldValidRegion);
oldAndPainted.Or(oldAndPainted, aPaintRegion);
#endif
NS_ABORT_IF_FALSE(oldAndPainted.Contains(newValidRegion), "newValidRegion has not been fully painted");
nsIntRegion regionToPaint(aPaintRegion);
// Pass 2: Validate
// We know at this point that any tile in the new buffer that had valid content
// from the previous buffer is placed correctly in the new buffer.
// We know that any tile in the old buffer that isn't a place holder is
// of no use and can be recycled.
// We also know that any place holder tile in the new buffer must be
// allocated.
tileX = 0;
for (int x = newBound.x; x < newBound.x + newBound.width; tileX++) {
// Compute tileRect(x,y,width,height) in layer space coordinate
// giving us the rect of the tile that hits the newBounds.
int tileStartX = RoundDownToTileEdge(x);
int width = GetTileLength() - x % GetTileLength();
if (x + width > newBound.XMost())
width = newBound.XMost() - x;
tileY = 0;
for (int y = newBound.y; y < newBound.y + newBound.height; tileY++) {
int tileStartY = RoundDownToTileEdge(y);
int height = GetTileLength() - y % GetTileLength();
if (y + height > newBound.YMost()) {
height = newBound.YMost() - y;
}
const nsIntRect tileRect(x, y, width, height);
nsIntRegion tileDrawRegion;
tileDrawRegion.And(tileRect, regionToPaint);
if (tileDrawRegion.IsEmpty()) {
// We have a tile but it doesn't hit the draw region
// because we can reuse all of the content from the
// previous buffer.
#ifdef DEBUG
int currTileX = (x - newBufferOrigin.x) / GetTileLength();
int currTileY = (y - newBufferOrigin.y) / GetTileLength();
int index = currTileX * mRetainedHeight + currTileY;
NS_ABORT_IF_FALSE(!newValidRegion.Intersects(tileRect) ||
!IsPlaceholder(newRetainedTiles.
SafeElementAt(index, AsDerived().GetPlaceholderTile())),
"If we don't draw a tile we shouldn't have a placeholder there.");
#endif
y += height;
continue;
}
int tileX = (x - newBufferOrigin.x) / GetTileLength();
int tileY = (y - newBufferOrigin.y) / GetTileLength();
int index = tileX * mRetainedHeight + tileY;
NS_ABORT_IF_FALSE(index >= 0 && index < newRetainedTiles.Length(), "index out of range");
Tile newTile = newRetainedTiles[index];
while (IsPlaceholder(newTile) && oldRetainedTiles.Length() > 0) {
AsDerived().SwapTiles(newTile, oldRetainedTiles[oldRetainedTiles.Length()-1]);
oldRetainedTiles.RemoveElementAt(oldRetainedTiles.Length()-1);
}
// We've done our best effort to recycle a tile but it can be null
// in which case it's up to the derived class's ValidateTile()
// implementation to allocate a new tile before drawing
nsIntPoint tileOrigin(tileStartX, tileStartY);
newTile = AsDerived().ValidateTile(newTile, nsIntPoint(tileStartX, tileStartY),
tileDrawRegion);
NS_ABORT_IF_FALSE(!IsPlaceholder(newTile), "index out of range");
newRetainedTiles[index] = newTile;
y += height;
}
x += width;
}
// Throw away any tiles we didn't recycle
// TODO: Add a tile pool
while (oldRetainedTiles.Length() > 0) {
Tile oldTile = oldRetainedTiles[oldRetainedTiles.Length()-1];
oldRetainedTiles.RemoveElementAt(oldRetainedTiles.Length()-1);
AsDerived().ReleaseTile(oldTile);
}
mRetainedTiles = newRetainedTiles;
mValidRegion = aNewValidRegion;
mLastPaintRegion = aPaintRegion;
}
} // layers
} // mozilla
#endif // GFX_TILEDLAYERBUFFER_H

View File

@ -0,0 +1,118 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GFX_BASICIMPLDATA_H
#define GFX_BASICIMPLDATA_H
namespace mozilla {
namespace layers {
/**
* This is the ImplData for all Basic layers. It also exposes methods
* private to the Basic implementation that are common to all Basic layer types.
* In particular, there is an internal Paint() method that we can use
* to paint the contents of non-Thebes layers.
*
* The class hierarchy for Basic layers is like this:
* BasicImplData
* Layer | | |
* | | | |
* +-> ContainerLayer | | |
* | | | | |
* | +-> BasicContainerLayer <--+ | |
* | | |
* +-> ThebesLayer | |
* | | | |
* | +-> BasicThebesLayer <---------+ |
* | |
* +-> ImageLayer |
* | |
* +-> BasicImageLayer <--------------+
*/
class BasicImplData {
public:
BasicImplData() : mHidden(false),
mClipToVisibleRegion(false),
mDrawAtomically(false),
mOperator(gfxContext::OPERATOR_OVER)
{
MOZ_COUNT_CTOR(BasicImplData);
}
virtual ~BasicImplData()
{
MOZ_COUNT_DTOR(BasicImplData);
}
/**
* Layers that paint themselves, such as ImageLayers, should paint
* in response to this method call. aContext will already have been
* set up to account for all the properties of the layer (transform,
* opacity, etc).
*/
virtual void Paint(gfxContext* aContext) {}
/**
* Like Paint() but called for ThebesLayers with the additional parameters
* they need.
* If mClipToVisibleRegion is set, then the layer must clip to its
* effective visible region (snapped or unsnapped, it doesn't matter).
*/
virtual void PaintThebes(gfxContext* aContext,
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData,
ReadbackProcessor* aReadback) {}
virtual ShadowableLayer* AsShadowableLayer() { return nsnull; }
/**
* Implementations return true here if they *must* retain their
* layer contents. This is true of shadowable layers with shadows,
* because there's no target on which to composite directly in the
* layer-publishing child process.
*/
virtual bool MustRetainContent() { return false; }
/**
* Layers will get this call when their layer manager is destroyed, this
* indicates they should clear resources they don't really need after their
* LayerManager ceases to exist.
*/
virtual void ClearCachedResources() {}
/**
* This variable is set by MarkLayersHidden() before painting. It indicates
* that the layer should not be composited during this transaction.
*/
void SetHidden(bool aCovered) { mHidden = aCovered; }
bool IsHidden() const { return false; }
/**
* This variable is set by MarkLayersHidden() before painting. This is
* the operator to be used when compositing the layer in this transaction. It must
* be OVER or SOURCE.
*/
void SetOperator(gfxContext::GraphicsOperator aOperator)
{
NS_ASSERTION(aOperator == gfxContext::OPERATOR_OVER ||
aOperator == gfxContext::OPERATOR_SOURCE,
"Bad composition operator");
mOperator = aOperator;
}
gfxContext::GraphicsOperator GetOperator() const { return mOperator; }
bool GetClipToVisibleRegion() { return mClipToVisibleRegion; }
void SetClipToVisibleRegion(bool aClip) { mClipToVisibleRegion = aClip; }
void SetDrawAtomically(bool aDrawAtomically) { mDrawAtomically = aDrawAtomically; }
protected:
bool mHidden;
bool mClipToVisibleRegion;
bool mDrawAtomically;
gfxContext::GraphicsOperator mOperator;
};
} // layers
} // mozilla
#endif

View File

@ -48,6 +48,7 @@
#include "ipc/ShadowLayerChild.h"
#include "BasicLayers.h"
#include "BasicImplData.h"
#include "ImageLayers.h"
#include "RenderTrace.h"
@ -78,110 +79,6 @@ namespace layers {
class BasicContainerLayer;
class ShadowableLayer;
/**
* This is the ImplData for all Basic layers. It also exposes methods
* private to the Basic implementation that are common to all Basic layer types.
* In particular, there is an internal Paint() method that we can use
* to paint the contents of non-Thebes layers.
*
* The class hierarchy for Basic layers is like this:
* BasicImplData
* Layer | | |
* | | | |
* +-> ContainerLayer | | |
* | | | | |
* | +-> BasicContainerLayer <--+ | |
* | | |
* +-> ThebesLayer | |
* | | | |
* | +-> BasicThebesLayer <---------+ |
* | |
* +-> ImageLayer |
* | |
* +-> BasicImageLayer <--------------+
*/
class BasicImplData {
public:
BasicImplData() : mHidden(false),
mClipToVisibleRegion(false),
mDrawAtomically(false),
mOperator(gfxContext::OPERATOR_OVER)
{
MOZ_COUNT_CTOR(BasicImplData);
}
virtual ~BasicImplData()
{
MOZ_COUNT_DTOR(BasicImplData);
}
/**
* Layers that paint themselves, such as ImageLayers, should paint
* in response to this method call. aContext will already have been
* set up to account for all the properties of the layer (transform,
* opacity, etc).
*/
virtual void Paint(gfxContext* aContext) {}
/**
* Like Paint() but called for ThebesLayers with the additional parameters
* they need.
* If mClipToVisibleRegion is set, then the layer must clip to its
* effective visible region (snapped or unsnapped, it doesn't matter).
*/
virtual void PaintThebes(gfxContext* aContext,
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData,
ReadbackProcessor* aReadback) {}
virtual ShadowableLayer* AsShadowableLayer() { return nsnull; }
/**
* Implementations return true here if they *must* retain their
* layer contents. This is true of shadowable layers with shadows,
* because there's no target on which to composite directly in the
* layer-publishing child process.
*/
virtual bool MustRetainContent() { return false; }
/**
* Layers will get this call when their layer manager is destroyed, this
* indicates they should clear resources they don't really need after their
* LayerManager ceases to exist.
*/
virtual void ClearCachedResources() {}
/**
* This variable is set by MarkLayersHidden() before painting. It indicates
* that the layer should not be composited during this transaction.
*/
void SetHidden(bool aCovered) { mHidden = aCovered; }
bool IsHidden() const { return false; }
/**
* This variable is set by MarkLayersHidden() before painting. This is
* the operator to be used when compositing the layer in this transaction. It must
* be OVER or SOURCE.
*/
void SetOperator(gfxContext::GraphicsOperator aOperator)
{
NS_ASSERTION(aOperator == gfxContext::OPERATOR_OVER ||
aOperator == gfxContext::OPERATOR_SOURCE,
"Bad composition operator");
mOperator = aOperator;
}
gfxContext::GraphicsOperator GetOperator() const { return mOperator; }
bool GetClipToVisibleRegion() { return mClipToVisibleRegion; }
void SetClipToVisibleRegion(bool aClip) { mClipToVisibleRegion = aClip; }
void SetDrawAtomically(bool aDrawAtomically) { mDrawAtomically = aDrawAtomically; }
protected:
bool mHidden;
bool mClipToVisibleRegion;
bool mDrawAtomically;
gfxContext::GraphicsOperator mOperator;
};
class AutoSetOperator {
public:
AutoSetOperator(gfxContext* aContext, gfxContext::GraphicsOperator aOperator) {
@ -2117,53 +2014,13 @@ BasicLayerManager::CreateReadbackLayer()
return layer.forget();
}
class BasicShadowableThebesLayer;
class BasicShadowableLayer : public ShadowableLayer
BasicShadowableLayer::~BasicShadowableLayer()
{
public:
BasicShadowableLayer()
{
MOZ_COUNT_CTOR(BasicShadowableLayer);
if (HasShadow()) {
PLayerChild::Send__delete__(GetShadow());
}
~BasicShadowableLayer()
{
if (HasShadow()) {
PLayerChild::Send__delete__(GetShadow());
}
MOZ_COUNT_DTOR(BasicShadowableLayer);
}
void SetShadow(PLayerChild* aShadow)
{
NS_ABORT_IF_FALSE(!mShadow, "can't have two shadows (yet)");
mShadow = aShadow;
}
virtual void SetBackBuffer(const SurfaceDescriptor& aBuffer)
{
NS_RUNTIMEABORT("if this default impl is called, |aBuffer| leaks");
}
virtual void SetBackBufferYUVImage(gfxSharedImageSurface* aYBuffer,
gfxSharedImageSurface* aUBuffer,
gfxSharedImageSurface* aVBuffer)
{
NS_RUNTIMEABORT("if this default impl is called, |aBuffer| leaks");
}
virtual void Disconnect()
{
// This is an "emergency Disconnect()", called when the compositing
// process has died. |mShadow| and our Shmem buffers are
// automatically managed by IPDL, so we don't need to explicitly
// free them here (it's hard to get that right on emergency
// shutdown anyway).
mShadow = nsnull;
}
virtual BasicShadowableThebesLayer* AsThebes() { return nsnull; }
};
MOZ_COUNT_DTOR(BasicShadowableLayer);
}
static ShadowableLayer*
ToShadowable(Layer* aLayer)

View File

@ -278,6 +278,49 @@ private:
LayerRefArray mKeepAlive;
};
class BasicShadowableThebesLayer;
class BasicShadowableLayer : public ShadowableLayer
{
public:
BasicShadowableLayer()
{
MOZ_COUNT_CTOR(BasicShadowableLayer);
}
~BasicShadowableLayer();
void SetShadow(PLayerChild* aShadow)
{
NS_ABORT_IF_FALSE(!mShadow, "can't have two shadows (yet)");
mShadow = aShadow;
}
virtual void SetBackBuffer(const SurfaceDescriptor& aBuffer)
{
NS_RUNTIMEABORT("if this default impl is called, |aBuffer| leaks");
}
virtual void SetBackBufferYUVImage(gfxSharedImageSurface* aYBuffer,
gfxSharedImageSurface* aUBuffer,
gfxSharedImageSurface* aVBuffer)
{
NS_RUNTIMEABORT("if this default impl is called, |aBuffer| leaks");
}
virtual void Disconnect()
{
// This is an "emergency Disconnect()", called when the compositing
// process has died. |mShadow| and our Shmem buffers are
// automatically managed by IPDL, so we don't need to explicitly
// free them here (it's hard to get that right on emergency
// shutdown anyway).
mShadow = nsnull;
}
virtual BasicShadowableThebesLayer* AsThebes() { return nsnull; }
};
}
}

View File

@ -132,6 +132,10 @@ gfxPattern::SetMatrix(const gfxMatrix& matrix)
cairo_pattern_set_matrix(mPattern, &mat);
} else {
mTransform = ToMatrix(matrix);
// Cairo-pattern matrices specify the conversion from DrawTarget to pattern
// space. Azure pattern matrices specify the conversion from pattern to
// DrawTarget space.
mTransform.Invert();
}
}

View File

@ -1265,15 +1265,6 @@ public:
// clears that capture.
static void ClearMouseCapture(nsIFrame* aFrame);
void SetScrollPositionClampingScrollPortSize(nscoord aWidth, nscoord aHeight);
bool IsScrollPositionClampingScrollPortSizeSet() {
return mScrollPositionClampingScrollPortSizeSet;
}
nsSize GetScrollPositionClampingScrollPortSize() {
NS_ASSERTION(mScrollPositionClampingScrollPortSizeSet, "asking for scroll port when its not set?");
return mScrollPositionClampingScrollPortSize;
}
protected:
friend class nsRefreshDriver;
@ -1324,8 +1315,6 @@ protected:
bool mSuppressInterruptibleReflows;
bool mScrollPositionClampingScrollPortSizeSet;
// A list of weak frames. This is a pointer to the last item in the list.
nsWeakFrame* mWeakFrames;
@ -1344,8 +1333,6 @@ protected:
float mXResolution;
float mYResolution;
nsSize mScrollPositionClampingScrollPortSize;
static nsIContent* gKeyDownTarget;
};

View File

@ -831,8 +831,6 @@ PresShell::PresShell()
mYResolution = 1.0;
mViewportOverridden = false;
mScrollPositionClampingScrollPortSizeSet = false;
static bool addedSynthMouseMove = false;
if (!addedSynthMouseMove) {
Preferences::AddBoolVarCache(&sSynthMouseMove,
@ -9149,10 +9147,3 @@ PresShell::SizeOfTextRuns(nsMallocSizeOfFun aMallocSizeOf) const
/* clear = */false);
}
void
nsIPresShell::SetScrollPositionClampingScrollPortSize(nscoord aWidth, nscoord aHeight)
{
mScrollPositionClampingScrollPortSizeSet = true;
mScrollPositionClampingScrollPortSize.width = aWidth;
mScrollPositionClampingScrollPortSize.height = aHeight;
}

View File

@ -1645,7 +1645,7 @@ Clamp(nscoord aLower, nscoord aVal, nscoord aUpper)
nsPoint
nsGfxScrollFrameInner::ClampScrollPosition(const nsPoint& aPt) const
{
nsRect range = GetScrollRangeForClamping();
nsRect range = GetScrollRange();
return nsPoint(Clamp(range.x, aPt.x, range.XMost()),
Clamp(range.y, aPt.y, range.YMost()));
}
@ -1971,7 +1971,7 @@ nsGfxScrollFrameInner::RestrictToDevPixels(const nsPoint& aPt,
// pixels. But we also need to make sure that our position remains
// inside the allowed region.
if (aShouldClamp) {
nsRect scrollRange = GetScrollRangeForClamping();
nsRect scrollRange = GetScrollRange();
*aPtDevPx = nsIntPoint(ClampInt(scrollRange.x, aPt.x, scrollRange.XMost(), appUnitsPerDevPixel),
ClampInt(scrollRange.y, aPt.y, scrollRange.YMost(), appUnitsPerDevPixel));
} else {
@ -2326,16 +2326,10 @@ AlignToDevPixelRoundingToZero(nscoord aVal, PRInt32 aAppUnitsPerDevPixel)
nsRect
nsGfxScrollFrameInner::GetScrollRange() const
{
return GetScrollRange(mScrollPort.width, mScrollPort.height);
}
nsRect
nsGfxScrollFrameInner::GetScrollRange(nscoord aWidth, nscoord aHeight) const
{
nsRect range = GetScrolledRect();
range.width -= aWidth;
range.height -= aHeight;
range.width -= mScrollPort.width;
range.height -= mScrollPort.height;
nsPresContext* presContext = mOuter->PresContext();
PRInt32 appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
@ -2348,17 +2342,6 @@ nsGfxScrollFrameInner::GetScrollRange(nscoord aWidth, nscoord aHeight) const
return range;
}
nsRect
nsGfxScrollFrameInner::GetScrollRangeForClamping() const
{
nsIPresShell* presShell = mOuter->PresContext()->PresShell();
if (presShell->IsScrollPositionClampingScrollPortSizeSet()) {
nsSize size = presShell->GetScrollPositionClampingScrollPortSize();
return GetScrollRange(size.width, size.height);
}
return GetScrollRange();
}
static void
AdjustForWholeDelta(PRInt32 aDelta, nscoord* aCoord)
{

View File

@ -178,12 +178,7 @@ public:
return pt;
}
nsRect GetScrollRange() const;
// Get the scroll range assuming the scrollport has size (aWidth, aHeight).
nsRect GetScrollRange(nscoord aWidth, nscoord aHeight) const;
protected:
nsRect GetScrollRangeForClamping() const;
public:
nsPoint RestrictToDevPixels(const nsPoint& aPt, nsIntPoint* aPtDevPx, bool aShouldClamp) const;
nsPoint ClampScrollPosition(const nsPoint& aPt) const;
static void AsyncScrollCallback(nsITimer *aTimer, void* anInstance);

View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<p>
From WebKit <a href='https://bugs.webkit.org/show_bug.cgi?id=50913'>bug 50913</a>
</p>
<p>
In this example, usernames are shown along with the number of posts that the user has submitted. If the bdi element were not used, the username of the Arabic user would end up confusing the text (the bidirectional algorithm would put the colon and the number "3" next to the word "User" rather than next to the word "posts").
</p>
<ul>
<li><bdo dir="ltr">User jcranmer: 12 posts.</bdo>
<li><bdo dir="ltr">User hober: 5 posts.</bdo>
<li><bdo dir="ltr">User نايإ: 3 posts.</bdo>
</ul>
</body>
</html>

View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<p>
From WebKit <a href='https://bugs.webkit.org/show_bug.cgi?id=50913'>bug 50913</a>
</p>
<p>
In this example, usernames are shown along with the number of posts that the user has submitted. If the bdi element were not used, the username of the Arabic user would end up confusing the text (the bidirectional algorithm would put the colon and the number "3" next to the word "User" rather than next to the word "posts").
</p>
<ul>
<li>User <bdi>jcranmer</bdi>: 12 posts.
<li>User <bdi>hober</bdi>: 5 posts.
<li>User <bdi>إيان</bdi>: 3 posts.
</ul>
</body>
</html>

View File

@ -1,3 +1,4 @@
fails-if(Android) == bdi-element.html bdi-element-ref.html # sub-pixel AA
== bidi-000.html bidi-000-ref.html
== bidi-001.html bidi-001-ref.html
== bidi-001-j.html bidi-001-ref.html
@ -32,6 +33,13 @@ random-if(cocoaWidget) == mirroring-02.html mirroring-02-ref.html
== mixedChartype-03-j.html mixedChartype-03-ref.html
== unicode-bidi-anonymous-001.html unicode-bidi-anonymous-001-ref.html
== unicode-bidi-anonymous-002.html unicode-bidi-anonymous-002-ref.html
fails == unicode-bidi-isolate-basic.html unicode-bidi-isolate-basic-ref.html # bug 712600
fails == unicode-bidi-isolate-aharon.html unicode-bidi-isolate-aharon-ref.html # bug 712600
fails-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)&&!layersGPUAccelerated) == unicode-bidi-plaintext.html unicode-bidi-plaintext-ref.html # sub-pixel AA
== unicode-bidi-plaintext-textarea-1.html unicode-bidi-plaintext-textarea-ref.html
== unicode-bidi-plaintext-textarea-2.html unicode-bidi-plaintext-textarea-ref.html
== unicode-bidi-plaintext-textarea-3.html unicode-bidi-plaintext-textarea-ref.html
== unicode-bidi-plaintext-textarea-4.html unicode-bidi-plaintext-textarea-ref.html
== with-first-letter-1a.html with-first-letter-1-ref.html
== with-first-letter-1b.html with-first-letter-1-ref.html
random-if(cocoaWidget) == with-first-letter-2a.html with-first-letter-2-ref.html # bug 734313

View File

@ -0,0 +1,69 @@
<!DOCTYPE html>
<html><head>
<title>Test cases for unicode-bidi:isolate</title>
<style>
</style>
</head><body>
opposite-to-base isolate followed by number.
<div>
<div class="reference">
<span dir="ltr">&#x05D0;</span> (3 reviews)
</div>
</div>
<hr>
opposite-to-base isolate with opposite-to-base text before it with neutrals in between.
<div>
<div class="reference">
<span dir="ltr">&#x05D0;</span>: <span dir="ltr">&#x05D1;</span>
</div>
</div>
<hr>
opposite-to-base isolate with opposite-to-base text before it and nothing in between.
<div>
<div class="reference">
<bdo dir="ltr">&#x05D0;&#x05D1;</bdo>
</div>
</div>
<hr>
two opposite-to-base isolates with neutrals in between.
<div>
<div class="reference">
<span dir="ltr">&#x05D0;</span> = <span dir="ltr">&#x05D1;</span>
</div>
</div>
<hr>
two opposite-to-base isolates with nothing in between.
<div>
<div class="reference">
<bdo dir="ltr">&#x05D0;&#x05D1;</bdo>
</div>
</div>
<hr>
same-as-base isolate preceded by opposite-to-base text and followed by number
<div dir="rtl">
<div class="reference">
see <span dir="ltr">&#x05D0;</span><sup>3</sup>
</div>
</div>
<hr>
same-as-base isolate surrounded by opposite-to-base text
<div dir="rtl">
<div class="reference">
with <span dir="ltr">&#x05D0;</span>=<span dir="ltr">&#x05D1;</span> everywhere
</div>
</div>
<hr>
chimeric isolate surrounded by chimeric text
<div>
<div class="reference">
about that <span dir="ltr">&#x05D0;</span> - &#x05D1;
</div>
</div>
<hr>
nested chimeric isolates surrounded by chimeric text
<div>
<div class="reference">
about that strange <span dir="ltr">&#x05D0;</span> - <span dir="ltr">&#x05D1;</span> - &#x05D2;
</div>
</div>
</body></html>

View File

@ -0,0 +1,74 @@
<!DOCTYPE html>
<html><head>
<title>Test cases for unicode-bidi:isolate</title>
<style>
.isolate {
unicode-bidi: -webkit-isolate;
unicode-bidi: -moz-isolate;
unicode-bidi: isolate;
}
</style>
</head><body>
opposite-to-base isolate followed by number.
<div>
<div class="test">
<span class="isolate">&#x05D0;</span> (3 reviews)
</div>
</div>
<hr>
opposite-to-base isolate with opposite-to-base text before it with neutrals in between.
<div>
<div class="test">
&#x05D0;: <span class="isolate">&#x05D1;</span>
</div>
</div>
<hr>
opposite-to-base isolate with opposite-to-base text before it and nothing in between.
<div>
<div class="test">
&#x05D0;<span class="isolate">&#x05D1;</span>
</div>
</div>
<hr>
two opposite-to-base isolates with neutrals in between.
<div>
<div class="test">
<span class="isolate">&#x05D0;</span> = <span class="isolate">&#x05D1;</span>
</div>
</div>
<hr>
two opposite-to-base isolates with nothing in between.
<div>
<div class="test">
<span class="isolate">&#x05D0;</span><span class="isolate">&#x05D1;</span>
</div>
</div>
<hr>
same-as-base isolate preceded by opposite-to-base text and followed by number
<div dir="rtl">
<div class="test">
see <span class="isolate">&#x05D0;</span><sup>3</sup>
</div>
</div>
<hr>
same-as-base isolate surrounded by opposite-to-base text
<div dir="rtl">
<div class="test">
with <span class="isolate">&#x05D0;</span>=<span class="isolate">&#x05D1;</span> everywhere
</div>
</div>
<hr>
chimeric isolate surrounded by chimeric text
<div>
<div class="test">
about <span class="isolate">that &#x05D0;</span> - &#x05D1;
</div>
</div>
<hr>
nested chimeric isolates surrounded by chimeric text
<div>
<div class="test">
about <span class="isolate">that <span class="isolate">strange &#x05D0;</span> - &#x05D1;</span> - &#x05D2;
</div>
</div>
</body></html>

View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="unicode-bidi-isolate-basic.js"></script>
<style>
.resultsDiv {
-moz-column-width: 3em;
-webkit-column-width: 3em;
-moz-column-gap: 5em;
-webkit-column-gap: 5em;
text-align: left;
}
.enclosed { display: inline-block; }
</style>
</head>
<body onload="buildTable();">
<div id="resultsContainer" style="position: relative">
<div id="elem" class="resultsDiv"></div>
</div>
</body>
</html>

View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="unicode-bidi-isolate-basic.js"></script>
<style>
.resultsDiv {
-moz-column-width: 3em;
-webkit-column-width: 3em;
-moz-column-gap: 5em;
-webkit-column-gap: 5em;
text-align: left;
}
.enclosed { unicode-bidi: -moz-isolate; }
</style>
</head>
<body onload="buildTable()">
<div id="resultsContainer" style="position: relative">
<div id="elem" class="resultsDiv"></div>
</div>
</body>
</html>

View File

@ -0,0 +1,44 @@
function buildTable()
{
var seed = 0;
var neutrals = ['"', ")", "("];
var strongRTLs = ['א', 'ב', 'ג', 'ד', 'ה', 'ו', 'ז'];
var strongLTRs = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
var neutral = function() { return neutrals[seed++ % neutrals.length]; }
var strongRTL = function() { return strongRTLs[seed++ % strongRTLs.length]; }
var strongLTR = function() { return strongLTRs[seed++ % strongLTRs.length]; }
var charClassExamples = [neutral, strongRTL, strongLTR];
var possibleDirs = ['ltr', 'rtl'];
var elem=document.getElementById("elem");
for (outerDirIndex in possibleDirs) {
var outerDir = possibleDirs[outerDirIndex];
for (beforeSpanIndex in charClassExamples) {
var beforeSpan = charClassExamples[beforeSpanIndex];
for (spanDirIndex in possibleDirs) {
var spanDir = possibleDirs[spanDirIndex];
for (inSpanIndex in charClassExamples) {
var inSpan = charClassExamples[inSpanIndex];
for (afterSpanIndex in charClassExamples) {
var afterSpan = charClassExamples[afterSpanIndex];
function caseWithStyle() {
seed = 0;
var outerDiv = document.createElement("div");
outerDiv.dir = outerDir;
outerDiv.appendChild(document.createTextNode(beforeSpan()));
var span = document.createElement("span");
span.dir = spanDir;
span.setAttribute("class", "enclosed")
span.appendChild(document.createTextNode(inSpan()));
outerDiv.appendChild(span);
outerDiv.appendChild(document.createTextNode(afterSpan()));
return outerDiv;
}
elem.appendChild(caseWithStyle());
}
}
}
}
}
}

View File

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<div>
!hello.<br>
<span dir=rtl>
!שלום.
</span><br>
<span dir=ltr>
hello, לוי!
</span><br>
<span dir=rtl>
שלום, WebKit!</span><br>
<pre>
a
(
!WebKit ,שלום
hello, לוי!
)
</pre>
</div>
</body>
</html>

View File

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html><head>
<title>unicode-bidi:plaintext</title>
<style>
textarea { text-align: left; resize: none; }
</style>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head><body>
<div>
The exclamation mark should be on the left side of the first line
and on the right side of the second line.
</div>
<textarea rows=4 cols=50 dir=auto>
שלום!
hello!
</textarea>
</body></html>

View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html><head>
<title>unicode-bidi:plaintext</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
.plaintext {
unicode-bidi:-webkit-plaintext;
unicode-bidi:-moz-plaintext;
unicode-bidi:plaintext;
}
textarea { text-align: left; resize: none; }
</style>
</head><body>
<div>
The exclamation mark should be on the left side of the first line
and on the right side of the second line.
</div>
<textarea rows=4 cols=50 class="plaintext">
שלום!
hello!
</textarea>
</body></html>

View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html><head>
<title>unicode-bidi:plaintext</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
.plaintext {
unicode-bidi:-webkit-plaintext;
unicode-bidi:-moz-plaintext;
unicode-bidi:plaintext;
}
textarea { text-align: left; resize: none; }
</style>
</head><body>
<div>
The exclamation mark should be on the left side of the first line
and on the right side of the second line.
</div>
<textarea rows=4 cols=50 dir="ltr" class="plaintext">
שלום!
hello!
</textarea>
</body></html>

View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html><head>
<title>unicode-bidi:plaintext</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
.plaintext {
unicode-bidi:-webkit-plaintext;
unicode-bidi:-moz-plaintext;
unicode-bidi:plaintext;
}
textarea { text-align: left; resize: none; }
</style>
</head><body>
<div>
The exclamation mark should be on the left side of the first line
and on the right side of the second line.
</div>
<textarea rows=4 cols=50 dir="rtl" class="plaintext">
שלום!
hello!
</textarea>
</body></html>

View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<title>unicode-bidi:plaintext</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
textarea { resize: none; }
</style>
</head>
<body>
<div>
The exclamation mark should be on the left side of the first line
and on the right side of the second line.
</div>
<textarea rows=4 cols=50 dir=ltr>
&#x202b;שלום!&#x202c;
&#x202a;hello!&#x202c
</textarea>
</body></html>

View File

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style>
div, pre { text-align: left; }
</style>
</head>
<body>
<div style="unicode-bidi: -webkit-plaintext; unicode-bidi: -moz-plaintext; unicode-bidi: plaintext;">
!hello.
<br>
!שלום.
<br>
hello, לוי!
<br>
שלום, WebKit!
</div>
<pre dir="auto">
a
(
שלום, WebKit!
hello, לוי!
)
</pre>
</body>
</html>

View File

@ -141,6 +141,7 @@ _TEST_FILES = test_acid3_test46.html \
test_computed_style_no_pseudo.html \
test_css_cross_domain.html \
test_css_eof_handling.html \
test_default_bidi_css.html \
test_descriptor_storage.html \
test_descriptor_syntax_errors.html \
test_dont_use_document_colors.html \

View File

@ -0,0 +1,79 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for Bug </title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for default bidi css **/
function styleOf(name, attributes) {
var element = document.createElement(name);
for (var name in attributes) {
var value = attributes[name];
element.setAttribute(name, value);
}
return getComputedStyle(element);
}
var tests = [
['div', {}, 'ltr', '-moz-isolate'],
['div', {'dir': 'ltr'}, 'ltr', '-moz-isolate'],
['div', {'dir': 'rtl'}, 'rtl', '-moz-isolate'],
['div', {'dir': 'auto'}, 'ltr', '-moz-isolate'],
['div', {'dir': ''}, 'ltr', '-moz-isolate'],
['span', {}, 'ltr', 'normal'],
['span', {'dir': 'ltr'}, 'ltr', 'embed'],
['span', {'dir': 'rtl'}, 'rtl', 'embed'],
['span', {'dir': 'auto'}, 'ltr', '-moz-isolate'],
['span', {'dir': ''}, 'ltr', 'normal'],
['bdi', {}, 'ltr', '-moz-isolate'],
['bdi', {'dir': 'ltr'}, 'ltr', '-moz-isolate'],
['bdi', {'dir': 'rtl'}, 'rtl', '-moz-isolate'],
['bdi', {'dir': 'auto'}, 'ltr', '-moz-isolate'],
['bdi', {'dir': ''}, 'ltr', '-moz-isolate'],
['output', {}, 'ltr', '-moz-isolate'],
['output', {'dir': 'ltr'}, 'ltr', '-moz-isolate'],
['output', {'dir': 'rtl'}, 'rtl', '-moz-isolate'],
['output', {'dir': 'auto'}, 'ltr', '-moz-isolate'],
['output', {'dir': ''}, 'ltr', '-moz-isolate'],
['bdo', {}, 'ltr', 'bidi-override'],
['bdo', {'dir': 'ltr'}, 'ltr', 'bidi-override'],
['bdo', {'dir': 'rtl'}, 'rtl', 'bidi-override'],
['bdo', {'dir': 'auto'}, 'ltr', '-moz-isolate bidi-override'],
['bdo', {'dir': ''}, 'ltr', 'bidi-override'],
['textarea', {}, 'ltr', 'normal'],
['textarea', {'dir': 'ltr'}, 'ltr', 'embed'],
['textarea', {'dir': 'rtl'}, 'rtl', 'embed'],
['textarea', {'dir': 'auto'}, 'ltr', '-moz-plaintext'],
['textarea', {'dir': ''}, 'ltr', 'normal'],
['pre', {}, 'ltr', '-moz-isolate'],
['pre', {'dir': 'ltr'}, 'ltr', '-moz-isolate'],
['pre', {'dir': 'rtl'}, 'rtl', '-moz-isolate'],
['pre', {'dir': 'auto'}, 'ltr', '-moz-plaintext'],
['pre', {'dir': ''}, 'ltr', '-moz-isolate'],
].forEach(function (test) {
var style = styleOf(test[0], test[1]);
is(style.direction, test[2], "default value for direction");
is(style.unicodeBidi, test[3], "default value for unicode-bidi");
});
</script>
</pre>
</body>
</html>

View File

@ -218,6 +218,7 @@ sa_stream_open(sa_stream_t *s) {
s->at_class = init_jni_bindings(jenv);
if (!s->at_class) {
(*jenv)->PopLocalFrame(jenv, NULL);
return SA_ERROR_NO_DEVICE;
}

View File

@ -273,7 +273,9 @@ public class BrowserToolbar {
} else {
mProgressSpinner.stop();
setStopVisibility(false);
setFavicon(Tabs.getInstance().getSelectedTab().getFavicon());
Tab selectedTab = Tabs.getInstance().getSelectedTab();
if (selectedTab != null)
setFavicon(selectedTab.getFavicon());
Log.i(LOGTAG, "zerdatime " + SystemClock.uptimeMillis() + " - Throbber stop");
}
}

View File

@ -670,6 +670,7 @@ abstract public class GeckoApp
tab.updateSecurityMode("unknown");
tab.removeTransientDoorHangers();
tab.setHasTouchListeners(false);
tab.setCheckerboardColor(Color.WHITE);
maybeCancelFaviconLoad(tab);
@ -829,14 +830,20 @@ abstract public class GeckoApp
final String title = message.getString("title");
final String backgroundColor = message.getString("bgColor");
handleContentLoaded(tabId, uri, title);
if (getLayerController() != null) {
if (backgroundColor != null) {
getLayerController().setCheckerboardColor(backgroundColor);
} else {
// Default to black if no color is given
getLayerController().setCheckerboardColor(0);
}
Tab tab = Tabs.getInstance().getTab(tabId);
if (backgroundColor != null) {
tab.setCheckerboardColor(backgroundColor);
} else {
// Default to white if no color is given
tab.setCheckerboardColor(Color.WHITE);
}
// Sync up the LayerController and the tab if the tab's
// currently displayed.
if (getLayerController() != null && Tabs.getInstance().isSelectedTab(tab)) {
getLayerController().setCheckerboardColor(tab.getCheckerboardColor());
}
Log.i(LOGTAG, "URI - " + uri + ", title - " + title);
} else if (event.equals("DOMTitleChanged")) {
final int tabId = message.getInt("tabID");
@ -1639,7 +1646,9 @@ abstract public class GeckoApp
}
mRestoreSession |= getProfile().shouldRestoreSession();
if (passedUri == null || passedUri.equals("about:home")) {
boolean isExternalURL = passedUri != null && !passedUri.equals("about:home");
if (!isExternalURL) {
// show about:home if we aren't restoring previous session
if (!mRestoreSession) {
mBrowserToolbar.updateTabCount(1);
@ -1649,6 +1658,8 @@ abstract public class GeckoApp
mBrowserToolbar.updateTabCount(1);
}
mBrowserToolbar.setProgressVisibility(isExternalURL || mRestoreSession);
// Start migrating as early as possible, can do this in
// parallel with Gecko load.
checkMigrateProfile();

View File

@ -529,14 +529,17 @@ public class GeckoAppShell
final int width, final int height) {
getHandler().post(new Runnable() {
public void run() {
final Tab tab = Tabs.getInstance().getTab(tabId);
if (tab == null)
return;
try {
final Tab tab = Tabs.getInstance().getTab(tabId);
if (tab == null)
return;
Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
b.copyPixelsFromBuffer(data);
freeDirectBuffer(data);
GeckoApp.mAppContext.processThumbnail(tab, b, null);
Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
b.copyPixelsFromBuffer(data);
GeckoApp.mAppContext.processThumbnail(tab, b, null);
} finally {
freeDirectBuffer(data);
}
}
});
}

View File

@ -481,6 +481,10 @@ RES_DRAWABLE_XHDPI_V11 = \
res/drawable-xhdpi-v11/address_bar_texture_port.png \
res/drawable-xhdpi-v11/address_bar_url_bg.9.png \
res/drawable-xhdpi-v11/address_bar_url_outline.9.png \
res/drawable-xhdpi-v11/doorhanger_arrow.png \
res/drawable-xhdpi-v11/doorhanger_bg.9.png \
res/drawable-xhdpi-v11/doorhanger_shadow_bg.9.png \
res/drawable-xhdpi-v11/doorhanger_popup_bg.9.png \
res/drawable-xhdpi-v11/urlbar_stop.png \
res/drawable-xhdpi-v11/site_security_identified.png \
res/drawable-xhdpi-v11/site_security_verified.png \

View File

@ -40,6 +40,7 @@ package org.mozilla.gecko;
import android.content.ContentResolver;
import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
@ -58,6 +59,8 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public final class Tab {
private static final String LOGTAG = "GeckoTab";
@ -68,6 +71,7 @@ public final class Tab {
private static float sDensity = 1;
private static int sMinScreenshotWidth = 0;
private static int sMinScreenshotHeight = 0;
private static Pattern sColorPattern;
private int mId;
private String mUrl;
private String mTitle;
@ -89,6 +93,7 @@ public final class Tab {
private HashMap<Surface, Layer> mPluginLayers;
private ContentResolver mContentResolver;
private ContentObserver mContentObserver;
private int mCheckerboardColor = Color.WHITE;
private int mState;
public static final int STATE_DELAYED = 0;
@ -561,4 +566,36 @@ public final class Tab {
public Layer removePluginLayer(Surface surface) {
return mPluginLayers.remove(surface);
}
public int getCheckerboardColor() {
return mCheckerboardColor;
}
/** Sets a new color for the checkerboard. */
public void setCheckerboardColor(int color) {
mCheckerboardColor = color;
}
/** Parses and sets a new color for the checkerboard. */
public void setCheckerboardColor(String newColor) {
setCheckerboardColor(parseColorFromGecko(newColor));
}
// Parses a color from an RGB triple of the form "rgb([0-9]+, [0-9]+, [0-9]+)". If the color
// cannot be parsed, returns white.
private static int parseColorFromGecko(String string) {
if (sColorPattern == null) {
sColorPattern = Pattern.compile("rgb\\((\\d+),\\s*(\\d+),\\s*(\\d+)\\)");
}
Matcher matcher = sColorPattern.matcher(string);
if (!matcher.matches()) {
return Color.WHITE;
}
int r = Integer.parseInt(matcher.group(1));
int g = Integer.parseInt(matcher.group(2));
int b = Integer.parseInt(matcher.group(3));
return Color.rgb(r, g, b);
}
}

View File

@ -58,6 +58,7 @@ import android.util.Log;
import android.view.View;
import java.util.Map;
import java.util.HashMap;
import org.mozilla.gecko.Tabs;
public class GeckoLayerClient implements GeckoEventResponder,
LayerView.Listener {
@ -329,6 +330,7 @@ public class GeckoLayerClient implements GeckoEventResponder,
currentMetrics.setZoomFactor(zoom);
currentMetrics.setPageSize(new FloatSize(pageWidth, pageHeight), new FloatSize(cssPageWidth, cssPageHeight));
mLayerController.setViewportMetrics(currentMetrics);
mLayerController.setCheckerboardColor(Tabs.getInstance().getSelectedTab().getCheckerboardColor());
// At this point, we have just switched to displaying a different document than we
// we previously displaying. This means we need to abort any panning/zooming animations
// that are in progress and send an updated display port request to browser.js as soon

View File

@ -52,8 +52,6 @@ import android.graphics.RectF;
import android.util.Log;
import android.view.GestureDetector;
import android.view.View.OnTouchListener;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* The layer controller manages a tile that represents the visible page. It does panning and
@ -91,13 +89,11 @@ public class LayerController {
private GeckoLayerClient mLayerClient; /* The layer client. */
/* The new color for the checkerboard. */
private int mCheckerboardColor;
private int mCheckerboardColor = Color.WHITE;
private boolean mCheckerboardShouldShowChecks;
private boolean mForceRedraw;
private static Pattern sColorPattern;
public LayerController(Context context) {
mContext = context;
@ -359,29 +355,4 @@ public class LayerController {
mCheckerboardColor = newColor;
mView.requestRender();
}
/** Parses and sets a new color for the checkerboard. */
public void setCheckerboardColor(String newColor) {
setCheckerboardColor(parseColorFromGecko(newColor));
}
// Parses a color from an RGB triple of the form "rgb([0-9]+, [0-9]+, [0-9]+)". If the color
// cannot be parsed, returns white.
private static int parseColorFromGecko(String string) {
if (sColorPattern == null) {
sColorPattern = Pattern.compile("rgb\\((\\d+),\\s*(\\d+),\\s*(\\d+)\\)");
}
Matcher matcher = sColorPattern.matcher(string);
if (!matcher.matches()) {
return Color.WHITE;
}
int r = Integer.parseInt(matcher.group(1));
int g = Integer.parseInt(matcher.group(2));
int b = Integer.parseInt(matcher.group(3));
return Color.rgb(r, g, b);
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 B

After

Width:  |  Height:  |  Size: 223 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 B

After

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 B

After

Width:  |  Height:  |  Size: 184 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 B

After

Width:  |  Height:  |  Size: 142 B

View File

@ -16,10 +16,10 @@
</ScrollView>
<ImageView android:layout_width="43dip"
android:layout_height="15dip"
<ImageView android:layout_width="44dip"
android:layout_height="16dip"
android:layout_marginLeft="4dip"
android:layout_marginTop="10dip"
android:layout_marginTop="9dip"
android:layout_alignParentTop="true"
android:src="@drawable/doorhanger_arrow"
android:scaleType="fitXY"/>

View File

@ -1560,6 +1560,7 @@ Tab.prototype = {
let frameLoader = this.browser.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader;
frameLoader.renderMode = Ci.nsIFrameLoader.RENDER_MODE_ASYNC_SCROLL;
frameLoader.clampScrollPosition = false;
// only set tab uri if uri is valid
let uri = null;
@ -1725,10 +1726,8 @@ Tab.prototype = {
let x = aViewport.x / aViewport.zoom;
let y = aViewport.y / aViewport.zoom;
// Set scroll-port size and scroll position (both in CSS pixels)
// Set scroll position
let win = this.browser.contentWindow;
win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).setScrollPositionClampingScrollPortSize(
gScreenWidth / aViewport.zoom, gScreenHeight / aViewport.zoom);
win.scrollTo(x, y);
this.userScrollPos.x = win.scrollX;
this.userScrollPos.y = win.scrollY;
@ -2044,11 +2043,6 @@ Tab.prototype = {
return;
}
let browser = BrowserApp.getBrowserForWindow(aWebProgress.DOMWindow);
let uri = "";
if (browser)
uri = browser.currentURI.spec;
// Check to see if we restoring the content from a previous presentation (session)
// since there should be no real network activity
let restoring = aStateFlags & Ci.nsIWebProgressListener.STATE_RESTORING;
@ -2056,6 +2050,10 @@ Tab.prototype = {
// true if the page loaded successfully (i.e., no 404s or other errors)
let success = false;
let uri = "";
try {
uri = aRequest.QueryInterface(Components.interfaces.nsIChannel).originalURI.spec;
} catch (e) { }
try {
success = aRequest.QueryInterface(Components.interfaces.nsIHttpChannel).requestSucceeded;
} catch (e) { }