This commit is contained in:
Philipp von Weitershausen 2011-10-27 11:32:20 -07:00
Родитель 0c57178a14 903c1e295e
Коммит 006f8e2a5d
75 изменённых файлов: 1729 добавлений и 436 удалений

Просмотреть файл

@ -654,7 +654,7 @@ nsAccessible::IsVisible(bool* aIsOffscreen)
}
// The frame intersects the viewport, but we need to check the parent view chain :(
bool isVisible = nsCoreUtils::CheckVisibilityInParentChain(frame);
bool isVisible = frame->IsVisibleConsideringAncestors(nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY);
if (isVisible && rectVisibility == nsRectVisibility_kVisible) {
*aIsOffscreen = false;
}

Просмотреть файл

@ -758,31 +758,6 @@ nsCoreUtils::IsColumnHidden(nsITreeColumn *aColumn)
nsGkAtoms::_true, eCaseMatters);
}
bool
nsCoreUtils::CheckVisibilityInParentChain(nsIFrame* aFrame)
{
nsIView* view = aFrame->GetClosestView();
if (view && !view->IsEffectivelyVisible())
return false;
nsIPresShell* presShell = aFrame->PresContext()->GetPresShell();
while (presShell) {
if (!presShell->IsActive()) {
return false;
}
nsIFrame* rootFrame = presShell->GetRootFrame();
presShell = nsnull;
if (rootFrame) {
nsIFrame* frame = nsLayoutUtils::GetCrossDocParentFrame(rootFrame);
if (frame) {
presShell = frame->PresContext()->GetPresShell();
}
}
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// nsAccessibleDOMStringList
////////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -370,11 +370,6 @@ public:
aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::scope);
}
/**
* Check the visibility across both parent content and chrome.
*/
static bool CheckVisibilityInParentChain(nsIFrame* aFrame);
};

Просмотреть файл

@ -311,7 +311,8 @@ nsDocAccessible::NativeState()
state |= states::BUSY;
nsIFrame* frame = GetFrame();
if (!frame || !nsCoreUtils::CheckVisibilityInParentChain(frame)) {
if (!frame ||
!frame->IsVisibleConsideringAncestors(nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY)) {
state |= states::INVISIBLE | states::OFFSCREEN;
}

Просмотреть файл

@ -1716,6 +1716,22 @@ public:
*/
static bool IsFullScreenKeyInputRestricted();
/**
* Returns true if the doctree rooted at aDoc contains any plugins which
* we don't control event dispatch for, i.e. do any plugins in this doc tree
* receive key events outside of our control? This always returns false
* on MacOSX.
*/
static bool HasPluginWithUncontrolledEventDispatch(nsIDocument* aDoc);
/**
* Returns true if the content is in a document and contains a plugin
* which we don't control event dispatch for, i.e. do any plugins in this
* doc tree receive key events outside of our control? This always returns
* false on MacOSX.
*/
static bool HasPluginWithUncontrolledEventDispatch(nsIContent* aContent);
/**
* Returns the time limit on handling user input before
* nsEventStateManager::IsHandlingUserInput() stops returning true.

Просмотреть файл

@ -203,8 +203,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
#include "nsDOMTouchEvent.h"
#include "nsIScriptElement.h"
#include "nsIContentViewer.h"
#include "prdtoa.h"
#include "nsIObjectLoadingContent.h"
#include "mozilla/Preferences.h"
@ -5815,6 +5814,70 @@ nsContentUtils::IsFullScreenKeyInputRestricted()
return sFullScreenKeyInputRestricted;
}
static void
CheckForWindowedPlugins(nsIContent* aContent, void* aResult)
{
if (!aContent->IsInDoc()) {
return;
}
nsCOMPtr<nsIObjectLoadingContent> olc(do_QueryInterface(aContent));
if (!olc) {
return;
}
nsRefPtr<nsNPAPIPluginInstance> plugin;
olc->GetPluginInstance(getter_AddRefs(plugin));
if (!plugin) {
return;
}
bool isWindowless = false;
nsresult res = plugin->IsWindowless(&isWindowless);
if (NS_SUCCEEDED(res) && !isWindowless) {
*static_cast<bool*>(aResult) = true;
}
}
static bool
DocTreeContainsWindowedPlugins(nsIDocument* aDoc, void* aResult)
{
if (!nsContentUtils::IsChromeDoc(aDoc)) {
aDoc->EnumerateFreezableElements(CheckForWindowedPlugins, aResult);
}
if (*static_cast<bool*>(aResult)) {
// Return false to stop iteration, we found a windowed plugin.
return false;
}
aDoc->EnumerateSubDocuments(DocTreeContainsWindowedPlugins, aResult);
// Return false to stop iteration if we found a windowed plugin in
// the sub documents.
return !*static_cast<bool*>(aResult);
}
/* static */
bool
nsContentUtils::HasPluginWithUncontrolledEventDispatch(nsIDocument* aDoc)
{
#ifdef XP_MACOSX
// We control dispatch to all mac plugins.
return false;
#endif
bool result = false;
DocTreeContainsWindowedPlugins(aDoc, &result);
return result;
}
/* static */
bool
nsContentUtils::HasPluginWithUncontrolledEventDispatch(nsIContent* aContent)
{
#ifdef XP_MACOSX
// We control dispatch to all mac plugins.
return false;
#endif
bool result = false;
CheckForWindowedPlugins(aContent, &result);
return result;
}
// static
void
nsContentUtils::ReleaseWrapper(nsISupports* aScriptObjectHolder,

Просмотреть файл

@ -8578,13 +8578,11 @@ nsDocument::GetMozFullScreenEnabled(bool *aFullScreen)
NS_ENSURE_ARG_POINTER(aFullScreen);
*aFullScreen = false;
if (!nsContentUtils::IsFullScreenApiEnabled()) {
if (!nsContentUtils::IsFullScreenApiEnabled() ||
nsContentUtils::HasPluginWithUncontrolledEventDispatch(this)) {
return NS_OK;
}
// todo: Bug 684618 - Deny requests for DOM full-screen when windowed
// plugins are present.
// Ensure that all ancestor <iframe> elements have the mozallowfullscreen
// boolean attribute set.
nsINode* node = static_cast<nsINode*>(this);

Просмотреть файл

@ -70,6 +70,7 @@ CPPSRCS += \
WebGLContextUtils.cpp \
WebGLContextValidate.cpp \
WebGLExtensionStandardDerivatives.cpp \
WebGLExtensionLoseContext.cpp \
$(NULL)
DEFINES += -DUSE_ANGLE

Просмотреть файл

@ -296,14 +296,21 @@ WebGLContext::WebGLContext()
// See OpenGL ES 2.0.25 spec, 6.2 State Tables, table 6.13
mPixelStorePackAlignment = 4;
mPixelStoreUnpackAlignment = 4;
WebGLMemoryReporter::AddWebGLContext(this);
mContextLost = false;
mAllowRestore = false;
}
WebGLContext::~WebGLContext()
{
DestroyResourcesAndContext();
WebGLMemoryReporter::RemoveWebGLContext(this);
if (mContextRestorer) {
mContextRestorer->Cancel();
mContextRestorer = NULL;
}
}
static PLDHashOperator
@ -822,6 +829,9 @@ WebGLContext::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
CanvasLayer *aOldLayer,
LayerManager *aManager)
{
if (mContextLost)
return nsnull;
if (!mResetLayer && aOldLayer &&
aOldLayer->HasUserData(&gWebGLLayerUserData)) {
NS_ADDREF(aOldLayer);
@ -885,6 +895,12 @@ WebGLContext::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
NS_IMETHODIMP
WebGLContext::GetContextAttributes(jsval *aResult)
{
if (mContextLost)
{
*aResult = OBJECT_TO_JSVAL(NULL);
return NS_OK;
}
JSContext *cx = nsContentUtils::GetCurrentJSContext();
if (!cx)
return NS_ERROR_FAILURE;
@ -923,6 +939,9 @@ WebGLContext::GetContextAttributes(jsval *aResult)
NS_IMETHODIMP
WebGLContext::MozGetUnderlyingParamString(PRUint32 pname, nsAString& retval)
{
if (mContextLost)
return NS_OK;
retval.SetIsVoid(true);
MakeContextCurrent();
@ -959,6 +978,10 @@ bool WebGLContext::IsExtensionSupported(WebGLExtensionID ei)
// We always support this extension.
isSupported = true;
break;
case WebGL_WEBKIT_lose_context:
// We always support this extension.
isSupported = true;
break;
default:
isSupported = false;
}
@ -970,6 +993,8 @@ NS_IMETHODIMP
WebGLContext::GetExtension(const nsAString& aName, nsIWebGLExtension **retval)
{
*retval = nsnull;
if (mContextLost)
return NS_OK;
if (mDisableExtensions) {
return NS_OK;
@ -985,6 +1010,10 @@ WebGLContext::GetExtension(const nsAString& aName, nsIWebGLExtension **retval)
if (IsExtensionSupported(WebGL_OES_standard_derivatives))
ei = WebGL_OES_standard_derivatives;
}
else if (aName.EqualsLiteral("WEBKIT_lose_context")) {
if (IsExtensionSupported(WebGL_WEBKIT_lose_context))
ei = WebGL_WEBKIT_lose_context;
}
if (ei != WebGLExtensionID_Max) {
if (!IsExtensionEnabled(ei)) {
@ -992,6 +1021,9 @@ WebGLContext::GetExtension(const nsAString& aName, nsIWebGLExtension **retval)
case WebGL_OES_standard_derivatives:
mEnabledExtensions[ei] = new WebGLExtensionStandardDerivatives(this);
break;
case WebGL_WEBKIT_lose_context:
mEnabledExtensions[ei] = new WebGLExtensionLoseContext(this);
break;
// create an extension for any types that don't
// have any additional tokens or methods
default:
@ -1095,6 +1127,86 @@ WebGLContext::EnsureBackbufferClearedAsNeeded()
Invalidate();
}
NS_IMETHODIMP
WebGLContext::Notify(nsITimer* timer)
{
MaybeRestoreContext();
if (mContextRestorer) {
mContextRestorer->Cancel();
mContextRestorer = NULL;
}
return NS_OK;
}
void
WebGLContext::MaybeRestoreContext()
{
if (mContextLost || mAllowRestore)
return;
GLContext::ContextResetARB resetStatus =
(GLContext::ContextResetARB) gl->fGetGraphicsResetStatus();
if (resetStatus != GLContext::CONTEXT_NO_ERROR) {
// It's already lost, but clean up after it and signal to JS that it is
// lost.
ForceLoseContext();
}
switch (resetStatus) {
case GLContext::CONTEXT_NO_ERROR:
return;
case GLContext::CONTEXT_GUILTY_CONTEXT_RESET_ARB:
NS_WARNING("WebGL content on the page caused the graphics card to reset; not restoring the context");
return;
case GLContext::CONTEXT_INNOCENT_CONTEXT_RESET_ARB:
break;
case GLContext::CONTEXT_UNKNOWN_CONTEXT_RESET_ARB:
NS_WARNING("WebGL content on the page might have caused the graphics card to reset");
break;
}
ForceRestoreContext();
}
void
WebGLContext::ForceLoseContext()
{
if (mContextRestorer) {
mContextRestorer->Cancel();
mContextRestorer = NULL;
}
mWebGLError = LOCAL_GL_CONTEXT_LOST;
bool defaultAction;
mContextLost = true;
DestroyResourcesAndContext();
nsContentUtils::DispatchTrustedEvent(HTMLCanvasElement()->OwnerDoc(),
(nsIDOMHTMLCanvasElement*) HTMLCanvasElement(),
NS_LITERAL_STRING("webglcontextlost"),
PR_TRUE,
PR_TRUE,
&defaultAction);
if (defaultAction)
mAllowRestore = false;
}
void
WebGLContext::ForceRestoreContext()
{
mContextLost = false;
mAllowRestore = false;
SetDimensions(mHeight, mWidth);
nsContentUtils::DispatchTrustedEvent(HTMLCanvasElement()->OwnerDoc(),
(nsIDOMHTMLCanvasElement*) HTMLCanvasElement(),
NS_LITERAL_STRING("webglcontextrestored"),
PR_TRUE,
PR_TRUE);
}
//
// XPCOM goop
//
@ -1116,6 +1228,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebGLContext)
NS_INTERFACE_MAP_ENTRY(nsIDOMWebGLRenderingContext)
NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextInternal)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMWebGLRenderingContext)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLRenderingContext)
NS_INTERFACE_MAP_END
@ -1254,10 +1367,24 @@ NS_INTERFACE_MAP_BEGIN(WebGLExtensionStandardDerivatives)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtensionStandardDerivatives)
NS_INTERFACE_MAP_END_INHERITING(WebGLExtension)
NS_IMPL_ADDREF(WebGLExtensionLoseContext)
NS_IMPL_RELEASE(WebGLExtensionLoseContext)
DOMCI_DATA(WebGLExtensionLoseContext, WebGLExtensionLoseContext)
NS_INTERFACE_MAP_BEGIN(WebGLExtensionLoseContext)
NS_INTERFACE_MAP_ENTRY(nsIWebGLExtensionLoseContext)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, WebGLExtension)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtensionLoseContext)
NS_INTERFACE_MAP_END_INHERITING(WebGLExtension)
/* readonly attribute WebGLsizei drawingBufferWidth; */
NS_IMETHODIMP
WebGLContext::GetDrawingBufferWidth(WebGLsizei *aWidth)
{
if (mContextLost)
return NS_OK;
*aWidth = mWidth;
return NS_OK;
}
@ -1266,6 +1393,9 @@ WebGLContext::GetDrawingBufferWidth(WebGLsizei *aWidth)
NS_IMETHODIMP
WebGLContext::GetDrawingBufferHeight(WebGLsizei *aHeight)
{
if (mContextLost)
return NS_OK;
*aHeight = mHeight;
return NS_OK;
}
@ -1311,6 +1441,8 @@ NS_IMETHODIMP
WebGLContext::GetSupportedExtensions(nsIVariant **retval)
{
*retval = nsnull;
if (mContextLost)
return NS_OK;
if (mDisableExtensions) {
return NS_OK;
@ -1343,7 +1475,7 @@ WebGLContext::GetSupportedExtensions(nsIVariant **retval)
NS_IMETHODIMP
WebGLContext::IsContextLost(WebGLboolean *retval)
{
*retval = false;
*retval = mContextLost;
return NS_OK;
}

Просмотреть файл

@ -339,9 +339,11 @@ struct WebGLContextOptions {
class WebGLContext :
public nsIDOMWebGLRenderingContext,
public nsICanvasRenderingContextInternal,
public nsSupportsWeakReference
public nsSupportsWeakReference,
public nsITimerCallback
{
friend class WebGLMemoryReporter;
friend class WebGLExtensionLoseContext;
public:
WebGLContext();
@ -353,6 +355,8 @@ public:
NS_DECL_NSIDOMWEBGLRENDERINGCONTEXT
NS_DECL_NSITIMERCALLBACK
// nsICanvasRenderingContextInternal
NS_IMETHOD SetCanvasElement(nsHTMLCanvasElement* aParentCanvas);
NS_IMETHOD SetDimensions(PRInt32 width, PRInt32 height);
@ -380,6 +384,9 @@ public:
PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h)
{ return NS_ERROR_NOT_IMPLEMENTED; }
bool LoseContext();
bool RestoreContext();
nsresult SynthesizeGLError(WebGLenum err);
nsresult SynthesizeGLError(WebGLenum err, const char *fmt, ...);
@ -438,6 +445,22 @@ public:
return mMinCapability;
}
// Sets up the GL_ARB_robustness timer if it isn't already, so that if the
// driver gets restarted, the context may get reset with it.
void SetupRobustnessTimer() {
if (mContextLost)
return;
if (!mContextRestorer)
mContextRestorer = do_CreateInstance("@mozilla.org/timer;1");
// As long as there's still activity, we reset the timer each time that
// this function gets called.
mContextRestorer->InitWithCallback(static_cast<nsITimerCallback*>(this),
PR_MillisecondsToInterval(1000),
nsITimer::TYPE_ONE_SHOT);
}
protected:
void SetDontKnowIfNeedFakeBlack() {
mFakeBlackStatus = DontKnowIfNeedFakeBlack;
@ -502,6 +525,7 @@ protected:
enum WebGLExtensionID {
WebGL_OES_texture_float,
WebGL_OES_standard_derivatives,
WebGL_WEBKIT_lose_context,
WebGLExtensionID_Max
};
nsCOMPtr<WebGLExtension> mEnabledExtensions[WebGLExtensionID_Max];
@ -633,6 +657,10 @@ protected:
GLenum type,
const GLvoid *data);
void MaybeRestoreContext();
void ForceLoseContext();
void ForceRestoreContext();
// the buffers bound to the current program's attribs
nsTArray<WebGLVertexAttribData> mAttribBuffers;
@ -691,6 +719,10 @@ protected:
int mBackbufferClearingStatus;
nsCOMPtr<nsITimer> mContextRestorer;
bool mContextLost;
bool mAllowRestore;
public:
// console logging helpers
static void LogMessage(const char *fmt, ...);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -53,3 +53,4 @@ DOMCI_DATA(WebGLRenderbuffer, void)
DOMCI_DATA(WebGLUniformLocation, void)
DOMCI_DATA(WebGLActiveInfo, void)
DOMCI_DATA(WebGLExtension, void)
DOMCI_DATA(WebGLExtensionLoseContext, void)

Просмотреть файл

@ -0,0 +1,76 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Doug Sherk <dsherk@mozilla.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include <stdarg.h>
#include "WebGLContext.h"
#include "WebGLExtensions.h"
#include "nsContentUtils.h"
#include "mozilla/Preferences.h"
using namespace mozilla;
WebGLExtensionLoseContext::WebGLExtensionLoseContext(WebGLContext* context) :
WebGLExtension(context)
{
}
WebGLExtensionLoseContext::~WebGLExtensionLoseContext()
{
}
NS_IMETHODIMP
WebGLExtensionLoseContext::LoseContext()
{
if (!mContext->LoseContext())
return mContext->mWebGLError = LOCAL_GL_INVALID_OPERATION;
return NS_OK;
}
NS_IMETHODIMP
WebGLExtensionLoseContext::RestoreContext()
{
if (!mContext->RestoreContext())
return mContext->mWebGLError = LOCAL_GL_INVALID_OPERATION;
return NS_OK;
}

Просмотреть файл

@ -41,8 +41,27 @@
namespace mozilla {
class WebGLExtensionLoseContext;
class WebGLExtensionStandardDerivatives;
#define WEBGLEXTENSIONLOSECONTEXT_PRIVATE_IID \
{0xb0afc2eb, 0x0895, 0x4509, {0x98, 0xde, 0x5c, 0x38, 0x3d, 0x16, 0x06, 0x94}}
class WebGLExtensionLoseContext :
public nsIWebGLExtensionLoseContext,
public WebGLExtension
{
public:
WebGLExtensionLoseContext(WebGLContext*);
virtual ~WebGLExtensionLoseContext();
NS_DECL_ISUPPORTS
NS_DECL_NSIWEBGLEXTENSIONLOSECONTEXT
NS_DECLARE_STATIC_IID_ACCESSOR(WEBGLEXTENSIONLOSECONTEXT_PRIVATE_IID)
};
NS_DEFINE_STATIC_IID_ACCESSOR(WebGLExtensionLoseContext, WEBGLACTIVEINFO_PRIVATE_IID)
#define WEBGLEXTENSIONSTANDARDDERIVATIVES_PRIVATE_IID \
{0x3de3dfd9, 0x864a, 0x4e4c, {0x98, 0x9b, 0x29, 0x77, 0xea, 0xa8, 0x0b, 0x7b}}
class WebGLExtensionStandardDerivatives :

Просмотреть файл

@ -45,21 +45,27 @@
#include "WebGLContext.h"
#if defined _MSC_VER
#define FORCE_INLINE __forceinline
#elif defined __GNUC__
#define FORCE_INLINE __attribute__((always_inline)) inline
#else
#define FORCE_INLINE inline
#endif
namespace mozilla {
typedef PRUint8 uint8_t;
typedef PRUint16 uint16_t;
namespace { // this is only included by WebGLContextGL.cpp anyway
namespace WebGLTexelConversions {
/****** BEGIN CODE TAKEN FROM WEBKIT ******/
/****** BEGIN CODE SHARED WITH WEBKIT ******/
//----------------------------------------------------------------------
// Pixel unpacking routines.
void unpackRGBA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
FORCE_INLINE void unpackRGBA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
{
destination[0] = source[0];
destination[1] = source[1];
@ -67,7 +73,7 @@ void unpackRGBA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict de
destination[3] = source[3];
}
void unpackRGB8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
FORCE_INLINE void unpackRGB8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
{
destination[0] = source[0];
destination[1] = source[1];
@ -75,7 +81,7 @@ void unpackRGB8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict des
destination[3] = 0xFF;
}
void unpackBGRA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
FORCE_INLINE void unpackBGRA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
{
destination[0] = source[2];
destination[1] = source[1];
@ -83,7 +89,7 @@ void unpackBGRA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict de
destination[3] = source[3];
}
void unpackBGR8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
FORCE_INLINE void unpackBGR8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
{
destination[0] = source[2];
destination[1] = source[1];
@ -91,7 +97,7 @@ void unpackBGR8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict des
destination[3] = 0xFF;
}
void unpackRGBA5551ToRGBA8(const uint16_t* __restrict source, uint8_t* __restrict destination)
FORCE_INLINE void unpackRGBA5551ToRGBA8(const uint16_t* __restrict source, uint8_t* __restrict destination)
{
uint16_t packedValue = source[0];
uint8_t r = packedValue >> 11;
@ -103,7 +109,7 @@ void unpackRGBA5551ToRGBA8(const uint16_t* __restrict source, uint8_t* __restric
destination[3] = (packedValue & 0x1) ? 0xFF : 0x0;
}
void unpackRGBA4444ToRGBA8(const uint16_t* __restrict source, uint8_t* __restrict destination)
FORCE_INLINE void unpackRGBA4444ToRGBA8(const uint16_t* __restrict source, uint8_t* __restrict destination)
{
uint16_t packedValue = source[0];
uint8_t r = packedValue >> 12;
@ -116,7 +122,7 @@ void unpackRGBA4444ToRGBA8(const uint16_t* __restrict source, uint8_t* __restric
destination[3] = a << 4 | a;
}
void unpackRGB565ToRGBA8(const uint16_t* __restrict source, uint8_t* __restrict destination)
FORCE_INLINE void unpackRGB565ToRGBA8(const uint16_t* __restrict source, uint8_t* __restrict destination)
{
uint16_t packedValue = source[0];
uint8_t r = packedValue >> 11;
@ -128,7 +134,7 @@ void unpackRGB565ToRGBA8(const uint16_t* __restrict source, uint8_t* __restrict
destination[3] = 0xFF;
}
void unpackR8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
FORCE_INLINE void unpackR8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
{
destination[0] = source[0];
destination[1] = source[0];
@ -136,7 +142,7 @@ void unpackR8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict desti
destination[3] = 0xFF;
}
void unpackRA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
FORCE_INLINE void unpackRA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
{
destination[0] = source[0];
destination[1] = source[0];
@ -144,7 +150,7 @@ void unpackRA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict dest
destination[3] = source[1];
}
void unpackA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
FORCE_INLINE void unpackA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
{
destination[0] = 0x0;
destination[1] = 0x0;
@ -152,7 +158,7 @@ void unpackA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict desti
destination[3] = source[0];
}
void unpackRGB32FToRGBA32F(const float* __restrict source, float* __restrict destination)
FORCE_INLINE void unpackRGB32FToRGBA32F(const float* __restrict source, float* __restrict destination)
{
destination[0] = source[0];
destination[1] = source[1];
@ -160,7 +166,7 @@ void unpackRGB32FToRGBA32F(const float* __restrict source, float* __restrict des
destination[3] = 1;
}
void unpackR32FToRGBA32F(const float* __restrict source, float* __restrict destination)
FORCE_INLINE void unpackR32FToRGBA32F(const float* __restrict source, float* __restrict destination)
{
destination[0] = source[0];
destination[1] = source[0];
@ -168,7 +174,7 @@ void unpackR32FToRGBA32F(const float* __restrict source, float* __restrict desti
destination[3] = 1;
}
void unpackRA32FToRGBA32F(const float* __restrict source, float* __restrict destination)
FORCE_INLINE void unpackRA32FToRGBA32F(const float* __restrict source, float* __restrict destination)
{
destination[0] = source[0];
destination[1] = source[0];
@ -176,7 +182,7 @@ void unpackRA32FToRGBA32F(const float* __restrict source, float* __restrict dest
destination[3] = source[1];
}
void unpackA32FToRGBA32F(const float* __restrict source, float* __restrict destination)
FORCE_INLINE void unpackA32FToRGBA32F(const float* __restrict source, float* __restrict destination)
{
destination[0] = 0;
destination[1] = 0;
@ -188,17 +194,17 @@ void unpackA32FToRGBA32F(const float* __restrict source, float* __restrict desti
// Pixel packing routines.
//
void packRGBA8ToA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
FORCE_INLINE void packRGBA8ToA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
{
destination[0] = source[3];
}
void packRGBA8ToR8(const uint8_t* __restrict source, uint8_t* __restrict destination)
FORCE_INLINE void packRGBA8ToR8(const uint8_t* __restrict source, uint8_t* __restrict destination)
{
destination[0] = source[0];
}
void packRGBA8ToR8Premultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
FORCE_INLINE void packRGBA8ToR8Premultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
{
float scaleFactor = source[3] / 255.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
@ -206,20 +212,20 @@ void packRGBA8ToR8Premultiply(const uint8_t* __restrict source, uint8_t* __restr
}
// FIXME: this routine is lossy and must be removed.
void packRGBA8ToR8Unmultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
FORCE_INLINE void packRGBA8ToR8Unmultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
{
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
destination[0] = sourceR;
}
void packRGBA8ToRA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
FORCE_INLINE void packRGBA8ToRA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
{
destination[0] = source[0];
destination[1] = source[3];
}
void packRGBA8ToRA8Premultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
FORCE_INLINE void packRGBA8ToRA8Premultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
{
float scaleFactor = source[3] / 255.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
@ -228,7 +234,7 @@ void packRGBA8ToRA8Premultiply(const uint8_t* __restrict source, uint8_t* __rest
}
// FIXME: this routine is lossy and must be removed.
void packRGBA8ToRA8Unmultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
FORCE_INLINE void packRGBA8ToRA8Unmultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
{
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
@ -236,14 +242,14 @@ void packRGBA8ToRA8Unmultiply(const uint8_t* __restrict source, uint8_t* __restr
destination[1] = source[3];
}
void packRGBA8ToRGB8(const uint8_t* __restrict source, uint8_t* __restrict destination)
FORCE_INLINE void packRGBA8ToRGB8(const uint8_t* __restrict source, uint8_t* __restrict destination)
{
destination[0] = source[0];
destination[1] = source[1];
destination[2] = source[2];
}
void packRGBA8ToRGB8Premultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
FORCE_INLINE void packRGBA8ToRGB8Premultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
{
float scaleFactor = source[3] / 255.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
@ -255,7 +261,7 @@ void packRGBA8ToRGB8Premultiply(const uint8_t* __restrict source, uint8_t* __res
}
// FIXME: this routine is lossy and must be removed.
void packRGBA8ToRGB8Unmultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
FORCE_INLINE void packRGBA8ToRGB8Unmultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
{
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
@ -267,7 +273,7 @@ void packRGBA8ToRGB8Unmultiply(const uint8_t* __restrict source, uint8_t* __rest
}
// This is only used when the source format is different than kSourceFormatRGBA8.
void packRGBA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
FORCE_INLINE void packRGBA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
{
destination[0] = source[0];
destination[1] = source[1];
@ -275,7 +281,7 @@ void packRGBA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict dest
destination[3] = source[3];
}
void packRGBA8ToRGBA8Premultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
FORCE_INLINE void packRGBA8ToRGBA8Premultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
{
float scaleFactor = source[3] / 255.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
@ -288,7 +294,7 @@ void packRGBA8ToRGBA8Premultiply(const uint8_t* __restrict source, uint8_t* __re
}
// FIXME: this routine is lossy and must be removed.
void packRGBA8ToRGBA8Unmultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
FORCE_INLINE void packRGBA8ToRGBA8Unmultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
{
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
@ -300,7 +306,7 @@ void packRGBA8ToRGBA8Unmultiply(const uint8_t* __restrict source, uint8_t* __res
destination[3] = source[3];
}
void packRGBA8ToUnsignedShort4444(const uint8_t* __restrict source, uint16_t* __restrict destination)
FORCE_INLINE void packRGBA8ToUnsignedShort4444(const uint8_t* __restrict source, uint16_t* __restrict destination)
{
*destination = (((source[0] & 0xF0) << 8)
| ((source[1] & 0xF0) << 4)
@ -308,7 +314,7 @@ void packRGBA8ToUnsignedShort4444(const uint8_t* __restrict source, uint16_t* __
| (source[3] >> 4));
}
void packRGBA8ToUnsignedShort4444Premultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
FORCE_INLINE void packRGBA8ToUnsignedShort4444Premultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
{
float scaleFactor = source[3] / 255.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
@ -321,7 +327,7 @@ void packRGBA8ToUnsignedShort4444Premultiply(const uint8_t* __restrict source, u
}
// FIXME: this routine is lossy and must be removed.
void packRGBA8ToUnsignedShort4444Unmultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
FORCE_INLINE void packRGBA8ToUnsignedShort4444Unmultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
{
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
@ -333,7 +339,7 @@ void packRGBA8ToUnsignedShort4444Unmultiply(const uint8_t* __restrict source, ui
| (source[3] >> 4));
}
void packRGBA8ToUnsignedShort5551(const uint8_t* __restrict source, uint16_t* __restrict destination)
FORCE_INLINE void packRGBA8ToUnsignedShort5551(const uint8_t* __restrict source, uint16_t* __restrict destination)
{
*destination = (((source[0] & 0xF8) << 8)
| ((source[1] & 0xF8) << 3)
@ -341,7 +347,7 @@ void packRGBA8ToUnsignedShort5551(const uint8_t* __restrict source, uint16_t* __
| (source[3] >> 7));
}
void packRGBA8ToUnsignedShort5551Premultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
FORCE_INLINE void packRGBA8ToUnsignedShort5551Premultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
{
float scaleFactor = source[3] / 255.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
@ -354,7 +360,7 @@ void packRGBA8ToUnsignedShort5551Premultiply(const uint8_t* __restrict source, u
}
// FIXME: this routine is lossy and must be removed.
void packRGBA8ToUnsignedShort5551Unmultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
FORCE_INLINE void packRGBA8ToUnsignedShort5551Unmultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
{
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
@ -366,14 +372,14 @@ void packRGBA8ToUnsignedShort5551Unmultiply(const uint8_t* __restrict source, ui
| (source[3] >> 7));
}
void packRGBA8ToUnsignedShort565(const uint8_t* __restrict source, uint16_t* __restrict destination)
FORCE_INLINE void packRGBA8ToUnsignedShort565(const uint8_t* __restrict source, uint16_t* __restrict destination)
{
*destination = (((source[0] & 0xF8) << 8)
| ((source[1] & 0xFC) << 3)
| ((source[2] & 0xF8) >> 3));
}
void packRGBA8ToUnsignedShort565Premultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
FORCE_INLINE void packRGBA8ToUnsignedShort565Premultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
{
float scaleFactor = source[3] / 255.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
@ -385,7 +391,7 @@ void packRGBA8ToUnsignedShort565Premultiply(const uint8_t* __restrict source, ui
}
// FIXME: this routine is lossy and must be removed.
void packRGBA8ToUnsignedShort565Unmultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
FORCE_INLINE void packRGBA8ToUnsignedShort565Unmultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
{
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
@ -396,14 +402,14 @@ void packRGBA8ToUnsignedShort565Unmultiply(const uint8_t* __restrict source, uin
| ((sourceB & 0xF8) >> 3));
}
void packRGBA32FToRGB32F(const float* __restrict source, float* __restrict destination)
FORCE_INLINE void packRGBA32FToRGB32F(const float* __restrict source, float* __restrict destination)
{
destination[0] = source[0];
destination[1] = source[1];
destination[2] = source[2];
}
void packRGBA32FToRGB32FPremultiply(const float* __restrict source, float* __restrict destination)
FORCE_INLINE void packRGBA32FToRGB32FPremultiply(const float* __restrict source, float* __restrict destination)
{
float scaleFactor = source[3];
destination[0] = source[0] * scaleFactor;
@ -411,7 +417,7 @@ void packRGBA32FToRGB32FPremultiply(const float* __restrict source, float* __res
destination[2] = source[2] * scaleFactor;
}
void packRGBA32FToRGBA32FPremultiply(const float* __restrict source, float* __restrict destination)
FORCE_INLINE void packRGBA32FToRGBA32FPremultiply(const float* __restrict source, float* __restrict destination)
{
float scaleFactor = source[3];
destination[0] = source[0] * scaleFactor;
@ -420,48 +426,46 @@ void packRGBA32FToRGBA32FPremultiply(const float* __restrict source, float* __re
destination[3] = source[3];
}
void packRGBA32FToA32F(const float* __restrict source, float* __restrict destination)
FORCE_INLINE void packRGBA32FToA32F(const float* __restrict source, float* __restrict destination)
{
destination[0] = source[3];
}
// identical to above, to avoid special-casing
void packRGBA32FToA32FPremultiply(const float* __restrict source, float* __restrict destination)
FORCE_INLINE void packRGBA32FToA32FPremultiply(const float* __restrict source, float* __restrict destination)
{
destination[0] = source[3];
}
void packRGBA32FToR32F(const float* __restrict source, float* __restrict destination)
FORCE_INLINE void packRGBA32FToR32F(const float* __restrict source, float* __restrict destination)
{
destination[0] = source[0];
}
void packRGBA32FToR32FPremultiply(const float* __restrict source, float* __restrict destination)
FORCE_INLINE void packRGBA32FToR32FPremultiply(const float* __restrict source, float* __restrict destination)
{
float scaleFactor = source[3];
destination[0] = source[0] * scaleFactor;
}
void packRGBA32FToRA32F(const float* __restrict source, float* __restrict destination)
FORCE_INLINE void packRGBA32FToRA32F(const float* __restrict source, float* __restrict destination)
{
destination[0] = source[0];
destination[1] = source[3];
}
void packRGBA32FToRA32FPremultiply(const float* __restrict source, float* __restrict destination)
FORCE_INLINE void packRGBA32FToRA32FPremultiply(const float* __restrict source, float* __restrict destination)
{
float scaleFactor = source[3];
destination[0] = source[0] * scaleFactor;
destination[1] = scaleFactor;
}
/****** END CODE TAKEN FROM WEBKIT ******/
/****** END CODE SHARED WITH WEBKIT ******/
} // end namespace WebGLTexelConversions
} // end anonymous namespace
} // end namespace mozilla
#endif // WEBGLTEXELCONVERSIONS_H_

Просмотреть файл

@ -1442,10 +1442,7 @@ IsAccessKeyTarget(nsIContent* aContent, nsIFrame* aFrame, nsAString& aKey)
if (aFrame->IsFocusable())
return true;
if (!aFrame->GetStyleVisibility()->IsVisible())
return false;
if (!aFrame->AreAncestorViewsVisible())
if (!aFrame->IsVisibleConsideringAncestors())
return false;
// XUL controls can be activated.

Просмотреть файл

@ -282,6 +282,17 @@ nsHTMLSharedObjectElement::BindToTree(nsIDocument *aDocument,
nsContentUtils::AddScriptRunner(NS_NewRunnableMethod(this, start));
}
#ifndef XP_MACOSX
if (aDocument &&
aDocument->IsFullScreenDoc() &&
nsContentUtils::HasPluginWithUncontrolledEventDispatch(this)) {
// This content contains a windowed plugin for which we don't control
// event dispatch, and we're in full-screen mode. Exit full-screen mode
// to prevent phishing attacks.
NS_DispatchToCurrentThread(
NS_NewRunnableMethod(aDocument, &nsIDocument::CancelFullScreen));
}
#endif
return NS_OK;
}

Просмотреть файл

@ -281,6 +281,7 @@ _TEST_FILES = \
file_fullscreen-api.html \
file_fullscreen-api-keys.html \
test_fullscreen-api.html \
file_fullscreen-plugins.html \
test_li_attributes_reflection.html \
test_ol_attributes_reflection.html \
test_bug651956.html \

Просмотреть файл

@ -0,0 +1,180 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=545812
Test plugins with DOM full-screen API:
* Presence of plugins has no effect on request for full-screen on MacOS.
* Request for full-screen is denied when windowed plugin in current doc is present.
* Request for full-screen is denied when windowed plugin in subdocument is present.
* Request for full-screen is not denied when the only plugin present is windowless.
* Adding an existing (out-of-doc) windowed plugin to a full-screen document causes document to exit full-screen.
* Create windowed plugin and adding it to full-screen document caused exit from full-screen.
-->
<head>
<title>Test for Bug 545812</title>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<style>
body:-moz-full-screen, div:-moz-full-screen {
background-color: red;
}
</style>
</head>
<body onload="scheduleTest();">
<!-- Windowed plugin, should prevent first full-screen request. -->
<embed id="windowed-plugin" type="application/x-test" style="width:200px;height:100px;" wmode="window"></embed>
<!-- Windowless plugin, should not prevent full-screen requests. -->
<embed type="application/x-test" style="width:200px;height:100px;"></embed>
<!-- iframe contents:
<html><body><embed id='windowed-plugin' type='application/x-test' style='width:200px;height:100px;' wmode='window'></embed></body></html>
-->
<iframe id="subdoc-plugin" src="data:text/html;charset=utf-8,<html><body><embed id%3D'windowed-plugin' type%3D'application%2Fx-test' style%3D'width%3A200px%3Bheight%3A100px%3B' wmode%3D'window'><%2Fembed><%2Fbody><%2Fhtml>%0D%0A"></iframe>
<script type="application/javascript">
/** Test for Bug 545812 **/
function ok(condition, msg) {
opener.ok(condition, msg);
}
function is(a, b, msg) {
opener.is(a, b, msg);
}
const isMacOs = navigator.appVersion.indexOf("Macintosh") != -1;
document.addEventListener("mozfullscreenchange", isMacOs ? macFullScreenChange : fullScreenChange, false);
var windowedPlugin = null;
function scheduleTest() {
// Delay test startup long enough for the windowed plugin in the subframe to
// start up and create its window.
opener.SimpleTest.executeSoon(function() {
opener.SimpleTest.executeSoon(function() {
startTest();
})
});
}
function startTest() {
ok(!document.mozFullScreen, "Should not be in full-screen mode initially");
document.body.mozRequestFullScreen();
if (isMacOs) {
// Running on MacOS, all plugins are effectively windowless, request for full-screen should be granted.
// Continue test in the (mac-specific) "mozfullscreenchange" handler.
return;
}
ok(!document.mozFullScreen, "Request for full-screen from a document containing windowed plugin should be denied.");
// Remove plugin in this document. Should still be a windowed plugin in sub-document.
windowedPlugin = document.getElementById("windowed-plugin");
windowedPlugin.parentNode.removeChild(windowedPlugin);
document.body.mozRequestFullScreen();
ok(!document.mozFullScreen, "Request for full-screen from a document with subdocument containing windowed plugin should be denied.");
// Remove subdoc which contains windowed plugin, request full-screen, request should be granted.
// Continue test in "mozfullscreenchange" handler.
var f = document.getElementById("subdoc-plugin");
f.parentNode.removeChild(f);
document.body.mozRequestFullScreen();
}
var fullScreenChangeCount = 0;
function createWindowedPlugin() {
var p = document.createElement("embed");
p.setAttribute("type", "application/x-test");
p.setAttribute("wmode", "window");
return p;
}
function macFullScreenChange(event) {
switch (fullScreenChangeCount) {
case 0: {
ok(document.mozFullScreen, "Requests for full-screen on pages with plugins should be granted on MacOS");
// Create a new windowed plugin, and add that to the document. Should *not* exit full-screen mode on MacOS.
windowedPlugin = createWindowedPlugin();
document.body.appendChild(windowedPlugin);
setTimeout(
function() {
ok(document.mozFullScreen, "Adding windowed plugin to document should not cause full-screen to exit on MacOS.");
document.mozCancelFullScreen();
}, 0);
break;
}
case 1: {
ok(!document.mozFullScreen, "Should have left full-screen mode after calling document.mozCancelFullScreen().");
opener.pluginTestFinished();
break;
}
default: {
ok(false, "Should not receive any more fullscreenchange events!");
}
}
fullScreenChangeCount++;
}
function fullScreenChange(event) {
switch (fullScreenChangeCount) {
case 0: {
ok(document.mozFullScreen, "Request for full-screen with document containing windowless plugin should be granted");
// Add windowed plugin to document, should cause full-screen mode to exit.
document.body.appendChild(windowedPlugin);
break;
}
case 1: {
ok(!document.mozFullScreen, "Should have left full-screen mode after re-adding windowed plugin to document");
windowedPlugin.parentNode.removeChild(windowedPlugin);
document.body.mozRequestFullScreen();
break;
}
case 2: {
ok(document.mozFullScreen, "Should have reentered full-screen mode");
// Create a new windowed plugin, and add that to the document. Should exit full-screen mode.
windowedPlugin = createWindowedPlugin();
document.body.appendChild(windowedPlugin);
break;
}
case 3: {
ok(!document.mozFullScreen, "Should have left full-screen mode after adding windowed plugin created after going full-screen to document");
windowedPlugin.parentNode.removeChild(windowedPlugin);
windowedPlugin = createWindowedPlugin();
document.body.mozRequestFullScreen();
break;
}
case 4: {
ok(document.mozFullScreen, "Should have (again) reentered full-screen mode");
document.body.appendChild(windowedPlugin);
break;
}
case 5: {
ok(!document.mozFullScreen, "Should have left full-screen mode after adding windowed plugin created before going full-screen to document");
opener.pluginTestFinished();
break;
}
default: {
ok(false, "Should not receive any more fullscreenchange events!");
}
}
fullScreenChangeCount++;
}
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -86,6 +86,11 @@ function apiTestFinished() {
}
function keysTestFinished() {
testWindow.close();
testWindow = window.open("file_fullscreen-plugins.html", "", "width=500,height=500");
}
function pluginTestFinished() {
testWindow.close();
SpecialPowers.setBoolPref("full-screen-api.enabled", prevEnabled);
SpecialPowers.setBoolPref("full-screen-api.allow-trusted-requests-only", prevTrusted);

Просмотреть файл

@ -656,14 +656,7 @@ nsXULElement::PerformAccesskey(bool aKeyCausesActivation,
}
nsIFrame* frame = content->GetPrimaryFrame();
if (!frame)
return;
const nsStyleVisibility* vis = frame->GetStyleVisibility();
if (vis->mVisible == NS_STYLE_VISIBILITY_COLLAPSE ||
vis->mVisible == NS_STYLE_VISIBILITY_HIDDEN ||
!frame->AreAncestorViewsVisible())
if (!frame || !frame->IsVisibleConsideringAncestors())
return;
nsXULElement* elm = FromContent(content);

Просмотреть файл

@ -4821,8 +4821,11 @@ nsDocShell::GetVisibility(bool * aVisibility)
nsIFrame* frame = shellContent ? shellContent->GetPrimaryFrame() : nsnull;
bool isDocShellOffScreen = false;
docShell->GetIsOffScreenBrowser(&isDocShellOffScreen);
if (frame && !frame->AreAncestorViewsVisible() && !isDocShellOffScreen)
if (frame &&
!frame->IsVisibleConsideringAncestors(nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY) &&
!isDocShellOffScreen) {
return NS_OK;
}
treeItem = parentItem;
treeItem->GetParent(getter_AddRefs(parentItem));

Просмотреть файл

@ -1450,6 +1450,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(WebGLExtensionStandardDerivatives, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(WebGLExtensionLoseContext, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(PaintRequest, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
@ -3986,6 +3988,10 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtensionStandardDerivatives)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(WebGLExtensionLoseContext, nsIWebGLExtensionLoseContext)
DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtensionLoseContext)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(PaintRequest, nsIDOMPaintRequest)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMPaintRequest)
DOM_CLASSINFO_MAP_END

Просмотреть файл

@ -472,6 +472,7 @@ DOMCI_CLASS(WebGLUniformLocation)
DOMCI_CLASS(WebGLActiveInfo)
DOMCI_CLASS(WebGLExtension)
DOMCI_CLASS(WebGLExtensionStandardDerivatives)
DOMCI_CLASS(WebGLExtensionLoseContext)
DOMCI_CLASS(PaintRequest)
DOMCI_CLASS(PaintRequestList)

Просмотреть файл

@ -1442,8 +1442,7 @@ nsFocusManager::CheckIfFocusable(nsIContent* aContent, PRUint32 aFlags)
// HTML areas do not have their own frame, and the img frame we get from
// GetPrimaryFrame() is not relevant as to whether it is focusable or
// not, so we have to do all the relevant checks manually for them.
return frame->AreAncestorViewsVisible() &&
frame->GetStyleVisibility()->IsVisible() &&
return frame->IsVisibleConsideringAncestors() &&
aContent->IsFocusable() ? aContent : nsnull;
}

Просмотреть файл

@ -153,6 +153,12 @@ interface nsIWebGLExtensionStandardDerivatives : nsIWebGLExtension
const WebGLenum FRAGMENT_SHADER_DERIVATIVE_HINT_OES = 0x8B8B;
};
[scriptable, uuid(b0afc2eb-0895-4509-98de-5c383d160694)]
interface nsIWebGLExtensionLoseContext : nsIWebGLExtension
{
void loseContext();
void restoreContext();
};
[scriptable, builtinclass, uuid(ef15ae85-4670-4dc4-848d-51ca81e8397a)]
interface nsIDOMWebGLRenderingContext : nsISupports

Просмотреть файл

@ -3277,7 +3277,13 @@ NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void)
if (!mWidget) {
bool windowless = false;
mInstance->IsWindowless(&windowless);
nsIDocument *doc = mContent ? mContent->OwnerDoc() : nsnull;
#ifndef XP_MACOSX
if (!windowless && doc && doc->IsFullScreenDoc()) {
NS_DispatchToCurrentThread(
NS_NewRunnableMethod(doc, &nsIDocument::CancelFullScreen));
}
#endif
// always create widgets in Twips, not pixels
nsPresContext* context = mObjectFrame->PresContext();
rv = mObjectFrame->CreateWidget(context->DevPixelsToAppUnits(mPluginWindow->width),

Просмотреть файл

@ -1111,7 +1111,7 @@ BasicCanvasLayer::UpdateSurface(gfxASurface* aDestSurface)
mGLContext->MakeCurrent();
#if defined (MOZ_X11) && defined (MOZ_EGL_XRENDER_COMPOSITE)
mGLContext->Finish();
mGLContext->fFinish();
gfxASurface* offscreenSurface = mGLContext->GetOffscreenPixmapSurface();
// XRender can only blend premuliplied alpha, so only allow xrender

Просмотреть файл

@ -174,6 +174,8 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
return true;
}
mHasRobustness = IsExtensionSupported(ARB_robustness);
SymLoadStruct symbols[] = {
{ (PRFuncPtr*) &mSymbols.fActiveTexture, { "ActiveTexture", "ActiveTextureARB", NULL } },
{ (PRFuncPtr*) &mSymbols.fAttachShader, { "AttachShader", "AttachShaderARB", NULL } },
@ -325,6 +327,9 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
{ mIsGLES2 ? (PRFuncPtr*) NULL : (PRFuncPtr*) &mSymbols.fUnmapBuffer,
{ mIsGLES2 ? NULL : "UnmapBuffer", NULL } },
{ mHasRobustness ? (PRFuncPtr*) &mSymbols.fGetGraphicsResetStatus : (PRFuncPtr*) NULL,
{ mHasRobustness ? "GetGraphicsResetStatusARB" : NULL, NULL } },
{ NULL, { NULL } },
};
@ -470,6 +475,7 @@ static const char *sExtensionNames[] = {
"GL_EXT_framebuffer_multisample",
"GL_ANGLE_framebuffer_multisample",
"GL_OES_rgb8_rgba8",
"GL_ARB_robustness",
NULL
};

Просмотреть файл

@ -532,7 +532,8 @@ public:
GLContext(const ContextFormat& aFormat,
bool aIsOffscreen = false,
GLContext *aSharedContext = nsnull)
: mInitialized(false),
: mOffscreenFBOsDirty(false),
mInitialized(false),
mIsOffscreen(aIsOffscreen),
#ifdef USE_GLES2
mIsGLES2(true),
@ -550,7 +551,6 @@ public:
mBlitFramebuffer(0),
mOffscreenDrawFBO(0),
mOffscreenReadFBO(0),
mOffscreenFBOsDirty(false),
mOffscreenColorRB(0),
mOffscreenDepthRB(0),
mOffscreenStencilRB(0)
@ -1242,6 +1242,7 @@ public:
EXT_framebuffer_multisample,
ANGLE_framebuffer_multisample,
OES_rgb8_rgba8,
ARB_robustness,
Extensions_Max
};
@ -1278,11 +1279,24 @@ public:
bool values[setlen];
};
/**
* Context reset constants.
* These are used to determine who is guilty when a context reset
* happens.
*/
enum ContextResetARB {
CONTEXT_NO_ERROR = 0,
CONTEXT_GUILTY_CONTEXT_RESET_ARB = 0x8253,
CONTEXT_INNOCENT_CONTEXT_RESET_ARB = 0x8254,
CONTEXT_UNKNOWN_CONTEXT_RESET_ARB = 0x8255,
};
protected:
bool mInitialized;
bool mIsOffscreen;
bool mIsGLES2;
bool mIsGlobalSharedContext;
bool mHasRobustness;
PRInt32 mVendor;
@ -2498,6 +2512,14 @@ public:
AFTER_GL_CALL;
TRACKING_CONTEXT(DeletedRenderbuffers(this, n, names));
}
GLenum GLAPIENTRY fGetGraphicsResetStatus() {
BEFORE_GL_CALL;
GLenum ret = mHasRobustness ? mSymbols.fGetGraphicsResetStatus() : 0;
AFTER_GL_CALL;
return ret;
}
#ifdef DEBUG
void THEBES_API CreatedProgram(GLContext *aOrigin, GLuint aName);
void THEBES_API CreatedShader(GLContext *aOrigin, GLuint aName);

Просмотреть файл

@ -581,8 +581,6 @@ GLContextProviderCGL::CreateOffscreen(const gfxIntSize& aSize,
glContext->mOffscreenSize = aSize;
glContext->mOffscreenActualSize = aSize;
printf("GL Offscreen: CGL+PBuffer\n");
return glContext.forget();
}
}

Просмотреть файл

@ -2251,38 +2251,32 @@ GLContextProviderEGL::CreateOffscreen(const gfxIntSize& aSize,
if (!sEGLLibrary.EnsureInitialized()) {
return nsnull;
}
ContextFormat actualFormat(aFormat);
// actualFormat.samples = 0;
#if defined(ANDROID) || defined(XP_WIN)
nsRefPtr<GLContextEGL> glContext =
GLContextEGL::CreateEGLPBufferOffscreenContext(aSize, actualFormat);
GLContextEGL::CreateEGLPBufferOffscreenContext(aSize, aFormat);
if (!glContext)
return nsnull;
if (!glContext->ResizeOffscreenFBO(glContext->OffscreenActualSize(), false))
return nsnull;
printf("GL Offscreen: EGL+PBuffer\n");
return glContext.forget();
return glContext.forget();
#elif defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE)
nsRefPtr<GLContextEGL> glContext =
GLContextEGL::CreateBasicEGLPixmapOffscreenContext(aSize, actualFormat);
GLContextEGL::CreateBasicEGLPixmapOffscreenContext(aSize, aFormat);
if (!glContext)
return nsnull;
if (!glContext->ResizeOffscreenFBO(glContext->OffscreenActualSize(), true))
return nsnull;
printf("GL Offscreen: EGL+Pixmap\n");
return glContext.forget();
#elif defined(MOZ_X11)
nsRefPtr<GLContextEGL> glContext =
GLContextEGL::CreateEGLPixmapOffscreenContext(aSize, actualFormat, true);
GLContextEGL::CreateEGLPixmapOffscreenContext(aSize, aFormat, true);
if (!glContext) {
return nsnull;

Просмотреть файл

@ -183,6 +183,11 @@ GLXLibrary::EnsureInitialized()
{ NULL, { NULL } }
};
LibrarySymbolLoader::SymLoadStruct symbols_robustness[] = {
{ (PRFuncPtr*) &xCreateContextAttribsInternal, { "glXCreateContextAttribsARB", NULL } },
{ NULL, { NULL } }
};
if (!LibrarySymbolLoader::LoadSymbols(mOGLLibrary, &symbols[0])) {
NS_WARNING("Couldn't find required entry point in OpenGL shared library");
return false;
@ -251,6 +256,17 @@ GLXLibrary::EnsureInitialized()
NS_WARNING("Texture from pixmap disabled");
}
if (HasExtension(extensionsStr, "GL_ARB_robustness")) {
if (!LibrarySymbolLoader::LoadSymbols(mOGLLibrary, symbols_robustness)) {
// We have no easy way of checking whether or not this extension
// exists, so it's best to just try to load it and accept that it
// might fail.
//NS_WARNING("Couldn't load ARB_robustness symbols");
} else {
mHasRobustness = true;
}
}
gIsATI = serverVendor && DoesVendorStringMatch(serverVendor, "ATI");
gIsChromium = (serverVendor &&
DoesVendorStringMatch(serverVendor, "Chromium")) ||
@ -633,6 +649,23 @@ GLXLibrary::xWaitX()
AFTER_GLX_CALL;
}
GLXContext
GLXLibrary::xCreateContextAttribs(Display* display,
GLXFBConfig config,
GLXContext share_list,
Bool direct,
const int* attrib_list)
{
BEFORE_GLX_CALL;
GLXContext result = xCreateContextAttribsInternal(display,
config,
share_list,
direct,
attrib_list);
AFTER_GLX_CALL;
return result;
}
GLXLibrary sGLXLibrary;
class GLContextGLX : public GLContext
@ -667,11 +700,25 @@ TRY_AGAIN_NO_SHARING:
error = false;
context = sGLXLibrary.xCreateNewContext(display,
cfg,
GLX_RGBA_TYPE,
shareContext ? shareContext->mContext : NULL,
True);
if (sGLXLibrary.HasRobustness()) {
int attrib_list[] = {
LOCAL_GL_CONTEXT_FLAGS_ARB, LOCAL_GL_CONTEXT_ROBUST_ACCESS_BIT_ARB,
LOCAL_GL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_GL_LOSE_CONTEXT_ON_RESET_ARB,
0,
};
context = sGLXLibrary.xCreateContextAttribs(display,
cfg,
shareContext ? shareContext->mContext : NULL,
True,
attrib_list);
} else {
context = sGLXLibrary.xCreateNewContext(display,
cfg,
GLX_RGBA_TYPE,
shareContext ? shareContext->mContext : NULL,
True);
}
if (context) {
glContext = new GLContextGLX(format,
@ -1241,11 +1288,8 @@ already_AddRefed<GLContext>
GLContextProviderGLX::CreateOffscreen(const gfxIntSize& aSize,
const ContextFormat& aFormat)
{
ContextFormat actualFormat(aFormat);
// actualFormat.samples = 0;
nsRefPtr<GLContextGLX> glContext =
CreateOffscreenPixmapContext(aSize, actualFormat, true);
CreateOffscreenPixmapContext(aSize, aFormat, true);
if (!glContext) {
return nsnull;

Просмотреть файл

@ -650,9 +650,6 @@ GLContextProviderWGL::CreateOffscreen(const gfxIntSize& aSize,
return nsnull;
}
ContextFormat actualFormat(aFormat);
// actualFormat.samples = 0;
nsRefPtr<GLContextWGL> glContext;
// Always try to create a pbuffer context first, because we
@ -663,12 +660,12 @@ GLContextProviderWGL::CreateOffscreen(const gfxIntSize& aSize,
sWGLLibrary.fCreatePbuffer &&
sWGLLibrary.fChoosePixelFormat)
{
glContext = CreatePBufferOffscreenContext(aSize, actualFormat);
glContext = CreatePBufferOffscreenContext(aSize, aFormat);
}
// If it failed, then create a window context and use a FBO.
if (!glContext) {
glContext = CreateWindowOffscreenContext(actualFormat);
glContext = CreateWindowOffscreenContext(aFormat);
}
if (!glContext ||

Просмотреть файл

@ -373,6 +373,8 @@ struct GLContextSymbols
typedef realGLboolean (GLAPIENTRY * PFNGLUNMAPBUFFER) (GLenum target);
PFNGLUNMAPBUFFER fUnmapBuffer;
typedef GLenum (GLAPIENTRY * PFNGLGETGRAPHICSRESETSTATUS) (void);
PFNGLGETGRAPHICSRESETSTATUS fGetGraphicsResetStatus;
};
}

Просмотреть файл

@ -178,6 +178,7 @@ typedef ptrdiff_t GLintptr;
#define LOCAL_GL_STACK_OVERFLOW 0x0503
#define LOCAL_GL_STACK_UNDERFLOW 0x0504
#define LOCAL_GL_OUT_OF_MEMORY 0x0505
#define LOCAL_GL_CONTEXT_LOST 0x9242
#define LOCAL_GL_2D 0x0600
#define LOCAL_GL_3D 0x0601
#define LOCAL_GL_3D_COLOR 0x0602
@ -3039,6 +3040,49 @@ typedef ptrdiff_t GLintptr;
#define LOCAL_GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
#define LOCAL_GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
#define LOCAL_GL_GUILTY_CONTEXT_RESET_ARB 0x8253
#define LOCAL_GL_INNOCENT_CONTEXT_RESET_ARB 0x8254
#define LOCAL_GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255
#define LOCAL_GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
#define LOCAL_GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
#define LOCAL_GL_NO_RESET_NOTIFICATION_ARB 0x8261
#define LOCAL_GL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
#define LOCAL_GL_NO_RESET_NOTIFICATION_ARB 0x8261
#define LOCAL_GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
#define LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
#define LOCAL_WGL_NO_RESET_NOTIFICATION_ARB 0x8261
#define LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
#define LOCAL_GL_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define LOCAL_GL_CONTEXT_MINOR_VERSION_ARB 0x2092
#define LOCAL_GL_CONTEXT_LAYER_PLANE_ARB 0x2093
#define LOCAL_GL_CONTEXT_FLAGS_ARB 0x2094
#define LOCAL_GL_CONTEXT_PROFILE_MASK_ARB 0x9126
#define LOCAL_WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define LOCAL_WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
#define LOCAL_WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
#define LOCAL_WGL_CONTEXT_FLAGS_ARB 0x2094
#define LOCAL_WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
#define LOCAL_GL_CONTEXT_DEBUG_BIT_ARB 0x0001
#define LOCAL_GL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
#define LOCAL_WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
#define LOCAL_WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
#define LOCAL_GL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
#define LOCAL_GL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
#define LOCAL_GL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
#define LOCAL_WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
#define LOCAL_WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
#define LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
#define LOCAL_WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
#define LOCAL_WGL_DRAW_TO_WINDOW_ARB 0x2001
#define LOCAL_WGL_DRAW_TO_BITMAP_ARB 0x2002

Просмотреть файл

@ -50,7 +50,7 @@ class GLXLibrary
public:
GLXLibrary() : mInitialized(false), mTriedInitializing(false),
mHasTextureFromPixmap(false), mDebug(false),
mOGLLibrary(nsnull) {}
mHasRobustness(false), mOGLLibrary(nsnull) {}
void xDestroyContext(Display* display, GLXContext context);
Bool xMakeCurrent(Display* display,
@ -108,6 +108,12 @@ public:
void xWaitGL();
void xWaitX();
GLXContext xCreateContextAttribs(Display* display,
GLXFBConfig config,
GLXContext share_list,
Bool direct,
const int* attrib_list);
bool EnsureInitialized();
GLXPixmap CreatePixmap(gfxASurface* aSurface);
@ -116,6 +122,7 @@ public:
void ReleaseTexImage(GLXPixmap aPixmap);
bool HasTextureFromPixmap() { return mHasTextureFromPixmap; }
bool HasRobustness() { return mHasRobustness; }
bool SupportsTextureFromPixmap(gfxASurface* aSurface);
private:
@ -209,6 +216,13 @@ private:
typedef void (GLAPIENTRY * PFNGLXWAITX) ();
PFNGLXWAITGL xWaitXInternal;
typedef GLXContext (GLAPIENTRY * PFNGLXCREATECONTEXTATTRIBS) (Display *,
GLXFBConfig,
GLXContext,
Bool,
const int *);
PFNGLXCREATECONTEXTATTRIBS xCreateContextAttribsInternal;
#ifdef DEBUG
void BeforeGLXCall();
void AfterGLXCall();
@ -218,6 +232,7 @@ private:
bool mTriedInitializing;
bool mHasTextureFromPixmap;
bool mDebug;
bool mHasRobustness;
PRLibrary *mOGLLibrary;
};

Просмотреть файл

@ -43,8 +43,7 @@ namespace JSC {
class MacroAssemblerARM : public AbstractMacroAssembler<ARMAssembler> {
static const int DoubleConditionMask = 0x0f;
static const int DoubleConditionBitSpecial = 0x10;
COMPILE_ASSERT(!(DoubleConditionBitSpecial & DoubleConditionMask), DoubleConditionBitSpecial_should_not_interfere_with_ARMAssembler_Condition_codes);
static const int DoubleConditionBitSpecial = 0x8;
public:
enum Condition {
Equal = ARMAssembler::EQ,

Просмотреть файл

@ -2723,6 +2723,11 @@ if test "$ac_cv_header_endian_h" = yes; then
AC_DEFINE(JS_HAVE_ENDIAN_H)
fi
AC_CHECK_HEADERS(sys/isa_defs.h)
if test "$ac_cv_header_sys_isa_defs_h" = yes; then
AC_DEFINE(JS_HAVE_SYS_ISA_DEFS_H)
fi
dnl Check for int16_t, int32_t, int64_t, int64, uint, uint_t, and uint16_t.
dnl ========================================================
AC_MSG_CHECKING(for int16_t)

Просмотреть файл

@ -63,6 +63,10 @@
useable. See jscpucfg.h. */
#undef JS_HAVE_ENDIAN_H
/* Define to 1 if the <sys/isa_defs.h> header is present and
useable. See jscpucfg.h. */
#undef JS_HAVE_SYS_ISA_DEFS_H
/* Define to 1 if the <sys/types.h> defines int8_t, etc. */
#undef JS_SYS_TYPES_H_DEFINES_EXACT_SIZE_TYPES

Просмотреть файл

@ -92,7 +92,37 @@
#error "endian.h does not define __BYTE_ORDER. Cannot determine endianness."
#endif
#else /* !defined(HAVE_ENDIAN_H) */
#elif defined(JS_HAVE_SYS_ISA_DEFS_H)
#include <sys/isa_defs.h>
#if defined(_BIG_ENDIAN)
#undef IS_LITTLE_ENDIAN
#define IS_BIG_ENDIAN 1
#elif defined(_LITTLE_ENDIAN)
#define IS_LITTLE_ENDIAN 1
#undef IS_BIG_ENDIAN
#else /* !defined(_LITTLE_ENDIAN) */
#error "sys/isa_defs.h does not define _BIG_ENDIAN or _LITTLE_ENDIAN. Cannot determine endianness."
#endif
#if !defined(JS_STACK_GROWTH_DIRECTION)
#if defined(_STACK_GROWS_UPWARD)
#define JS_STACK_GROWTH_DIRECTION (1)
#elif defined(_STACK_GROWS_DOWNWARD)
#define JS_STACK_GROWTH_DIRECTION (-1)
#endif
#endif
#elif defined(__sparc) || defined(__sparc__) || \
defined(_POWER) || defined(__powerpc__) || \
defined(__ppc__) || defined(__hppa) || \
defined(_MIPSEB) || defined(_BIG_ENDIAN)
/* IA64 running HP-UX will have _BIG_ENDIAN defined.
* IA64 running Linux will have endian.h and be handled above.
*/
#undef IS_LITTLE_ENDIAN
#define IS_BIG_ENDIAN 1
#else /* !defined(__sparc) && !defined(__sparc__) && ... */
#error "Cannot determine endianness of your platform. Please add support to jscpucfg.h."
#endif

Просмотреть файл

@ -4954,7 +4954,7 @@ MarkIteratorUnknownSlow(JSContext *cx)
void
TypeMonitorCallSlow(JSContext *cx, JSObject *callee,
const CallArgs &args, bool constructing)
CallArgs &args, bool constructing)
{
unsigned nargs = callee->getFunctionPrivate()->nargs;
JSScript *script = callee->getFunctionPrivate()->script();
@ -4972,8 +4972,10 @@ TypeMonitorCallSlow(JSContext *cx, JSObject *callee,
TypeScript::SetArgument(cx, script, arg, args[arg]);
/* Watch for fewer actuals than formals to the call. */
for (; arg < nargs; arg++)
TypeScript::SetArgument(cx, script, arg, UndefinedValue());
for (; arg < nargs; arg++) {
Value v = UndefinedValue();
TypeScript::SetArgument(cx, script, arg, v);
}
}
static inline bool
@ -5091,8 +5093,10 @@ TypeDynamicResult(JSContext *cx, JSScript *script, jsbytecode *pc, Type type)
}
void
TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc, const js::Value &rval)
TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc, js::Value &rval)
{
TryCoerceNumberToInt32(rval);
UntrapOpcode untrap(cx, script, pc);
/* Allow the non-TYPESET scenario to simplify stubs used in compound opcodes. */

Просмотреть файл

@ -1077,9 +1077,14 @@ class TypeScript
* by type inference or where the pc has type barriers. For simplicity, we
* always monitor JOF_TYPESET opcodes in the interpreter and stub calls,
* and only look at barriers when generating JIT code for the script.
*
* 'val' is passed by reference, and must refer to the location of the op's
* result which will be subsequently used (i.e. not a temporary value).
* This call may change val by coercing a double-representable-as-an-int
* into an integer.
*/
static inline void Monitor(JSContext *cx, JSScript *script, jsbytecode *pc,
const js::Value &val);
js::Value &val);
/* Monitor an assignment at a SETELEM on a non-integer identifier. */
static inline void MonitorAssign(JSContext *cx, JSScript *script, jsbytecode *pc,
@ -1091,7 +1096,7 @@ class TypeScript
static inline void SetLocal(JSContext *cx, JSScript *script, unsigned local, Type type);
static inline void SetLocal(JSContext *cx, JSScript *script, unsigned local, const js::Value &value);
static inline void SetArgument(JSContext *cx, JSScript *script, unsigned arg, Type type);
static inline void SetArgument(JSContext *cx, JSScript *script, unsigned arg, const js::Value &value);
static inline void SetArgument(JSContext *cx, JSScript *script, unsigned arg, js::Value &value);
static void Sweep(JSContext *cx, JSScript *script);
inline void trace(JSTracer *trc);

Просмотреть файл

@ -310,14 +310,15 @@ MarkIteratorUnknown(JSContext *cx)
}
/*
* Monitor a javascript call, either on entry to the interpreter or made
* from within the interpreter.
* Monitor a javascript call, either on entry to the interpreter or made from
* within the interpreter. As with TypeScript::Monitor, this may coerce double
* arguments to the call into integers.
*/
inline void
TypeMonitorCall(JSContext *cx, const js::CallArgs &args, bool constructing)
TypeMonitorCall(JSContext *cx, js::CallArgs &args, bool constructing)
{
extern void TypeMonitorCallSlow(JSContext *cx, JSObject *callee,
const CallArgs &args, bool constructing);
CallArgs &args, bool constructing);
JSObject *callee = &args.callee();
if (callee->isFunction()) {
@ -444,7 +445,7 @@ FixObjectType(JSContext *cx, JSObject *obj)
}
/* Interface helpers for JSScript */
extern void TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc, const js::Value &rval);
extern void TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc, js::Value &rval);
extern void TypeDynamicResult(JSContext *cx, JSScript *script, jsbytecode *pc, js::types::Type type);
inline bool
@ -559,7 +560,7 @@ TypeScript::InitObject(JSContext *cx, JSScript *script, const jsbytecode *pc, JS
}
/* static */ inline void
TypeScript::Monitor(JSContext *cx, JSScript *script, jsbytecode *pc, const js::Value &rval)
TypeScript::Monitor(JSContext *cx, JSScript *script, jsbytecode *pc, js::Value &rval)
{
if (cx->typeInferenceEnabled())
TypeMonitorResult(cx, script, pc, rval);
@ -677,9 +678,10 @@ TypeScript::SetArgument(JSContext *cx, JSScript *script, unsigned arg, Type type
}
/* static */ inline void
TypeScript::SetArgument(JSContext *cx, JSScript *script, unsigned arg, const js::Value &value)
TypeScript::SetArgument(JSContext *cx, JSScript *script, unsigned arg, js::Value &value)
{
if (cx->typeInferenceEnabled()) {
TryCoerceNumberToInt32(value);
Type type = GetValueType(cx, value);
SetArgument(cx, script, arg, type);
}

Просмотреть файл

@ -3488,10 +3488,10 @@ BEGIN_CASE(JSOP_LENGTH)
}
} while (0);
TypeScript::Monitor(cx, script, regs.pc, rval);
regs.sp[-1] = rval;
assertSameCompartment(cx, regs.sp[-1]);
TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
}
END_CASE(JSOP_GETPROP)
@ -3583,7 +3583,7 @@ BEGIN_CASE(JSOP_CALLPROP)
goto error;
}
#endif
TypeScript::Monitor(cx, script, regs.pc, rval);
TypeScript::Monitor(cx, script, regs.pc, regs.sp[-2]);
}
END_CASE(JSOP_CALLPROP)
@ -4089,7 +4089,7 @@ BEGIN_CASE(JSOP_CALLNAME)
}
PUSH_COPY(rval);
TypeScript::Monitor(cx, script, regs.pc, rval);
TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
/* obj must be on the scope chain, thus not a function. */
if (op == JSOP_CALLNAME || op == JSOP_CALLGNAME)

Просмотреть файл

@ -658,6 +658,17 @@ ToInteger(JSContext *cx, const js::Value &v, jsdouble *dp)
return true;
}
/* If v is a double value which fits in an int32, coerce it to that int32. */
static inline void
TryCoerceNumberToInt32(Value &v)
{
if (v.isDouble()) {
int32_t res;
if (JSDOUBLE_IS_INT32(v.toDouble(), &res))
v.setInt32(res);
}
}
} /* namespace js */
#endif /* jsnum_h___ */

Просмотреть файл

@ -2157,9 +2157,9 @@ ASTSerializer::statement(ParseNode *pn, Value *dst)
return expression(pn->pn_left, &expr) &&
statement(pn->pn_right, &stmt) &&
pn->isKind(TOK_WITH)
? builder.withStatement(expr, stmt, &pn->pn_pos, dst)
: builder.whileStatement(expr, stmt, &pn->pn_pos, dst);
(pn->isKind(TOK_WITH)
? builder.withStatement(expr, stmt, &pn->pn_pos, dst)
: builder.whileStatement(expr, stmt, &pn->pn_pos, dst));
}
case TOK_DO:

Просмотреть файл

@ -223,9 +223,9 @@ WeakMap_set(JSContext *cx, uintN argc, Value *vp)
obj->setPrivate(map);
}
args.thisv() = UndefinedValue();
if (!map->put(key, value))
goto out_of_memory;
args.rval().setUndefined();
return true;
out_of_memory:

Просмотреть файл

@ -6810,6 +6810,12 @@ xml_setName(JSContext *cx, uintN argc, jsval *vp)
return JS_TRUE;
}
/* Utility function used within xml_setNamespace */
static JSBool qn_match(const void *xml, const void *qn) {
return qname_identity(((JSXML *)xml)->name, (JSObject *)qn);
}
/* ECMA-357 13.4.4.36 */
static JSBool
xml_setNamespace(JSContext *cx, uintN argc, jsval *vp)
{
@ -6838,6 +6844,22 @@ xml_setNamespace(JSContext *cx, uintN argc, jsval *vp)
if (!qn)
return JS_FALSE;
/*
* Erratum: setting the namespace of an attribute may cause it to duplicate
* an already-existing attribute. To preserve the invariant that there are
* not multiple attributes with the same name, we delete the existing
* attribute so that the mutated attribute will not be a duplicate.
*/
if (xml->xml_class == JSXML_CLASS_ATTRIBUTE &&
xml->parent && xml->parent->xml_class == JSXML_CLASS_ELEMENT &&
!qn_match(xml, qn))
{
JSXMLArray *array = &xml->parent->xml_attrs;
uint32 i = XMLArrayFindMember(array, qn, qn_match);
if (i != XML_NOT_FOUND)
XMLArrayDelete(cx, array, i, JS_TRUE);
}
xml->name = qn;
/*

Просмотреть файл

@ -230,6 +230,17 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegist
}
#endif
void moveDoubleRegisters(RegisterID data, RegisterID type, Address address, FPRegisterID fpreg)
{
#ifdef JS_CPU_X86
fastLoadDouble(data, type, fpreg);
#else
/* Store the components, then read it back out as a double. */
storeValueFromComponents(type, data, address);
loadDouble(address, fpreg);
#endif
}
/*
* Move a register pair which may indicate either an int32 or double into fpreg,
* converting to double in the int32 case.
@ -1164,6 +1175,29 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegist
} else if (types->hasType(types::Type::Int32Type())) {
if (!matches.append(testInt32(Assembler::Equal, address)))
return false;
/* Generate a path to try coercing doubles to integers in place. */
Jump notDouble = testDouble(Assembler::NotEqual, address);
Registers tempRegs(Registers::AvailRegs);
RegisterID T1 = tempRegs.takeAnyReg().reg();
Registers tempFPRegs(Registers::TempFPRegs);
FPRegisterID FP1 = tempFPRegs.takeAnyReg().fpreg();
FPRegisterID FP2 = tempFPRegs.takeAnyReg().fpreg();
loadDouble(address, FP1);
JumpList isDouble;
branchConvertDoubleToInt32(FP1, T1, isDouble, FP2);
storeValueFromComponents(ImmType(JSVAL_TYPE_INT32), T1, address);
if (!matches.append(jump()))
return false;
isDouble.linkTo(label(), this);
notDouble.linkTo(label(), this);
}
if (types->hasType(types::Type::UndefinedType())) {

Просмотреть файл

@ -7369,39 +7369,6 @@ mjit::Compiler::pushAddressMaybeBarrier(Address address, JSValueType type, bool
return testBarrier(typeReg, dataReg, testUndefined);
}
MaybeJump
mjit::Compiler::trySingleTypeTest(types::TypeSet *types, RegisterID typeReg)
{
/*
* If a type set we have a barrier on is monomorphic, generate a single
* jump taken if a type register has a match. This doesn't handle type sets
* containing objects, as these require two jumps regardless (test for
* object, then test the type of the object).
*/
MaybeJump res;
switch (types->getKnownTypeTag(cx)) {
case JSVAL_TYPE_INT32:
res.setJump(masm.testInt32(Assembler::NotEqual, typeReg));
return res;
case JSVAL_TYPE_DOUBLE:
res.setJump(masm.testNumber(Assembler::NotEqual, typeReg));
return res;
case JSVAL_TYPE_BOOLEAN:
res.setJump(masm.testBoolean(Assembler::NotEqual, typeReg));
return res;
case JSVAL_TYPE_STRING:
res.setJump(masm.testString(Assembler::NotEqual, typeReg));
return res;
default:
return res;
}
}
JSC::MacroAssembler::Jump
mjit::Compiler::addTypeTest(types::TypeSet *types, RegisterID typeReg, RegisterID dataReg)
{
@ -7413,11 +7380,32 @@ mjit::Compiler::addTypeTest(types::TypeSet *types, RegisterID typeReg, RegisterI
Vector<Jump> matches(CompilerAllocPolicy(cx, *this));
if (types->hasType(types::Type::Int32Type()))
if (types->hasType(types::Type::DoubleType())) {
matches.append(masm.testNumber(Assembler::Equal, typeReg));
} else if (types->hasType(types::Type::Int32Type())) {
matches.append(masm.testInt32(Assembler::Equal, typeReg));
if (types->hasType(types::Type::DoubleType()))
matches.append(masm.testDouble(Assembler::Equal, typeReg));
/* Generate a path to try coercing doubles to integers in place. */
Jump notDouble = masm.testDouble(Assembler::NotEqual, typeReg);
FPRegisterID fpTemp = frame.getScratchFPReg();
masm.moveDoubleRegisters(dataReg, typeReg, frame.addressOfTop(), fpTemp);
JumpList isDouble;
masm.branchConvertDoubleToInt32(fpTemp, dataReg, isDouble, Registers::FPConversionTemp);
masm.move(ImmType(JSVAL_TYPE_INT32), typeReg);
frame.restoreScratchFPReg(fpTemp);
matches.append(masm.jump());
isDouble.linkTo(masm.label(), &masm);
masm.breakDouble(fpTemp, typeReg, dataReg);
frame.restoreScratchFPReg(fpTemp);
notDouble.linkTo(masm.label(), &masm);
}
if (types->hasType(types::Type::UndefinedType()))
matches.append(masm.testUndefined(Assembler::Equal, typeReg));
@ -7511,9 +7499,7 @@ mjit::Compiler::testBarrier(RegisterID typeReg, RegisterID dataReg,
/* Cannot have type barriers when the result of the operation is already unknown. */
JS_ASSERT(!types->unknown());
state.jump = trySingleTypeTest(types, typeReg);
if (!state.jump.isSet())
state.jump.setJump(addTypeTest(types, typeReg, dataReg));
state.jump.setJump(addTypeTest(types, typeReg, dataReg));
return state;
}

Просмотреть файл

@ -556,7 +556,6 @@ private:
RegisterID dataReg;
};
MaybeJump trySingleTypeTest(types::TypeSet *types, RegisterID typeReg);
Jump addTypeTest(types::TypeSet *types, RegisterID typeReg, RegisterID dataReg);
BarrierState pushAddressMaybeBarrier(Address address, JSValueType type, bool reuseBase,
bool testUndefined = false);

Просмотреть файл

@ -1974,7 +1974,6 @@ mjit::Compiler::jsop_getelem_typed(int atype)
frame.popn(2);
BarrierState barrier;
if (dataReg.isFPReg()) {
frame.pushDouble(dataReg.fpreg());
} else if (typeReg.isSet()) {
@ -1985,8 +1984,6 @@ mjit::Compiler::jsop_getelem_typed(int atype)
}
stubcc.rejoin(Changes(2));
finishBarrier(barrier, REJOIN_FALLTHROUGH, 0);
return true;
}
#endif /* JS_METHODJIT_TYPED_ARRAY */
@ -2010,7 +2007,12 @@ mjit::Compiler::jsop_getelem(bool isCall)
if (cx->typeInferenceEnabled() && id->mightBeType(JSVAL_TYPE_INT32) && !isCall) {
types::TypeSet *types = analysis->poppedTypes(PC, 1);
if (types->isLazyArguments(cx) && !outerScript->analysis()->modifiesArguments()) {
// Inline arguments path.
// Inline arguments path. This path can access non-canonical args
// if fun->nargs != 0, so we require that the script never has any
// of its arguments directly modified. Note that the canonical and
// formal arg may not be the exact same value if we coerced a
// double actual into an int32 formal from a type barrier at entry,
// but this is ok as the underlying number is the same.
jsop_getelem_args();
return true;
}

Просмотреть файл

@ -195,6 +195,36 @@ FrameState::takeReg(AnyRegisterID reg)
}
}
JSC::MacroAssembler::FPRegisterID
FrameState::getScratchFPReg()
{
if (freeRegs.hasRegInMask(Registers::TempFPRegs)) {
FPRegisterID reg = freeRegs.takeAnyReg(Registers::TempFPRegs).fpreg();
freeRegs.putReg(reg);
return reg;
}
Registers regs(Registers::TempFPRegs);
FPRegisterID reg;
do {
reg = regs.takeAnyReg().fpreg();
} while (!regstate(reg).fe());
masm.storeDouble(reg, addressOf(regstate(reg).fe()));
return reg;
}
void
FrameState::restoreScratchFPReg(FPRegisterID reg)
{
if (freeRegs.hasReg(reg))
return;
masm.loadDouble(addressOf(regstate(reg).fe()), reg);
}
#ifdef DEBUG
const char *
FrameState::entryName(const FrameEntry *fe) const

Просмотреть файл

@ -613,6 +613,14 @@ class FrameState
*/
void takeReg(AnyRegisterID reg);
/*
* Gets an FP register which the compiler does not own but can freely write
* over. Can only be used in the inline path, and must be matched with a
* restoreScratchFPReg. (Emits sync/restore code if the reg is in use).
*/
FPRegisterID getScratchFPReg();
void restoreScratchFPReg(FPRegisterID reg);
/*
* Returns a FrameEntry * for a slot on the operation stack.
*/

Просмотреть файл

@ -2367,7 +2367,7 @@ stubs::TypeBarrierHelper(VMFrame &f, uint32 which)
void JS_FASTCALL
stubs::StubTypeHelper(VMFrame &f, int32 which)
{
const Value &result = f.regs.sp[which];
Value &result = f.regs.sp[which];
if (f.script()->hasAnalysis() && f.script()->analysis()->ranInference()) {
AutoEnterTypeInference enter(f.cx);

Просмотреть файл

@ -68,4 +68,15 @@ TEST(3, 1, xhtml.namespaceDeclarations().length);
TEST(4, xhtml1NS, xhtml.namespace());
var xml = <root xmlns:ns="http://example.org/"><blah/></root>
var ns = new Namespace('ns','http://example.org/');
xml.blah.@foo = 'bar';
xml.blah.@foo.setNamespace(ns);
xml.blah.@foo = 'baz';
xml.blah.@foo.setNamespace(ns);
var expected = <root xmlns:ns="http://example.org/"><blah ns:foo="baz"/></root>;
TEST(5, xml, expected);
END();

Просмотреть файл

@ -58,4 +58,6 @@ require-or(debugMode,skip) script regress-672804-2.js
require-or(debugMode,skip) script regress-672804-3.js
skip-if(!xulRuntime.shell) script regress-677589.js
script regress-677924.js
skip-if(!xulRuntime.shell) script regress-696109.js
script regress-691746.js
script regress-697515.js

Просмотреть файл

@ -0,0 +1,18 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
* Contributor: Dave Herman <dherman@mozilla.com>
*/
// Bug 696109 - fixed a precedence bug in with/while nodes
try {
Reflect.parse("with({foo})bar");
throw new Error("supposed to be a syntax error");
} catch (e if e instanceof SyntaxError) { }
try {
Reflect.parse("while({foo})bar");
throw new Error("supposed to be a syntax error");
} catch (e if e instanceof SyntaxError) { }
reportCompare(true, true);

Просмотреть файл

@ -0,0 +1,6 @@
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/licenses/publicdomain/
assertEq(new WeakMap().set({}, 0), undefined);
reportCompare(0, 0, 'ok');

Просмотреть файл

@ -546,7 +546,7 @@ class Writer
}
nj::LIns *ldiConstTypedArrayLength(nj::LIns *obj) const {
return name(lir->insLoad(nj::LIR_ldi, obj, TypedArray::lengthOffset(), ACCSET_TARRAY,
return name(lir->insLoad(nj::LIR_ldi, obj, TypedArray::lengthOffset() + sPayloadOffset, ACCSET_TARRAY,
nj::LOAD_CONST),
"typedArrayLength");
}

Просмотреть файл

@ -65,6 +65,7 @@ members = [
'nsIDOMWindow.name',
'nsIDOMWindow.parent',
'nsIDOMWindow.top',
'nsIDOMWindow.self',
# Several window properties are magically resolved, including
# location, _content, navigator, document, and window itself.
# These do not need quick stubs.
@ -486,6 +487,7 @@ irregularFilenames = {
'nsIWebGLUniformLocation': 'nsIDOMWebGLRenderingContext',
'nsIWebGLExtension': 'nsIDOMWebGLRenderingContext',
'nsIWebGLExtensionStandardDerivatives' : 'nsIDOMWebGLRenderingContext',
'nsIWebGLExtensionLoseContext' : 'nsIDOMWebGLRenderingContext',
'nsIIndexedDatabaseUsageCallback': 'nsIIndexedDatabaseManager',

Просмотреть файл

@ -1780,10 +1780,26 @@ nsDisplayOpacity::BuildLayer(nsDisplayListBuilder* aBuilder,
return layer.forget();
}
/**
* This doesn't take into account layer scaling --- the layer may be
* rendered at a higher (or lower) resolution, affecting the retained layer
* size --- but this should be good enough.
*/
static bool
IsItemTooSmallForActiveLayer(nsDisplayItem* aItem)
{
nsIntRect visibleDevPixels = aItem->GetVisibleRect().ToOutsidePixels(
aItem->GetUnderlyingFrame()->PresContext()->AppUnitsPerDevPixel());
static const int MIN_ACTIVE_LAYER_SIZE_DEV_PIXELS = 16;
return visibleDevPixels.Size() <
nsIntSize(MIN_ACTIVE_LAYER_SIZE_DEV_PIXELS, MIN_ACTIVE_LAYER_SIZE_DEV_PIXELS);
}
nsDisplayItem::LayerState
nsDisplayOpacity::GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager) {
if (mFrame->AreLayersMarkedActive(nsChangeHint_UpdateOpacityLayer))
if (mFrame->AreLayersMarkedActive(nsChangeHint_UpdateOpacityLayer) &&
!IsItemTooSmallForActiveLayer(this))
return LAYER_ACTIVE;
nsIFrame* activeScrolledRoot =
nsLayoutUtils::GetActiveScrolledRootFor(mFrame, nsnull);
@ -2605,7 +2621,10 @@ already_AddRefed<Layer> nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBu
nsDisplayItem::LayerState
nsDisplayTransform::GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager) {
if (mFrame->AreLayersMarkedActive(nsChangeHint_UpdateTransformLayer))
// Here we check if the *post-transform* bounds of this item are big enough
// to justify an active layer.
if (mFrame->AreLayersMarkedActive(nsChangeHint_UpdateTransformLayer) &&
!IsItemTooSmallForActiveLayer(this))
return LAYER_ACTIVE;
if (!GetTransform(mFrame->PresContext()->AppUnitsPerDevPixel()).Is2D() || mFrame->Preserves3D())
return LAYER_ACTIVE;

Просмотреть файл

@ -5251,8 +5251,11 @@ static nsIView* FindFloatingViewContaining(nsIView* aView, nsPoint aPt)
return nsnull;
nsIFrame* frame = static_cast<nsIFrame*>(aView->GetClientData());
if (frame && !frame->PresContext()->PresShell()->IsActive()) {
return nsnull;
if (frame) {
if (!frame->IsVisibleConsideringAncestors(nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY) ||
!frame->PresContext()->PresShell()->IsActive()) {
return nsnull;
}
}
for (nsIView* v = aView->GetFirstChild(); v; v = v->GetNextSibling()) {
@ -5285,8 +5288,11 @@ static nsIView* FindViewContaining(nsIView* aView, nsPoint aPt)
}
nsIFrame* frame = static_cast<nsIFrame*>(aView->GetClientData());
if (frame && !frame->PresContext()->PresShell()->IsActive()) {
return nsnull;
if (frame) {
if (!frame->IsVisibleConsideringAncestors(nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY) ||
!frame->PresContext()->PresShell()->IsActive()) {
return nsnull;
}
}
for (nsIView* v = aView->GetFirstChild(); v; v = v->GetNextSibling()) {
@ -6864,7 +6870,7 @@ PresShell::WillPaint(bool aWillSendDidPaint)
{
// Don't bother doing anything if some viewmanager in our tree is painting
// while we still have painting suppressed or we are not active.
if (mPaintingSuppressed || !mIsActive) {
if (mPaintingSuppressed || !mIsActive || !IsVisible()) {
return;
}
@ -6890,7 +6896,7 @@ PresShell::WillPaint(bool aWillSendDidPaint)
NS_IMETHODIMP_(void)
PresShell::DidPaint()
{
if (mPaintingSuppressed || !mIsActive) {
if (mPaintingSuppressed || !mIsActive || !IsVisible()) {
return;
}
@ -6903,6 +6909,33 @@ PresShell::DidPaint()
}
}
NS_IMETHODIMP_(bool)
PresShell::IsVisible()
{
if (!mViewManager)
return false;
nsIView* view = mViewManager->GetRootView();
if (!view)
return true;
// inner view of subdoc frame
view = view->GetParent();
if (!view)
return true;
// subdoc view
view = view->GetParent();
if (!view)
return true;
nsIFrame* frame = static_cast<nsIFrame*>(view->GetClientData());
if (!frame)
return true;
return frame->IsVisibleConsideringAncestors(nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY);
}
nsresult
PresShell::GetAgentStyleSheets(nsCOMArray<nsIStyleSheet>& aSheets)
{

Просмотреть файл

@ -337,6 +337,7 @@ public:
NS_IMETHOD_(void) DispatchSynthMouseMove(nsGUIEvent *aEvent,
bool aFlushOnHoverChange);
NS_IMETHOD_(void) ClearMouseCapture(nsIView* aView);
NS_IMETHOD_(bool) IsVisible();
// caret handling
virtual NS_HIDDEN_(already_AddRefed<nsCaret>) GetCaret() const;

Просмотреть файл

@ -119,6 +119,7 @@
#include "nsSVGIntegrationUtils.h"
#include "nsSVGEffects.h"
#include "nsChangeHint.h"
#include "nsDeckFrame.h"
#include "gfxContext.h"
#include "CSSCalc.h"
@ -301,6 +302,48 @@ nsIFrame::CheckAndClearPaintedState()
return result;
}
bool
nsIFrame::IsVisibleConsideringAncestors(PRUint32 aFlags) const
{
if (!GetStyleVisibility()->IsVisible()) {
return false;
}
const nsIFrame* frame = this;
while (frame) {
nsIView* view = frame->GetView();
if (view && view->GetVisibility() == nsViewVisibility_kHide)
return false;
nsIFrame* parent = frame->GetParent();
nsDeckFrame* deck = do_QueryFrame(parent);
if (deck) {
if (deck->GetSelectedBox() != frame)
return false;
}
if (parent) {
frame = parent;
} else {
parent = nsLayoutUtils::GetCrossDocParentFrame(frame);
if (!parent)
break;
if ((aFlags & nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY) == 0 &&
parent->PresContext()->IsChrome() && !frame->PresContext()->IsChrome()) {
break;
}
if (!parent->GetStyleVisibility()->IsVisible())
return false;
frame = parent;
}
}
return true;
}
static bool ApplyOverflowClipping(nsDisplayListBuilder* aBuilder,
const nsIFrame* aFrame,
const nsStyleDisplay* aDisp,
@ -4196,30 +4239,6 @@ NS_IMETHODIMP nsFrame::GetOffsetFromView(nsPoint& aOffset,
return NS_OK;
}
/* virtual */ bool
nsIFrame::AreAncestorViewsVisible() const
{
const nsIFrame* parent;
for (const nsIFrame* f = this; f; f = parent) {
nsIView* view = f->GetView();
if (view && view->GetVisibility() == nsViewVisibility_kHide) {
return false;
}
parent = f->GetParent();
if (!parent) {
parent = nsLayoutUtils::GetCrossDocParentFrame(f);
if (parent && parent->PresContext()->IsChrome() &&
!f->PresContext()->IsChrome()) {
// Don't look beyond chrome/content boundary ... if the chrome
// has hidden a content docshell, the content in the content
// docshell shouldn't be affected (e.g. it should remain focusable).
break;
}
}
}
return true;
}
nsIWidget*
nsIFrame::GetNearestWidget() const
{
@ -7005,38 +7024,34 @@ nsIFrame::IsFocusable(PRInt32 *aTabIndex, bool aWithMouse)
}
bool isFocusable = false;
if (mContent && mContent->IsElement() && AreAncestorViewsVisible()) {
const nsStyleVisibility* vis = GetStyleVisibility();
if (vis->mVisible != NS_STYLE_VISIBILITY_COLLAPSE &&
vis->mVisible != NS_STYLE_VISIBILITY_HIDDEN) {
const nsStyleUserInterface* ui = GetStyleUserInterface();
if (ui->mUserFocus != NS_STYLE_USER_FOCUS_IGNORE &&
ui->mUserFocus != NS_STYLE_USER_FOCUS_NONE) {
// Pass in default tabindex of -1 for nonfocusable and 0 for focusable
tabIndex = 0;
}
isFocusable = mContent->IsFocusable(&tabIndex, aWithMouse);
if (!isFocusable && !aWithMouse &&
GetType() == nsGkAtoms::scrollFrame &&
mContent->IsHTML() &&
!mContent->IsRootOfNativeAnonymousSubtree() &&
mContent->GetParent() &&
!mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)) {
// Elements with scrollable view are focusable with script & tabbable
// Otherwise you couldn't scroll them with keyboard, which is
// an accessibility issue (e.g. Section 508 rules)
// However, we don't make them to be focusable with the mouse,
// because the extra focus outlines are considered unnecessarily ugly.
// When clicked on, the selection position within the element
// will be enough to make them keyboard scrollable.
nsIScrollableFrame *scrollFrame = do_QueryFrame(this);
if (scrollFrame &&
scrollFrame->GetScrollbarStyles() != nsIScrollableFrame::ScrollbarStyles(NS_STYLE_OVERFLOW_HIDDEN, NS_STYLE_OVERFLOW_HIDDEN) &&
!scrollFrame->GetScrollRange().IsEqualEdges(nsRect(0, 0, 0, 0))) {
// Scroll bars will be used for overflow
isFocusable = true;
tabIndex = 0;
}
if (mContent && mContent->IsElement() && IsVisibleConsideringAncestors()) {
const nsStyleUserInterface* ui = GetStyleUserInterface();
if (ui->mUserFocus != NS_STYLE_USER_FOCUS_IGNORE &&
ui->mUserFocus != NS_STYLE_USER_FOCUS_NONE) {
// Pass in default tabindex of -1 for nonfocusable and 0 for focusable
tabIndex = 0;
}
isFocusable = mContent->IsFocusable(&tabIndex, aWithMouse);
if (!isFocusable && !aWithMouse &&
GetType() == nsGkAtoms::scrollFrame &&
mContent->IsHTML() &&
!mContent->IsRootOfNativeAnonymousSubtree() &&
mContent->GetParent() &&
!mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)) {
// Elements with scrollable view are focusable with script & tabbable
// Otherwise you couldn't scroll them with keyboard, which is
// an accessibility issue (e.g. Section 508 rules)
// However, we don't make them to be focusable with the mouse,
// because the extra focus outlines are considered unnecessarily ugly.
// When clicked on, the selection position within the element
// will be enough to make them keyboard scrollable.
nsIScrollableFrame *scrollFrame = do_QueryFrame(this);
if (scrollFrame &&
scrollFrame->GetScrollbarStyles() != nsIScrollableFrame::ScrollbarStyles(NS_STYLE_OVERFLOW_HIDDEN, NS_STYLE_OVERFLOW_HIDDEN) &&
!scrollFrame->GetScrollRange().IsEqualEdges(nsRect(0, 0, 0, 0))) {
// Scroll bars will be used for overflow
isFocusable = true;
tabIndex = 0;
}
}
}

Просмотреть файл

@ -1897,12 +1897,6 @@ public:
NS_IMETHOD GetOffsetFromView(nsPoint& aOffset,
nsIView** aView) const = 0;
/**
* Returns true if and only if all views, from |GetClosestView| up to
* the top of the view hierarchy are visible.
*/
virtual bool AreAncestorViewsVisible() const;
/**
* Returns the nearest widget containing this frame. If this frame has a
* view and the view has a widget, then this frame's widget is
@ -2760,6 +2754,19 @@ NS_PTR_TO_INT32(frame->Properties().Get(nsIFrame::EmbeddingLevelProperty()))
// clears this bit if so.
bool CheckAndClearPaintedState();
// CSS visibility just doesn't cut it because it doesn't inherit through
// documents. Also if this frame is in a hidden card of a deck then it isn't
// visible either and that isn't expressed using CSS visibility. Also if it
// is in a hidden view (there are a few cases left and they are hopefully
// going away soon).
// If the VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY flag is passed then we
// ignore the chrome/content boundary, otherwise we stop looking when we
// reach it.
enum {
VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY = 0x01
};
bool IsVisibleConsideringAncestors(PRUint32 aFlags = 0) const;
protected:
// Members
nsRect mRect;

Просмотреть файл

@ -10,9 +10,9 @@
<body>
<div id="d">
<div id="e">
<div style="width:10px; height:10px; background:yellow;"></div>
<div style="width:80px; height:80px; background:yellow;"></div>
<div id="f">
<div style="width:10px; height:10px; background:blue;"></div>
<div style="width:80px; height:80px; background:blue;"></div>
</div>
</div>
</div>

Просмотреть файл

@ -10,9 +10,9 @@
<body onload="step()">
<div id="d">
<div id="e">
<div style="width:10px; height:10px; background:yellow;"></div>
<div style="width:80px; height:80px; background:yellow;"></div>
<div id="f">
<div style="width:10px; height:10px; background:blue;"></div>
<div style="width:80px; height:80px; background:blue;"></div>
</div>
</div>
</div>

Просмотреть файл

@ -56,7 +56,10 @@ nsNthIndexCache::~nsNthIndexCache()
void
nsNthIndexCache::Reset()
{
mCache.clear();
mCaches[0][0].clear();
mCaches[0][1].clear();
mCaches[1][0].clear();
mCaches[1][1].clear();
}
inline bool
@ -69,29 +72,28 @@ nsNthIndexCache::SiblingMatchesElement(nsIContent* aSibling, Element* aElement,
}
inline bool
nsNthIndexCache::IndexDetermined(nsIContent* aSibling, Element* aChild,
bool aIsOfType, bool aIsFromEnd,
bool aCheckEdgeOnly, PRInt32& aResult)
nsNthIndexCache::IndexDeterminedFromPreviousSibling(nsIContent* aSibling,
Element* aChild,
bool aIsOfType,
bool aIsFromEnd,
const Cache& aCache,
PRInt32& aResult)
{
if (SiblingMatchesElement(aSibling, aChild, aIsOfType)) {
if (aCheckEdgeOnly) {
// The caller only cares whether or not the result is 1, and we
// now know it's not.
aResult = -1;
return true;
}
Cache::Ptr siblingEntry = mCache.lookup(aSibling);
Cache::Ptr siblingEntry = aCache.lookup(aSibling);
if (siblingEntry) {
PRInt32 siblingIndex = siblingEntry->value.mNthIndices[aIsOfType][aIsFromEnd];
PRInt32 siblingIndex = siblingEntry->value;
NS_ASSERTION(siblingIndex != 0,
"How can a non-anonymous node have an anonymous sibling?");
if (siblingIndex > 0) {
// At this point, aResult is a count of how many elements matching
// aChild we have seen after aSibling, including aChild itself. So if
// |siblingIndex| is the index of aSibling, we need to add aResult to
// get the right answer here.
aResult = siblingIndex + aResult;
// aChild we have seen after aSibling, including aChild itself.
// |siblingIndex| is the index of aSibling.
// So if aIsFromEnd, we want |aResult = siblingIndex - aResult| and
// otherwise we want |aResult = siblingIndex + aResult|.
NS_ABORT_IF_FALSE(aIsFromEnd == 0 || aIsFromEnd == 1,
"Bogus bool value");
aResult = siblingIndex + aResult * (1 - 2 * aIsFromEnd);
return true;
}
}
@ -112,48 +114,75 @@ nsNthIndexCache::GetNthIndex(Element* aChild, bool aIsOfType,
return 0;
}
if (!mCache.initialized() && !mCache.init()) {
Cache &cache = mCaches[aIsOfType][aIsFromEnd];
if (!cache.initialized() && !cache.init()) {
// Give up and just don't match.
return 0;
}
Cache::AddPtr entry = mCache.lookupForAdd(aChild);
if (!entry && !mCache.add(entry, aChild)) {
Cache::AddPtr entry = cache.lookupForAdd(aChild);
// Default the value to -2 when adding
if (!entry && !cache.add(entry, aChild, -2)) {
// No good; don't match.
return 0;
}
PRInt32 &slot = entry->value.mNthIndices[aIsOfType][aIsFromEnd];
PRInt32 &slot = entry->value;
if (slot != -2 && (slot != -1 || aCheckEdgeOnly)) {
return slot;
}
PRInt32 result = 1;
if (aIsFromEnd) {
for (nsIContent *cur = aChild->GetNextSibling();
cur;
cur = cur->GetNextSibling()) {
// It doesn't make sense to do cache lookups for siblings when
// aIsFromEnd. In general, the cache will only be primed for
// things that are _before_ us in the DOM.
if (SiblingMatchesElement(cur, aChild, aIsOfType)) {
if (aCheckEdgeOnly) {
// The caller only cares whether or not the result is 1, and we
// now know it's not.
if (aCheckEdgeOnly) {
// The caller only cares whether or not the result is 1, so we can
// stop as soon as we see any other elements that match us.
if (aIsFromEnd) {
for (nsIContent *cur = aChild->GetNextSibling();
cur;
cur = cur->GetNextSibling()) {
if (SiblingMatchesElement(cur, aChild, aIsOfType)) {
result = -1;
break;
}
}
} else {
for (nsIContent *cur = aChild->GetPreviousSibling();
cur;
cur = cur->GetPreviousSibling()) {
if (SiblingMatchesElement(cur, aChild, aIsOfType)) {
result = -1;
break;
}
++result;
}
}
} else {
// In the common case, we already have a cached index for one of
// our previous siblings, so check that first.
for (nsIContent *cur = aChild->GetPreviousSibling();
cur;
cur = cur->GetPreviousSibling()) {
if (IndexDetermined(cur, aChild, aIsOfType, aIsFromEnd, aCheckEdgeOnly,
result)) {
break;
if (IndexDeterminedFromPreviousSibling(cur, aChild, aIsOfType,
aIsFromEnd, cache, result)) {
slot = result;
return result;
}
}
// Now if aIsFromEnd we lose: need to actually compute our index,
// since looking at previous siblings wouldn't have told us
// anything about it. Note that it doesn't make sense to do cache
// lookups on our following siblings, since chances are the cache
// is not primed for them.
if (aIsFromEnd) {
result = 1;
for (nsIContent *cur = aChild->GetNextSibling();
cur;
cur = cur->GetNextSibling()) {
if (SiblingMatchesElement(cur, aChild, aIsOfType)) {
++result;
}
}
}
}

Просмотреть файл

@ -80,30 +80,11 @@ private:
inline bool SiblingMatchesElement(nsIContent* aSibling, Element* aElement,
bool aIsOfType);
/**
* Returns true if aResult has been set to the correct value for aChild and
* no more work needs to be done. Returns false otherwise.
*/
inline bool IndexDetermined(nsIContent* aSibling, Element* aChild,
bool aIsOfType, bool aIsFromEnd,
bool aCheckEdgeOnly, PRInt32& aResult);
struct CacheEntry {
CacheEntry() {
mNthIndices[0][0] = -2;
mNthIndices[0][1] = -2;
mNthIndices[1][0] = -2;
mNthIndices[1][1] = -2;
}
// This node's index for :nth-child(), :nth-last-child(),
// :nth-of-type(), :nth-last-of-type(). If -2, needs to be computed.
// If -1, needs to be computed but known not to be 1.
// If 0, the node is not at any index in its parent.
// The first subscript is 0 for -child and 1 for -of-type, the second
// subscript is 0 for nth- and 1 for nth-last-.
PRInt32 mNthIndices[2][2];
};
// This node's index for this cache.
// If -2, needs to be computed.
// If -1, needs to be computed but known not to be 1.
// If 0, the node is not at any index in its parent.
typedef PRInt32 CacheEntry;
class SystemAllocPolicy {
public:
@ -116,7 +97,30 @@ private:
typedef js::HashMap<nsIContent*, CacheEntry, js::DefaultHasher<nsIContent*>,
SystemAllocPolicy> Cache;
Cache mCache;
/**
* Returns true if aResult has been set to the correct value for aChild and
* no more work needs to be done. Returns false otherwise.
*
* aResult is an inout parameter. The in value is the number of elements
* that are in the half-open range (aSibling, aChild] (so including aChild
* but not including aSibling) that match aChild. The out value is the
* correct index for aChild if this function returns true and the number of
* elements in the closed range [aSibling, aChild] that match aChild
* otherwise.
*/
inline bool IndexDeterminedFromPreviousSibling(nsIContent* aSibling,
Element* aChild,
bool aIsOfType,
bool aIsFromEnd,
const Cache& aCache,
PRInt32& aResult);
// Caches of indices for :nth-child(), :nth-last-child(),
// :nth-of-type(), :nth-last-of-type(), keyed by Element*.
//
// The first subscript is 0 for -child and 1 for -of-type, the second
// subscript is 0 for nth- and 1 for nth-last-.
Cache mCaches[2][2];
};
#endif /* nsContentIndexCache_h__ */

Просмотреть файл

@ -66,6 +66,10 @@ NS_NewDeckFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
NS_IMPL_FRAMEARENA_HELPERS(nsDeckFrame)
NS_QUERYFRAME_HEAD(nsDeckFrame)
NS_QUERYFRAME_ENTRY(nsDeckFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
nsDeckFrame::nsDeckFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
: nsBoxFrame(aPresShell, aContext), mIndex(0)
@ -92,7 +96,7 @@ nsDeckFrame::AttributeChanged(PRInt32 aNameSpaceID,
// if the index changed hide the old element and make the new element visible
if (aAttribute == nsGkAtoms::selectedIndex) {
IndexChanged(PresContext());
IndexChanged();
}
return rv;
@ -110,68 +114,14 @@ nsDeckFrame::Init(nsIContent* aContent,
return rv;
}
static void
CreateViewsForFrames(const nsFrameList& aFrames)
void
nsDeckFrame::HideBox(nsIBox* aBox)
{
for (nsFrameList::Enumerator f(aFrames); !f.AtEnd(); f.Next()) {
nsContainerFrame::CreateViewForFrame(f.get(), true);
}
}
NS_IMETHODIMP
nsDeckFrame::SetInitialChildList(ChildListID aListID,
nsFrameList& aChildList)
{
CreateViewsForFrames(aChildList);
return nsBoxFrame::SetInitialChildList(aListID, aChildList);
}
NS_IMETHODIMP
nsDeckFrame::AppendFrames(ChildListID aListID,
nsFrameList& aFrameList)
{
CreateViewsForFrames(aFrameList);
return nsBoxFrame::AppendFrames(aListID, aFrameList);
}
NS_IMETHODIMP
nsDeckFrame::InsertFrames(ChildListID aListID,
nsIFrame* aPrevFrame,
nsFrameList& aFrameList)
{
CreateViewsForFrames(aFrameList);
return nsBoxFrame::InsertFrames(aListID, aPrevFrame, aFrameList);
nsIPresShell::ClearMouseCapture(aBox);
}
void
nsDeckFrame::HideBox(nsPresContext* aPresContext, nsIBox* aBox)
{
nsIView* view = aBox->GetView();
if (view) {
nsIViewManager* viewManager = view->GetViewManager();
viewManager->SetViewVisibility(view, nsViewVisibility_kHide);
viewManager->ResizeView(view, nsRect(0, 0, 0, 0));
nsIPresShell::ClearMouseCapture(aBox);
}
}
void
nsDeckFrame::ShowBox(nsPresContext* aPresContext, nsIBox* aBox)
{
nsRect rect = aBox->GetRect();
nsIView* view = aBox->GetView();
if (view) {
nsIViewManager* viewManager = view->GetViewManager();
rect.x = rect.y = 0;
viewManager->ResizeView(view, rect);
viewManager->SetViewVisibility(view, nsViewVisibility_kShow);
}
}
void
nsDeckFrame::IndexChanged(nsPresContext* aPresContext)
nsDeckFrame::IndexChanged()
{
//did the index change?
PRInt32 index = GetSelectedIndex();
@ -184,14 +134,9 @@ nsDeckFrame::IndexChanged(nsPresContext* aPresContext)
// hide the currently showing box
nsIBox* currentBox = GetSelectedBox();
if (currentBox) // only hide if it exists
HideBox(aPresContext, currentBox);
HideBox(currentBox);
mIndex = index;
// show the new box
nsIBox* newBox = GetSelectedBox();
if (newBox) // only show if it exists
ShowBox(aPresContext, newBox);
}
PRInt32
@ -213,7 +158,7 @@ nsDeckFrame::GetSelectedIndex()
return index;
}
nsIBox*
nsIFrame*
nsDeckFrame::GetSelectedBox()
{
return (mIndex >= 0) ? mFrames.FrameAt(mIndex) : nsnull;
@ -267,10 +212,8 @@ nsDeckFrame::DoLayout(nsBoxLayoutState& aState)
while (box)
{
// make collapsed children not show up
if (count == mIndex)
ShowBox(aState.PresContext(), box);
else
HideBox(aState.PresContext(), box);
if (count != mIndex)
HideBox(box);
box = box->GetNextBox();
count++;

Просмотреть файл

@ -51,6 +51,8 @@
class nsDeckFrame : public nsBoxFrame
{
public:
NS_DECL_QUERYFRAME_TARGET(nsDeckFrame)
NS_DECL_QUERYFRAME
NS_DECL_FRAMEARENA_HELPERS
friend nsIFrame* NS_NewDeckFrame(nsIPresShell* aPresShell,
@ -74,16 +76,6 @@ public:
nsIFrame* aParent,
nsIFrame* aPrevInFlow);
// Override SetInitialChildList/AppendFrames/InsertFrames to
// create views for our child frames if necessary
NS_IMETHOD SetInitialChildList(ChildListID aListID,
nsFrameList& aChildList);
NS_IMETHOD AppendFrames(ChildListID aListID,
nsFrameList& aFrameList);
NS_IMETHOD InsertFrames(ChildListID aListID,
nsIFrame* aPrevFrame,
nsFrameList& aFrameList);
virtual nsIAtom* GetType() const;
#ifdef NS_DEBUG
@ -95,14 +87,13 @@ public:
nsDeckFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
nsIFrame* GetSelectedBox();
protected:
// REVIEW: Sorry, I couldn't resist devirtualizing these.
nsIBox* GetSelectedBox();
void IndexChanged(nsPresContext* aPresContext);
void IndexChanged();
PRInt32 GetSelectedIndex();
void HideBox(nsPresContext* aPresContext, nsIBox* aBox);
void ShowBox(nsPresContext* aPresContext, nsIBox* aBox);
void HideBox(nsIBox* aBox);
private:

Просмотреть файл

@ -50,8 +50,8 @@ class nsRegion;
class nsIntRegion;
#define NS_IVIEWOBSERVER_IID \
{ 0xdc283a18, 0x61cb, 0x468c, \
{ 0x8d, 0xb8, 0x9b, 0x81, 0xf7, 0xc9, 0x33, 0x25 } }
{ 0xac6eec35, 0x65d2, 0x4fe8, \
{ 0xa1, 0x37, 0x1a, 0xc3, 0xf6, 0x51, 0x52, 0x56 } }
class nsIViewObserver : public nsISupports
{
@ -145,6 +145,11 @@ public:
*/
NS_IMETHOD_(void) ClearMouseCapture(nsIView* aView) = 0;
/**
* Returns true if the view observer is visible in some way. Otherwise false.
*/
NS_IMETHOD_(bool) IsVisible() = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIViewObserver, NS_IVIEWOBSERVER_IID)

Просмотреть файл

@ -265,7 +265,7 @@ void nsViewManager::DoSetWindowDimensions(nscoord aWidth, nscoord aHeight)
NS_IMETHODIMP nsViewManager::SetWindowDimensions(nscoord aWidth, nscoord aHeight)
{
if (mRootView) {
if (mRootView->IsEffectivelyVisible()) {
if (mRootView->IsEffectivelyVisible() && mObserver && mObserver->IsVisible()) {
if (mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) &&
mDelayedResize != nsSize(aWidth, aHeight)) {
// We have a delayed resize; that now obsolete size may already have
@ -827,7 +827,8 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent,
? vm->mRootView->GetParent()->GetViewManager()
: nsnull) {
if (vm->mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) &&
vm->mRootView->IsEffectivelyVisible()) {
vm->mRootView->IsEffectivelyVisible() &&
mObserver && mObserver->IsVisible()) {
vm->FlushDelayedResize(true);
// Paint later.