Merge last PGO-safe green changeset from mozilla-inbound to mozilla-central

This commit is contained in:
Marco Bonardo 2012-01-14 10:01:34 +01:00
commit 5acdef53c1
79 changed files with 5112 additions and 308 deletions

View File

@ -2617,7 +2617,7 @@ function UpdateUrlbarSearchSplitterState()
}
function setUrlAndSearchBarWidthForConditionalForwardButton() {
// Woraround for bug 694084: Showing/hiding the conditional forward button resizes
// Workaround for bug 694084: Showing/hiding the conditional forward button resizes
// the search bar when the url/search bar splitter hasn't been used.
var urlbarContainer = document.getElementById("urlbar-container");
var searchbarContainer = document.getElementById("search-container");
@ -5487,7 +5487,7 @@ function updateAppButtonDisplay() {
document.getElementById("titlebar").hidden = !displayAppButton;
if (displayAppButton)
document.documentElement.setAttribute("chromemargin", "0,-1,-1,-1");
document.documentElement.setAttribute("chromemargin", "0,2,2,2");
else
document.documentElement.removeAttribute("chromemargin");

View File

@ -134,7 +134,6 @@
@BINPATH@/components/directory.xpt
@BINPATH@/components/docshell.xpt
@BINPATH@/components/dom.xpt
@BINPATH@/components/dom_apps.xpt
@BINPATH@/components/dom_base.xpt
#ifdef MOZ_B2G_RIL
@BINPATH@/components/dom_telephony.xpt
@ -389,8 +388,6 @@
#endif
@BINPATH@/components/TelemetryPing.js
@BINPATH@/components/TelemetryPing.manifest
@BINPATH@/components/Webapps.js
@BINPATH@/components/Webapps.manifest
; Modules
@BINPATH@/modules/*

View File

@ -2,5 +2,6 @@
global:
NSModule;
NSGetModule;
__RLD_MAP;
local: *;
};

View File

@ -2,5 +2,6 @@ EXPORTED {
global:
NSModule;
NSGetModule;
__RLD_MAP;
local: *;
};

View File

@ -2536,7 +2536,7 @@ ia64*-hpux*)
# Use temp file for windres (bug 213281)
RCFLAGS='-O coff --use-temp-file'
# mingw doesn't require kernel32, user32, and advapi32 explicitly
LIBS="$LIBS -luuid -lgdi32 -lwinmm -lwsock32"
LIBS="$LIBS -luuid -lgdi32 -lwinmm -lwsock32 -luserenv"
MOZ_FIX_LINK_PATHS=
DYNAMIC_XPCOM_LIBS='-L$(LIBXUL_DIST)/lib -lxpcom -lxpcom_core -lmozalloc'
XPCOM_FROZEN_LDOPTS='-L$(LIBXUL_DIST)/lib -lxpcom -lmozalloc'

View File

@ -116,7 +116,6 @@ _TEST_FILES1 = \
test_bug364413.xhtml \
test_bug366946.html \
test_bug367164.html \
test_bug371576-1.html \
test_bug371576-2.html \
test_bug371576-3.html \
test_bug371576-4.html \

View File

@ -1,32 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=371576
-->
<head id="head">
<title>Test for Bug 371576</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=371576">Mozilla Bug 371576</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
var result = "A";
var scrElem= document.createElement('script');
scrElem.setAttribute('src','data:text/javascript,result+="C";$("content").innerHTML="--";result+="D";');
$("head").appendChild(scrElem);
result += "B";
</script>
<script>result += "E"</script>
<script>result += "F"</script>
<script>is(result, "ABCDEF", "Wrong order of execution");</script>
</pre>
</body>
</html>

View File

@ -52,14 +52,18 @@ EXTRA_PP_COMPONENTS = \
ConsoleAPI.manifest \
$(NULL)
EXTRA_JS_MODULES = ConsoleAPIStorage.jsm \
$(NULL)
ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
EXTRA_COMPONENTS = \
Webapps.js \
Webapps.manifest \
$(NULL)
EXTRA_JS_MODULES = ConsoleAPIStorage.jsm \
Webapps.jsm \
EXTRA_JS_MODULES += Webapps.jsm \
$(NULL)
endif
XPIDLSRCS = \
nsIEntropyCollector.idl \

View File

@ -166,7 +166,7 @@ static bool init() {
if (gSurfaceFunctions.initialized)
return true;
void* handle = dlopen("/system/lib/libsurfaceflinger_client.so", RTLD_LAZY);
void* handle = dlopen("libsurfaceflinger_client.so", RTLD_LAZY);
if (!handle) {
LOG("Failed to open libsurfaceflinger_client.so");
@ -176,7 +176,7 @@ static bool init() {
gSurfaceFunctions.lock = (int (*)(void*, SurfaceInfo*, void*))dlsym(handle, "_ZN7android7Surface4lockEPNS0_11SurfaceInfoEPNS_6RegionEb");
gSurfaceFunctions.unlockAndPost = (int (*)(void*))dlsym(handle, "_ZN7android7Surface13unlockAndPostEv");
handle = dlopen("/system/lib/libui.so", RTLD_LAZY);
handle = dlopen("libui.so", RTLD_LAZY);
if (!handle) {
LOG("Failed to open libui.so");
return false;

View File

@ -4,7 +4,7 @@
"use strict";
let libcutils = (function () {
let library = ctypes.open("/system/lib/libcutils.so");
let library = ctypes.open("libcutils.so");
return {
property_get: library.declare("property_get", ctypes.default_abi, ctypes.int, ctypes.char.ptr, ctypes.char.ptr, ctypes.char.ptr),

View File

@ -4,7 +4,7 @@
"use strict";
let libhardware_legacy = (function () {
let library = ctypes.open("/system/lib/libhardware_legacy.so");
let library = ctypes.open("libhardware_legacy.so");
return {
// Load wifi driver, 0 on success, < 0 on failure.

View File

@ -4,7 +4,7 @@
"use strict";
let libnetutils = (function () {
let library = ctypes.open("/system/lib/libnetutils.so");
let library = ctypes.open("libnetutils.so");
return {
ifc_enable: library.declare("ifc_enable", ctypes.default_abi, ctypes.int, ctypes.char.ptr),

View File

@ -647,6 +647,10 @@ nsEditorEventListener::HandleText(nsIDOMEvent* aTextEvent)
return NS_OK;
}
// Transfer the event's trusted-ness to our editor
nsCOMPtr<nsIDOMNSEvent> NSEvent = do_QueryInterface(aTextEvent);
nsAutoEditorKeypressOperation operation(mEditor, NSEvent);
return mEditor->UpdateIMEComposition(composedText, textRangeList);
}

View File

@ -969,6 +969,7 @@ nsPlaintextEditor::UpdateIMEComposition(const nsAString& aCompositionString,
// list are empty when listing the Chinese characters. In this case,
// we don't need to process composition string too. See bug 271815.
bool notifyEditorObservers = false;
if (!aCompositionString.IsEmpty() || (mIMETextNode && aTextRangeList)) {
mIMETextRangeList = aTextRangeList;
@ -992,9 +993,12 @@ nsPlaintextEditor::UpdateIMEComposition(const nsAString& aCompositionString,
// If still composing, we should fire input event via observer.
// Note that if committed, we don't need to notify it since it will be
// notified at followed compositionend event.
if (mIsIMEComposing) {
NotifyEditorObservers();
}
// NOTE: We must notify after the auto batch will be gone.
notifyEditorObservers = mIsIMEComposing;
}
if (notifyEditorObservers) {
NotifyEditorObservers();
}
return rv;

View File

@ -65,6 +65,7 @@ _TEST_FILES = \
test_bug645914.html \
test_bug681229.html \
test_bug692520.html \
test_bug717147.html \
$(NULL)
# disables the key handling test on gtk2 because gtk2 overrides some key events

View File

@ -0,0 +1,99 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=717147
-->
<head>
<title>Test for Bug 717147</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717147">Mozilla Bug 717147</a>
<p id="display"></p>
<div id="content">
<iframe id="formTarget" name="formTarget"></iframe>
<form action="data:text/html," target="formTarget">
<input name="test" id="initValue"><input type="submit">
</form>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 717147 **/
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(function() {
var formTarget = document.getElementById("formTarget");
var initValue = document.getElementById("initValue");
formTarget.addEventListener("load", function() {
var newInput = document.createElement("input");
newInput.setAttribute("name", "test");
document.body.appendChild(newInput);
setTimeout(function() {
var popupShown = false;
function listener() {
popupShown = true;
}
SpecialPowers.addAutoCompletePopupEventListener(window, listener);
newInput.value = "";
newInput.focus();
synthesizeComposition({ type: "compositionstart" });
synthesizeComposition({ type: "compositionupdate", data: "f" });
synthesizeText(
{ "composition":
{ "string": "f",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
]
},
"caret": { "start": 1, "length": 0 }
});
hitEventLoop(function() {
ok(!popupShown, "Popup must not be opened during composition");
synthesizeText(
{ "composition":
{ "string": "f",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 1, "length": 0 }
});
synthesizeComposition({ type: "compositionend", data: "f" });
hitEventLoop(function () {
ok(popupShown, "Popup must be opened after compositionend");
SpecialPowers.removeAutoCompletePopupEventListener(window, listener);
SimpleTest.finish();
}, 100);
}, 100);
}, 0);
}, false);
initValue.focus();
initValue.value = "foo";
synthesizeKey("VK_ENTER", {});
});
function hitEventLoop(func, times) {
if (times > 0) {
setTimeout(hitEventLoop, 0, func, times - 1);
} else {
setTimeout(func, 0);
}
}
</script>
</pre>
</body>
</html>

View File

@ -69,11 +69,11 @@
#include "AndroidBridge.h"
#endif
#include <android/log.h>
#define EGL_LIB "/system/lib/libEGL.so"
#define GLES2_LIB "/system/lib/libGLESv2.so"
#define EGL_LIB "libEGL.so"
#define GLES2_LIB "libGLESv2.so"
#else
#define EGL_LIB "/usr/lib/libEGL.so"
#define GLES2_LIB "/usr/lib/libGLESv2.so"
#define EGL_LIB "libEGL.so.1"
#define GLES2_LIB "libGLESv2.so.2"
#endif
typedef void *EGLNativeDisplayType;

View File

@ -69,6 +69,7 @@
#include "nsCompressedCharMap.h"
#include "nsStyleConsts.h"
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#include "cairo.h"
#include "gfxFontTest.h"
@ -81,6 +82,7 @@
using namespace mozilla;
using namespace mozilla::gfx;
using mozilla::services::GetObserverService;
gfxFontCache *gfxFontCache::gGlobalCache = nsnull;
@ -954,6 +956,39 @@ gfxFontFamily::FindFont(const nsAString& aPostscriptName)
return nsnull;
}
/*
* gfxFontCache - global cache of gfxFont instances.
* Expires unused fonts after a short interval;
* notifies fonts to age their cached shaped-word records;
* observes memory-pressure notification and tells fonts to clear their
* shaped-word caches to free up memory.
*/
// Observer for the memory-pressure notification, to trigger
// flushing of the shaped-word caches
class MemoryPressureObserver : public nsIObserver,
public nsSupportsWeakReference
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
};
NS_IMPL_ISUPPORTS2(MemoryPressureObserver, nsIObserver, nsISupportsWeakReference)
NS_IMETHODIMP
MemoryPressureObserver::Observe(nsISupports *aSubject,
const char *aTopic,
const PRUnichar *someData)
{
if (!nsCRT::strcmp(aTopic, "memory-pressure")) {
gfxFontCache *fontCache = gfxFontCache::GetCache();
if (fontCache) {
fontCache->FlushShapedWordCaches();
}
}
return NS_OK;
}
nsresult
gfxFontCache::Init()
@ -986,6 +1021,12 @@ gfxFontCache::gfxFontCache()
: nsExpirationTracker<gfxFont,3>(FONT_TIMEOUT_SECONDS * 1000)
{
mFonts.Init();
nsCOMPtr<nsIObserverService> obs = GetObserverService();
if (obs) {
obs->AddObserver(new MemoryPressureObserver, "memory-pressure", false);
}
mWordCacheExpirationTimer = do_CreateInstance("@mozilla.org/timer;1");
if (mWordCacheExpirationTimer) {
mWordCacheExpirationTimer->
@ -1102,6 +1143,14 @@ gfxFontCache::WordCacheExpirationTimerCallback(nsITimer* aTimer, void* aCache)
cache->mFonts.EnumerateEntries(AgeCachedWordsForFont, nsnull);
}
/*static*/
PLDHashOperator
gfxFontCache::ClearCachedWordsForFont(HashEntry* aHashEntry, void* aUserData)
{
aHashEntry->mFont->ClearCachedWords();
return PL_DHASH_NEXT;
}
void
gfxFont::RunMetrics::CombineWith(const RunMetrics& aOther, bool aOtherIsOnLeft)
{

View File

@ -732,6 +732,10 @@ public:
AgeAllGenerations();
}
void FlushShapedWordCaches() {
mFonts.EnumerateEntries(ClearCachedWordsForFont, nsnull);
}
protected:
void DestroyFont(gfxFont *aFont);
@ -767,6 +771,7 @@ protected:
nsTHashtable<HashEntry> mFonts;
static PLDHashOperator ClearCachedWordsForFont(HashEntry* aHashEntry, void*);
static PLDHashOperator AgeCachedWordsForFont(HashEntry* aHashEntry, void*);
static void WordCacheExpirationTimerCallback(nsITimer* aTimer, void* aCache);
nsCOMPtr<nsITimer> mWordCacheExpirationTimer;
@ -1405,6 +1410,13 @@ public:
}
}
// Discard all cached word records; called on memory-pressure notification.
void ClearCachedWords() {
if (mWordCache.IsInitialized()) {
mWordCache.Clear();
}
}
protected:
// Call the appropriate shaper to generate glyphs for aText and store
// them into aShapedWord.

View File

@ -319,10 +319,12 @@ endif # }
ifneq (86,$(findstring 86,$(OS_TEST))) # {
ifneq (arm,$(findstring arm,$(OS_TEST))) # {
ifneq (mips,$(findstring mips,$(OS_TEST))) # {
# Use mutex-backed atomics
CPPSRCS += atomicops_internals_mutex.cc
endif # }
endif # }
endif # }
OS_CXXFLAGS += $(TK_CFLAGS)

View File

@ -136,6 +136,8 @@ Atomic64 Release_Load(volatile const Atomic64* ptr);
#include "base/atomicops_internals_x86_gcc.h"
#elif defined(COMPILER_GCC) && defined(ARCH_CPU_ARM_FAMILY)
#include "base/atomicops_internals_arm_gcc.h"
#elif defined(COMPILER_GCC) && defined(ARCH_CPU_MIPS)
#include "base/atomicops_internals_mips_gcc.h"
#else
#include "base/atomicops_internals_mutex.h"
#endif

View File

@ -2848,6 +2848,11 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
if toplevel.talksRpc():
self.rpcSwitch.addcase(DefaultLabel(), default)
# FIXME/bug 535053: only manager protocols and non-manager
# protocols with union types need Lookup(). we'll give it to
# all for the time being (simpler)
if 1 or ptype.isManager():
self.cls.addstmts(self.implementManagerIface())
def makeHandlerMethod(name, switch, hasReply, dispatches=0):
params = [ Decl(Type('Message', const=1, ref=1), msgvar.name) ]
@ -3010,11 +3015,6 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
_runtimeAbort("'OnConnected' called on non-toplevel actor"))
self.cls.addstmts([ onconnected, Whitespace.NL ])
# FIXME/bug 535053: only manager protocols and non-manager
# protocols with union types need Lookup(). we'll give it to
# all for the time being (simpler)
if 1 or ptype.isManager():
self.cls.addstmts(self.implementManagerIface())
# User-facing shmem methods
self.cls.addstmts(self.makeShmemIface())

View File

@ -333,6 +333,9 @@ endif
ifeq (sparc, $(findstring sparc,$(TARGET_CPU)))
ASFILES += TrampolineSparc.s
endif
ifeq (mips, $(findstring mips,$(TARGET_CPU)))
CPPSRCS += TrampolineMIPS.cpp
endif
#
# END enclude sources for the method JIT
#############################################
@ -361,7 +364,7 @@ CPPSRCS += checks.cc \
# For architectures without YARR JIT, PCRE is faster than the YARR
# interpreter (bug 684559).
ifeq (,$(filter arm% sparc %86 x86_64,$(TARGET_CPU)))
ifeq (,$(filter arm% sparc %86 x86_64 mips%,$(TARGET_CPU)))
VPATH += $(srcdir)/yarr/pcre \
$(NULL)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1028,7 +1028,7 @@
/* The JIT is enabled by default on all x86, x64-64, ARM platforms. */
#if !defined(ENABLE_JIT) \
&& (WTF_CPU_X86 || WTF_CPU_X86_64 || WTF_CPU_ARM || WTF_CPU_SPARC32) \
&& (WTF_CPU_X86 || WTF_CPU_X86_64 || WTF_CPU_ARM || WTF_CPU_SPARC32 || WTF_CPU_MIPS) \
&& (WTF_OS_DARWIN || !WTF_COMPILER_GCC || GCC_VERSION_AT_LEAST(4, 1, 0)) \
&& !WTF_OS_WINCE
#define ENABLE_JIT 1

View File

@ -2811,6 +2811,14 @@ sparc*-*)
AC_DEFINE(JS_CPU_SPARC)
AC_DEFINE(JS_NUNBOX32)
;;
mips*-*)
ENABLE_METHODJIT=1
ENABLE_MONOIC=1
ENABLE_POLYIC=1
ENABLE_METHODJIT_TYPED_ARRAY=1
AC_DEFINE(JS_CPU_MIPS)
AC_DEFINE(JS_NUNBOX32)
;;
esac
MOZ_ARG_DISABLE_BOOL(methodjit,

View File

@ -1,32 +0,0 @@
function leak_test() {
// Create a reference loop function->script->traceFragment->object->function
// that GC must be able to break. To embedd object into the fragment the
// code use prototype chain of depth 2 which caches obj.__proto__.__proto__
// into the fragment.
// To make sure that we have no references to the function f after this
// function returns due via the conservative scan of the native stack we
// loop here multiple times overwriting the stack and registers with new garabge.
for (var j = 0; j != 8; ++j) {
var f = Function("a", "var s = 0; for (var i = 0; i != 100; ++i) s += a.b; return s;");
var c = {b: 1, f: f, leakDetection: makeFinalizeObserver()};
f({ __proto__: { __proto__: c}});
f = c = a = null;
gc();
}
}
function test()
{
if (typeof finalizeCount != "function")
return;
var base = finalizeCount();
leak_test();
gc();
gc();
var n = finalizeCount();
assertEq(base + 4 < finalizeCount(), true, "Some finalizations must happen");
}
test();

View File

@ -85,6 +85,7 @@ JITSTAT(archIs64BIT)
JITSTAT(archIsARM)
JITSTAT(archIsSPARC)
JITSTAT(archIsPPC)
JITSTAT(archIsMIPS)
#ifdef DEFINED_MONITOR_JITSTAT
#undef DEFINED_MONITOR_JITSTAT

View File

@ -4064,8 +4064,11 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
pushed[0].addType(cx, Type::UnknownType());
break;
case JSOP_XMLNAME:
case JSOP_CALLXMLNAME:
pushed[1].addType(cx, Type::UnknownType());
/* FALLTHROUGH */
case JSOP_XMLNAME:
pushed[0].addType(cx, Type::UnknownType());
break;

View File

@ -92,7 +92,11 @@ JSDOUBLE_IS_NaN(jsdouble d)
{
jsdpun u;
u.d = d;
#if defined(mips) || defined(__mips__) || defined(MIPS) || defined(_MIPS_)
return (u.u64 & ~JSDOUBLE_SIGNBIT) > JSDOUBLE_EXPMASK;
#else
return (u.s.hi & JSDOUBLE_HI32_NAN) == JSDOUBLE_HI32_NAN;
#endif
}
static inline int

View File

@ -581,7 +581,7 @@ class OpcodeCounts
};
static bool elementOp(JSOp op) {
return accessOp(op) && !!(js_CodeSpec[op].format & JOF_ELEM);
return accessOp(op) && (JOF_MODE(js_CodeSpec[op].format) == JOF_ELEM);
}
enum PropertyCounts {
@ -593,7 +593,7 @@ class OpcodeCounts
};
static bool propertyOp(JSOp op) {
return accessOp(op) && !!(js_CodeSpec[op].format & JOF_PROP);
return accessOp(op) && (JOF_MODE(js_CodeSpec[op].format) == JOF_PROP);
}
enum ArithCounts {

View File

@ -174,6 +174,10 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::ARMRegiste
static const JSC::MacroAssembler::RegisterID JSReturnReg_Type = JSC::SparcRegisters::l2;
static const JSC::MacroAssembler::RegisterID JSReturnReg_Data = JSC::SparcRegisters::l3;
static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegisters::l4;
#elif defined(JS_CPU_MIPS)
static const JSC::MacroAssembler::RegisterID JSReturnReg_Type = JSC::MIPSRegisters::a0;
static const JSC::MacroAssembler::RegisterID JSReturnReg_Data = JSC::MIPSRegisters::a2;
static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::MIPSRegisters::a1;
#endif
size_t distanceOf(Label l) {
@ -283,7 +287,7 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegist
static const uint64_t DoubleNegMask = 0x8000000000000000ULL;
loadDouble(&DoubleNegMask, Registers::FPConversionTemp);
xorDouble(Registers::FPConversionTemp, fpreg);
#elif defined JS_CPU_ARM || defined JS_CPU_SPARC
#elif defined JS_CPU_ARM || defined JS_CPU_SPARC || defined JS_CPU_MIPS
negDouble(fpreg, fpreg);
#endif
}
@ -318,6 +322,13 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegist
*/
moveWithPatch(Imm32(intptr_t(fun)), JSC::SparcRegisters::i0);
return JS_FUNC_TO_DATA_PTR(void *, JaegerStubVeneer);
#elif defined(JS_CPU_MIPS)
/*
* For MIPS, we need to call JaegerStubVeneer by passing
* the real target address in v0.
*/
moveWithPatch(Imm32(intptr_t(fun)), JSC::MIPSRegisters::v0);
return JS_FUNC_TO_DATA_PTR(void *, JaegerStubVeneer);
#else
/*
* Architectures that push the return address to an easily-determined
@ -358,10 +369,14 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegist
pop(reg);
}
#if defined JS_CPU_MIPS
static const uint32_t StackAlignment = 8;
#else
static const uint32_t StackAlignment = 16;
#endif
static inline uint32_t alignForCall(uint32_t stackBytes) {
#if defined(JS_CPU_X86) || defined(JS_CPU_X64)
#if defined(JS_CPU_X86) || defined(JS_CPU_X64) || defined(JS_CPU_MIPS)
// If StackAlignment is a power of two, % is just two shifts.
// 16 - (x % 16) gives alignment, extra % 16 handles total == 0.
return align(stackBytes, StackAlignment);

View File

@ -944,8 +944,14 @@ mjit::Compiler::finishThisUp(JITScript **jitp)
JaegerSpew(JSpew_Insns, "## Fast code (masm) size = %lu, Slow code (stubcc) size = %lu.\n",
(unsigned long) masm.size(), (unsigned long) stubcc.size());
/* To make inlineDoubles and oolDoubles aligned to sizeof(double) bytes,
MIPS adds extra sizeof(double) bytes to codeSize. */
size_t codeSize = masm.size() +
#if defined(JS_CPU_MIPS)
stubcc.size() + sizeof(double) +
#else
stubcc.size() +
#endif
(masm.numDoubles() * sizeof(double)) +
(stubcc.masm.numDoubles() * sizeof(double)) +
jumpTableOffsets.length() * sizeof(void *);
@ -1367,7 +1373,16 @@ mjit::Compiler::finishThisUp(JITScript **jitp)
/* Link fast and slow paths together. */
stubcc.fixCrossJumps(result, masm.size(), masm.size() + stubcc.size());
#if defined(JS_CPU_MIPS)
/* Make sure doubleOffset is aligned to sizeof(double) bytes. */
size_t doubleOffset = (((size_t)result + masm.size() + stubcc.size() +
sizeof(double) - 1) & (~(sizeof(double) - 1))) -
(size_t)result;
JS_ASSERT((((size_t)result + doubleOffset) & 7) == 0);
#else
size_t doubleOffset = masm.size() + stubcc.size();
#endif
double *inlineDoubles = (double *) (result + doubleOffset);
double *oolDoubles = (double*) (result + doubleOffset +
masm.numDoubles() * sizeof(double));
@ -3398,7 +3413,7 @@ mjit::Compiler::interruptCheckHelper()
void *interrupt = (void*) &JS_THREAD_DATA(cx)->interruptFlags;
#endif
#if defined(JS_CPU_X86) || defined(JS_CPU_ARM)
#if defined(JS_CPU_X86) || defined(JS_CPU_ARM) || defined(JS_CPU_MIPS)
jump = masm.branch32(Assembler::NotEqual, AbsoluteAddress(interrupt), Imm32(0));
#else
/* Handle processors that can't load from absolute addresses. */

View File

@ -1432,13 +1432,24 @@ mjit::Compiler::jsop_relational_double(JSOp op, BoolStub stub, jsbytecode *targe
stubcc.leave();
OOL_STUBCALL(stub, REJOIN_BRANCH);
if (!allocateLeft)
frame.pinReg(fpLeft);
if (!allocateRight)
frame.pinReg(fpRight);
frame.syncAndKillEverything();
Jump j = masm.branchDouble(dblCond, fpLeft, fpRight);
if (allocateLeft)
frame.freeReg(fpLeft);
else
frame.unpinKilledReg(fpLeft);
if (allocateRight)
frame.freeReg(fpRight);
else
frame.unpinKilledReg(fpRight);
frame.popn(2);

View File

@ -2324,6 +2324,12 @@ mjit::Compiler::jsop_stricteq(JSOp op)
masm.or32(result1, result);
}
frame.freeReg(result1);
#elif defined(JS_CPU_MIPS)
/* On MIPS the result 0.0/0.0 is 0x7FF7FFFF.
We need to manually set it to 0x7FF80000. */
static const int ShiftedCanonicalNaNType = 0x7FF80000 << 1;
masm.setShiftedCanonicalNaN(treg, treg);
masm.setPtr(oppositeCond, treg, Imm32(ShiftedCanonicalNaNType), result);
#elif !defined(JS_CPU_X64)
static const int ShiftedCanonicalNaNType = 0x7FF80000 << 1;
masm.setPtr(oppositeCond, treg, Imm32(ShiftedCanonicalNaNType), result);

View File

@ -1282,7 +1282,7 @@ FrameState::getCallee()
}
inline void
FrameState::unpinKilledReg(RegisterID reg)
FrameState::unpinKilledReg(AnyRegisterID reg)
{
regstate(reg).unpinUnsafe();
freeRegs.putReg(reg);

View File

@ -1498,10 +1498,11 @@ FrameState::syncAndKill(Registers kill, Uses uses, Uses ignore)
if (!fe || deadEntry(fe, ignore.nuses))
continue;
JS_ASSERT(fe->isTracked() && !fe->isType(JSVAL_TYPE_DOUBLE));
JS_ASSERT(fe->isTracked());
if (regstate(reg).type() == RematInfo::DATA) {
JS_ASSERT(fe->data.reg() == reg.reg());
JS_ASSERT_IF(reg.isFPReg(), fe->data.fpreg() == reg.fpreg());
JS_ASSERT_IF(!reg.isFPReg(), fe->data.reg() == reg.reg());
JS_ASSERT(fe->data.synced());
fe->data.setMemory();
} else {

View File

@ -806,7 +806,7 @@ class FrameState
/*
* Same as unpinReg(), but does not restore the FrameEntry.
*/
inline void unpinKilledReg(RegisterID reg);
inline void unpinKilledReg(AnyRegisterID reg);
/* Pins a data or type register if one exists. */
MaybeRegisterID maybePinData(FrameEntry *fe);

View File

@ -88,6 +88,23 @@ class Repatcher : public JSC::RepatchBuffer
*/
CheckIsStubCall(call.labelAtOffset(0));
JSC::RepatchBuffer::relink(call.callAtOffset(-4), stub);
#elif defined JS_CPU_MIPS
/*
* Stub calls on MIPS look like this:
*
* lui v0, hi(stub)
* ori v0, v0, lo(stub)
* lui t9, hi(JaegerStubVeneer)
* ori t9, t9, lo(JaegerStubVeneer)
* jalr t9
* nop
* call label -> xxx
*
* MIPS has to run stub calls through a veneer in order for THROW to
* work properly. The address that must be patched is the load into
* 'v0', not the load into 't9'.
*/
JSC::RepatchBuffer::relink(call.callAtOffset(-8), stub);
#else
# error
#endif
@ -95,7 +112,7 @@ class Repatcher : public JSC::RepatchBuffer
/* Patch the offset of a Value load emitted by loadValueWithAddressOffsetPatch. */
void patchAddressOffsetForValueLoad(CodeLocationLabel label, uint32_t offset) {
#if defined JS_CPU_X64 || defined JS_CPU_ARM || defined JS_CPU_SPARC
#if defined JS_CPU_X64 || defined JS_CPU_ARM || defined JS_CPU_SPARC || defined JS_CPU_MIPS
repatch(label.dataLabel32AtOffset(0), offset);
#elif defined JS_CPU_X86
static const unsigned LOAD_TYPE_OFFSET = 6;
@ -115,7 +132,7 @@ class Repatcher : public JSC::RepatchBuffer
}
void patchAddressOffsetForValueStore(CodeLocationLabel label, uint32_t offset, bool typeConst) {
#if defined JS_CPU_ARM || defined JS_CPU_X64 || defined JS_CPU_SPARC
#if defined JS_CPU_ARM || defined JS_CPU_X64 || defined JS_CPU_SPARC || defined JS_CPU_MIPS
(void) typeConst;
repatch(label.dataLabel32AtOffset(0), offset);
#elif defined JS_CPU_X86

View File

@ -122,6 +122,8 @@ struct Registers {
static const RegisterID JSFrameReg = JSC::ARMRegisters::r10;
#elif defined(JS_CPU_SPARC)
static const RegisterID JSFrameReg = JSC::SparcRegisters::l0;
#elif defined(JS_CPU_MIPS)
static const RegisterID JSFrameReg = JSC::MIPSRegisters::s0;
#endif
#if defined(JS_CPU_X86) || defined(JS_CPU_X64)
@ -152,6 +154,12 @@ struct Registers {
static const RegisterID ArgReg3 = JSC::SparcRegisters::o3;
static const RegisterID ArgReg4 = JSC::SparcRegisters::o4;
static const RegisterID ArgReg5 = JSC::SparcRegisters::o5;
#elif JS_CPU_MIPS
static const RegisterID ReturnReg = JSC::MIPSRegisters::v0;
static const RegisterID ArgReg0 = JSC::MIPSRegisters::a0;
static const RegisterID ArgReg1 = JSC::MIPSRegisters::a1;
static const RegisterID ArgReg2 = JSC::MIPSRegisters::a2;
static const RegisterID ArgReg3 = JSC::MIPSRegisters::a3;
#endif
static const RegisterID StackPointer = JSC::MacroAssembler::stackPointerRegister;
@ -252,6 +260,33 @@ struct Registers {
| (1 << JSC::SparcRegisters::l6)
| (1 << JSC::SparcRegisters::l7);
static const uint32_t SingleByteRegs = TempRegs | SavedRegs;
#elif defined(JS_CPU_MIPS)
static const uint32_t TempRegs =
(1 << JSC::MIPSRegisters::at)
| (1 << JSC::MIPSRegisters::v0)
| (1 << JSC::MIPSRegisters::v1)
| (1 << JSC::MIPSRegisters::a0)
| (1 << JSC::MIPSRegisters::a1)
| (1 << JSC::MIPSRegisters::a2)
| (1 << JSC::MIPSRegisters::a3)
| (1 << JSC::MIPSRegisters::t5)
| (1 << JSC::MIPSRegisters::t6)
| (1 << JSC::MIPSRegisters::t7);
/* t0-t4,t9 is reserved as a scratch register for the assembler.
We don't use t8 ($24), as we limit ourselves within $0 to $23 to
leave the bitmask for 8 FP registers. */
static const uint32_t SavedRegs =
(1 << JSC::MIPSRegisters::s1)
| (1 << JSC::MIPSRegisters::s2)
| (1 << JSC::MIPSRegisters::s3)
| (1 << JSC::MIPSRegisters::s4)
| (1 << JSC::MIPSRegisters::s5)
| (1 << JSC::MIPSRegisters::s6)
| (1 << JSC::MIPSRegisters::s7);
// s0 is reserved for JSFrameReg.
static const uint32_t SingleByteRegs = TempRegs | SavedRegs;
#else
# error "Unsupported platform"
@ -287,6 +322,8 @@ struct Registers {
return 4;
#elif defined(JS_CPU_SPARC)
return 6;
#elif defined(JS_CPU_MIPS)
return 4;
#endif
}
@ -337,6 +374,13 @@ struct Registers {
JSC::SparcRegisters::o4,
JSC::SparcRegisters::o5
};
#elif defined(JS_CPU_MIPS)
static const RegisterID regs[] = {
JSC::MIPSRegisters::a0,
JSC::MIPSRegisters::a1,
JSC::MIPSRegisters::a2,
JSC::MIPSRegisters::a3,
};
#endif
JS_ASSERT(numArgRegs(conv) == mozilla::ArrayLength(regs));
if (i > mozilla::ArrayLength(regs))
@ -386,6 +430,19 @@ struct Registers {
| (1 << JSC::SparcRegisters::f6)
) << TotalRegisters;
static const FPRegisterID FPConversionTemp = JSC::SparcRegisters::f8;
#elif defined(JS_CPU_MIPS)
/* TotalRegisters is 24, so TotalFPRegisters can be 8 to have a 32-bit
bit mask.
Note that the O32 ABI can access only even FP registers. */
static const uint32_t TotalFPRegisters = 8;
static const uint32_t TempFPRegs = (uint32_t)(
(1 << JSC::MIPSRegisters::f0)
| (1 << JSC::MIPSRegisters::f2)
| (1 << JSC::MIPSRegisters::f4)
| (1 << JSC::MIPSRegisters::f6)
) << TotalRegisters;
// f16 is reserved as a scratch register for the assembler.
static const FPRegisterID FPConversionTemp = JSC::MIPSRegisters::f18;
#else
# error "Unsupported platform"
#endif
@ -397,6 +454,8 @@ struct Registers {
static const RegisterID ClobberInCall = JSC::ARMRegisters::r2;
#elif defined(JS_CPU_SPARC)
static const RegisterID ClobberInCall = JSC::SparcRegisters::l1;
#elif defined(JS_CPU_MIPS)
static const RegisterID ClobberInCall = JSC::MIPSRegisters::at;
#endif
static const uint32_t AvailFPRegs = TempFPRegs;

View File

@ -253,7 +253,7 @@ JS_STATIC_ASSERT(offsetof(FrameRegs, sp) == 0);
#if defined(__GNUC__) && !defined(_WIN64)
/* If this assert fails, you need to realign VMFrame to 16 bytes. */
#ifdef JS_CPU_ARM
#if defined(JS_CPU_ARM) || defined(JS_CPU_MIPS)
JS_STATIC_ASSERT(sizeof(VMFrame) % 8 == 0);
#else
JS_STATIC_ASSERT(sizeof(VMFrame) % 16 == 0);
@ -822,6 +822,7 @@ SYMBOL_STRING(JaegerStubVeneer) ":" "\n"
);
# elif defined(JS_CPU_SPARC)
# elif defined(JS_CPU_MIPS)
# else
# error "Unsupported CPU!"
# endif

View File

@ -52,7 +52,8 @@
#if !defined JS_CPU_X64 && \
!defined JS_CPU_X86 && \
!defined JS_CPU_SPARC && \
!defined JS_CPU_ARM
!defined JS_CPU_ARM && \
!defined JS_CPU_MIPS
# error "Oh no, you should define a platform so this compiles."
#endif
@ -97,6 +98,13 @@ struct VMFrame
void *reserve_0;
void *reserve_1;
#elif defined(JS_CPU_MIPS)
/* Reserved 16 bytes for a0-a3 space in MIPS O32 ABI */
void *unused0;
void *unused1;
void *unused2;
void *unused3;
#endif
union Arguments {
@ -204,6 +212,22 @@ struct VMFrame
inline void** returnAddressLocation() {
return reinterpret_cast<void**>(&this->veneerReturn);
}
#elif defined(JS_CPU_MIPS)
void *savedS0;
void *savedS1;
void *savedS2;
void *savedS3;
void *savedS4;
void *savedS5;
void *savedS6;
void *savedS7;
void *savedGP;
void *savedRA;
void *unused4; // For alignment.
inline void** returnAddressLocation() {
return reinterpret_cast<void**>(this) - 1;
}
#else
# error "The VMFrame layout isn't defined for your processor architecture!"
#endif
@ -226,6 +250,9 @@ struct VMFrame
#if defined(JS_CPU_SPARC)
static const size_t offsetOfFp = 30 * sizeof(void *) + FrameRegs::offsetOfFp;
static const size_t offsetOfInlined = 30 * sizeof(void *) + FrameRegs::offsetOfInlined;
#elif defined(JS_CPU_MIPS)
static const size_t offsetOfFp = 8 * sizeof(void *) + FrameRegs::offsetOfFp;
static const size_t offsetOfInlined = 8 * sizeof(void *) + FrameRegs::offsetOfInlined;
#else
static const size_t offsetOfFp = 4 * sizeof(void *) + FrameRegs::offsetOfFp;
static const size_t offsetOfInlined = 4 * sizeof(void *) + FrameRegs::offsetOfInlined;
@ -237,7 +264,7 @@ struct VMFrame
}
};
#if defined(JS_CPU_ARM) || defined(JS_CPU_SPARC)
#if defined(JS_CPU_ARM) || defined(JS_CPU_SPARC) || defined(JS_CPU_MIPS)
// WARNING: Do not call this function directly from C(++) code because it is not ABI-compliant.
extern "C" void JaegerStubVeneer(void);
#endif

View File

@ -207,6 +207,12 @@ class NunboxAssembler : public JSC::MacroAssembler
JS_ASSERT(differenceBetween(start, load) == 0);
(void) load;
return start;
#elif defined JS_CPU_MIPS
/*
* On MIPS there are LUI/ORI to patch.
*/
load64WithPatch(address, treg, dreg, TAG_OFFSET, PAYLOAD_OFFSET);
return start;
#endif
}
@ -232,6 +238,12 @@ class NunboxAssembler : public JSC::MacroAssembler
return start;
#elif defined JS_CPU_ARM || defined JS_CPU_SPARC
return store64WithAddressOffsetPatch(treg, dreg, address);
#elif defined JS_CPU_MIPS
/*
* On MIPS there are LUI/ORI to patch.
*/
store64WithPatch(address, treg, dreg, TAG_OFFSET, PAYLOAD_OFFSET);
return start;
#endif
}
@ -248,6 +260,12 @@ class NunboxAssembler : public JSC::MacroAssembler
return start;
#elif defined JS_CPU_ARM || defined JS_CPU_SPARC
return store64WithAddressOffsetPatch(type, dreg, address);
#elif defined JS_CPU_MIPS
/*
* On MIPS there are LUI/ORI to patch.
*/
store64WithPatch(address, type, dreg, TAG_OFFSET, PAYLOAD_OFFSET);
return start;
#endif
}
@ -267,6 +285,12 @@ class NunboxAssembler : public JSC::MacroAssembler
return start;
#elif defined JS_CPU_ARM || defined JS_CPU_SPARC
return store64WithAddressOffsetPatch(type, payload, address);
#elif defined JS_CPU_MIPS
/*
* On MIPS there are LUI/ORI to patch.
*/
store64WithPatch(address, type, payload, TAG_OFFSET, PAYLOAD_OFFSET);
return start;
#endif
}
@ -470,6 +494,12 @@ class NunboxAssembler : public JSC::MacroAssembler
#elif defined JS_CPU_ARM
// Yes, we are backwards from SPARC.
fastStoreDouble(srcDest, dataReg, typeReg);
#elif defined JS_CPU_MIPS
#if defined(IS_LITTLE_ENDIAN)
fastStoreDouble(srcDest, dataReg, typeReg);
#else
fastStoreDouble(srcDest, typeReg, dataReg);
#endif
#else
JS_NOT_REACHED("implement this - push double, pop pop is easiest");
#endif

View File

@ -0,0 +1,344 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=4 sw=4 et tw=99:
*
* ***** 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 Jaegermonkey.
*
* The Initial Developer of the Original Code is the Mozilla Foundation.
*
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Chao-ying Fu <fu@mips.com>
*
* 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 "jstypes.h"
/*
* The MIPS VMFrame is 112 bytes as follows.
*
* 108 [ unused4 ] For alignment.
* 104 [ ra ]
* 100 [ gp ] If PIC code is generated, we will save gp.
* 96 [ s7 ]
* 92 [ s6 ]
* 88 [ s5 ]
* 84 [ s4 ]
* 80 [ s3 ]
* 76 [ s2 ]
* 72 [ s1 ]
* 68 [ s0 ]
* 64 [ stubRejoin ]
* 60 [ entrycode ]
* 56 [ entryfp ]
* 52 [ stkLimit ]
* 48 [ cx ]
* 44 [ regs.fp_ ]
* 40 [ regs.inlined_]
* 36 [ regs.pc ]
* 32 [ regs.sp ]
* 28 [ scratch ]
* 24 [ previous ]
* 20 [ args.ptr2 ] [ dynamicArgc ] (union)
* 16 [ args.ptr ] [ lazyArgsObj ] (union)
* 12 [ unused3 ] O32 ABI, space for a3 (used in callee)
* 8 [ unused2 ] O32 ABI, space for a2 (used in callee)
* 4 [ unused1 ] O32 ABI, space for a1 (used in callee)
* 0 [ unused0 ] O32 ABI, space for a0 (used in callee)
*/
asm (
".text" "\n"
".align 2" "\n"
".set noreorder" "\n"
".set nomacro" "\n"
".set nomips16" "\n"
".globl JaegerThrowpoline" "\n"
".ent JaegerThrowpoline" "\n"
".type JaegerThrowpoline,@function" "\n"
"JaegerThrowpoline:" "\n"
#if defined(__PIC__)
"lw $28,100($29)" "\n"
"la $25,js_InternalThrow" "\n"
".reloc 1f,R_MIPS_JALR,js_InternalThrow" "\n"
"1: jalr $25" "\n"
"move $4,$29 # set up a0" "\n"
#else
"jal js_InternalThrow" "\n"
"move $4,$29 # set up a0" "\n"
#endif
"beq $2,$0,1f" "\n"
"nop" "\n"
"jr $2 # jump to a scripted handler" "\n"
"nop" "\n"
"1:" "\n"
#if defined(__PIC__)
"lw $28,100($29)" "\n"
"la $25,PopActiveVMFrame" "\n"
".reloc 1f,R_MIPS_JALR,PopActiveVMFrame" "\n"
"1: jalr $25" "\n"
"move $4,$29 # set up a0" "\n"
#else
"jal PopActiveVMFrame" "\n"
"move $4,$29 # set up a0" "\n"
#endif
"lw $31,104($29)" "\n"
#if defined(__PIC__)
"lw $28,100($29)" "\n"
#endif
"lw $23,96($29)" "\n"
"lw $22,92($29)" "\n"
"lw $21,88($29)" "\n"
"lw $20,84($29)" "\n"
"lw $19,80($29)" "\n"
"lw $18,76($29)" "\n"
"lw $17,72($29)" "\n"
"lw $16,68($29)" "\n"
"li $2,0 # return 0 to represent an unhandled exception." "\n"
"jr $31" "\n"
"addiu $29,$29,112" "\n"
".set reorder" "\n"
".set macro" "\n"
".end JaegerThrowpoline" "\n"
".size JaegerThrowpoline,.-JaegerThrowpoline" "\n"
);
asm (
".text" "\n"
".align 2" "\n"
".set noreorder" "\n"
".set nomacro" "\n"
".set nomips16" "\n"
".globl JaegerTrampoline" "\n"
".ent JaegerTrampoline" "\n"
".type JaegerTrampoline,@function" "\n"
"JaegerTrampoline:" "\n"
#if defined(__PIC__)
"lui $28,%hi(_gp_disp)" "\n"
"addiu $28,$28,%lo(_gp_disp)" "\n"
"addu $28,$28,$25" "\n"
#endif
"addiu $29,$29,-112" "\n"
"sw $31,104($29)" "\n"
#if defined(__PIC__)
"sw $28,100($29)" "\n"
#endif
"sw $23,96($29)" "\n"
"sw $22,92($29)" "\n"
"sw $21,88($29)" "\n"
"sw $20,84($29)" "\n"
"sw $19,80($29)" "\n"
"sw $18,76($29)" "\n"
"sw $17,72($29)" "\n"
"sw $16,68($29)" "\n"
"sw $0,64($29) # stubRejoin" "\n"
"sw $5,60($29) # entrycode" "\n"
"sw $5,56($29) # entryfp" "\n"
"sw $7,52($29) # stackLimit" "\n"
"sw $4,48($29) # cx" "\n"
"sw $5,44($29) # regs.fp" "\n"
"move $16,$5 # preserve fp to s0" "\n"
"move $17,$6 # preserve code to s1" "\n"
#if defined(__PIC__)
"la $25,PushActiveVMFrame" "\n"
".reloc 1f,R_MIPS_JALR,PushActiveVMFrame" "\n"
"1: jalr $25" "\n"
"move $4,$29 # set up a0" "\n"
#else
"jal PushActiveVMFrame" "\n"
"move $4,$29 # set up a0" "\n"
#endif
"move $25,$17 # move code to $25" "\n"
"jr $25 # jump to the compiled JavaScript Function" "\n"
"nop" "\n"
".set reorder" "\n"
".set macro" "\n"
".end JaegerTrampoline" "\n"
".size JaegerTrampoline,.-JaegerTrampoline" "\n"
);
asm (
".text" "\n"
".align 2" "\n"
".set noreorder" "\n"
".set nomacro" "\n"
".set nomips16" "\n"
".globl JaegerTrampolineReturn" "\n"
".ent JaegerTrampolineReturn" "\n"
".type JaegerTrampolineReturn,@function" "\n"
"JaegerTrampolineReturn:" "\n"
#if defined(IS_LITTLE_ENDIAN)
"sw $4,28($16) # a0: fp->rval type for LITTLE-ENDIAN" "\n"
"sw $6,24($16) # a2: fp->rval data for LITTLE-ENDIAN" "\n"
#else
"sw $4,24($16) # a0: fp->rval type for BIG-ENDIAN" "\n"
"sw $6,28($16) # a2: fp->rval data for BIG-ENDIAN" "\n"
#endif
#if defined(__PIC__)
"lw $28,100($29)" "\n"
"la $25,PopActiveVMFrame" "\n"
".reloc 1f,R_MIPS_JALR,PopActiveVMFrame" "\n"
"1: jalr $25" "\n"
"move $4,$29 # set up a0" "\n"
#else
"jal PopActiveVMFrame" "\n"
"move $4,$29 # set up a0" "\n"
#endif
"lw $31,104($29)" "\n"
#if defined(__PIC__)
"lw $28,100($29)" "\n"
#endif
"lw $23,96($29)" "\n"
"lw $22,92($29)" "\n"
"lw $21,88($29)" "\n"
"lw $20,84($29)" "\n"
"lw $19,80($29)" "\n"
"lw $18,76($29)" "\n"
"lw $17,72($29)" "\n"
"lw $16,68($29)" "\n"
"li $2,1 # return ture to indicate successful completion" "\n"
"jr $31" "\n"
"addiu $29,$29,112" "\n"
".set reorder" "\n"
".set macro" "\n"
".end JaegerTrampolineReturn" "\n"
".size JaegerTrampolineReturn,.-JaegerTrampolineReturn" "\n"
);
asm (
".text" "\n"
".align 2" "\n"
".set noreorder" "\n"
".set nomacro" "\n"
".set nomips16" "\n"
".globl JaegerStubVeneer" "\n"
".ent JaegerStubVeneer" "\n"
".type JaegerStubVeneer,@function" "\n"
"JaegerStubVeneer:" "\n"
"addiu $29,$29,-24 # Need 16 (a0-a3) + 4 (align) + 4 ($31) bytes" "\n"
"sw $31,20($29) # Store $31 to 20($29)" "\n"
"move $25,$2 # the target address is passed from $2" "\n"
"jalr $25" "\n"
"nop" "\n"
"lw $31,20($29)" "\n"
"jr $31" "\n"
"addiu $29,$29,24" "\n"
".set reorder" "\n"
".set macro" "\n"
".end JaegerStubVeneer" "\n"
".size JaegerStubVeneer,.-JaegerStubVeneer" "\n"
);
asm (
".text" "\n"
".align 2" "\n"
".set noreorder" "\n"
".set nomacro" "\n"
".set nomips16" "\n"
".globl JaegerInterpolineScripted" "\n"
".ent JaegerInterpolineScripted" "\n"
".type JaegerInterpolineScripted,@function" "\n"
"JaegerInterpolineScripted:" "\n"
"lw $16,16($16) # Load f->prev_" "\n"
"b JaegerInterpoline" "\n"
"sw $16,44($29) # Update f->regs->fp_" "\n"
".set reorder" "\n"
".set macro" "\n"
".end JaegerInterpolineScripted" "\n"
".size JaegerInterpolineScripted,.-JaegerInterpolineScripted" "\n"
);
asm (
".text" "\n"
".align 2" "\n"
".set noreorder" "\n"
".set nomacro" "\n"
".set nomips16" "\n"
".globl JaegerInterpoline" "\n"
".ent JaegerInterpoline" "\n"
".type JaegerInterpoline,@function" "\n"
"JaegerInterpoline:" "\n"
"move $5,$4 # returntype" "\n"
"move $4,$6 # returnData" "\n"
"move $6,$2 # returnReg" "\n"
#if defined(__PIC__)
"lw $28,100($29)" "\n"
"la $25,js_InternalInterpret" "\n"
".reloc 1f,R_MIPS_JALR,js_InternalInterpret" "\n"
"1: jalr $25" "\n"
"move $7,$29 # f" "\n"
#else
"jal js_InternalInterpret" "\n"
"move $7,$29 # f" "\n"
#endif
"lw $16,44($29) # Load f->regs->fp_ to s0" "\n"
#if defined(IS_LITTLE_ENDIAN)
"lw $4,28($16) # a0: fp->rval type for LITTLE-ENDIAN" "\n"
"lw $6,24($16) # a2: fp->rval data for LITTLE-ENDIAN" "\n"
#else
"lw $4,24($16) # a0: fp->rval type for BIG-ENDIAN" "\n"
"lw $6,28($16) # a2: fp->rval data for BIG-ENDIAN" "\n"
#endif
"lw $5,28($29) # Load sctrach -> argc" "\n"
"beq $2,$0,1f" "\n"
"nop" "\n"
"jr $2" "\n"
"nop" "\n"
"1:" "\n"
#if defined(__PIC__)
"lw $28,100($29)" "\n"
"la $25,PopActiveVMFrame" "\n"
".reloc 1f,R_MIPS_JALR,PopActiveVMFrame" "\n"
"1: jalr $25" "\n"
"move $4,$29 # set up a0" "\n"
#else
"jal PopActiveVMFrame" "\n"
"move $4,$29 # set up a0" "\n"
#endif
"lw $31,104($29)" "\n"
#if defined(__PIC__)
"lw $28,100($29)" "\n"
#endif
"lw $23,96($29)" "\n"
"lw $22,92($29)" "\n"
"lw $21,88($29)" "\n"
"lw $20,84($29)" "\n"
"lw $19,80($29)" "\n"
"lw $18,76($29)" "\n"
"lw $17,72($29)" "\n"
"lw $16,68($29)" "\n"
"li $2,0 # return 0" "\n"
"jr $31" "\n"
"addiu $29,$29,112" "\n"
".set reorder" "\n"
".set macro" "\n"
".end JaegerInterpoline" "\n"
".size JaegerInterpoline,.-JaegerInterpoline" "\n"
);

View File

@ -196,7 +196,7 @@ const CharacterInfo js_charinfo[] = {
{58272, 0, 2},
};
const uint16_t index1[] = {
const uint8_t index1[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 34,
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
@ -256,7 +256,7 @@ const uint16_t index1[] = {
26, 26, 26, 26, 164, 165, 166, 167, 168, 169, 26, 170, 171, 172, 173, 174,
};
const uint16_t index2[] = {
const uint8_t index2[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2,

View File

@ -160,14 +160,14 @@ class CharacterInfo {
}
};
extern const uint16_t index1[];
extern const uint16_t index2[];
extern const uint8_t index1[];
extern const uint8_t index2[];
extern const CharacterInfo js_charinfo[];
inline const CharacterInfo&
CharInfo(jschar code)
{
uint16_t index = index1[code >> 6];
size_t index = index1[code >> 6];
index = index2[(index << 6) + (code & 0x3f)];
return js_charinfo[index];

View File

@ -267,13 +267,13 @@ if (typeof reportCompare === "function")
data_file.write('\n')
def dump(data, name, file):
file.write('const uint16_t ' + name + '[] = {\n')
file.write('const uint8_t ' + name + '[] = {\n')
line = pad = ' ' * 4
lines = []
for entry in data:
assert entry < 256
s = str(entry)
assert len(s) <= 3
s = s.rjust(3)
if len(line + s) + 5 > 99:

View File

@ -58,7 +58,9 @@
static int gDummyCounter;
static void
// Not inlining this function avoids the compiler making optimizations
// that end up corrupting stack traces.
MOZ_NEVER_INLINE static void
TouchBadMemory()
{
// XXX this should use the frame poisoning code

View File

@ -66,6 +66,7 @@ class ConfirmPreference extends DialogPreference {
GeckoAppShell.getHandler().post(new Runnable(){
public void run() {
BrowserDB.clearHistory(mContext.getContentResolver());
GeckoApp.mAppContext.mFavicons.clearFavicons();
}
});
} else if ("clear_private_data".equalsIgnoreCase(mAction)) {

View File

@ -152,6 +152,12 @@ public class Favicons {
db.replace(TABLE_NAME, null, values);
}
public void clearFavicons() {
SQLiteDatabase db = mDbHelper.getWritableDatabase();
db.delete(TABLE_NAME, null, null);
}
}
public Favicons(Context context) {
@ -199,6 +205,10 @@ public class Favicons {
return task.cancel(false);
}
public void clearFavicons() {
mDbHelper.clearFavicons();
}
public void close() {
Log.d(LOGTAG, "Closing Favicons database");
mDbHelper.close();

View File

@ -573,9 +573,8 @@ public class GeckoAppShell
GeckoApp.mAppContext.getSystemService(Context.LOCATION_SERVICE);
if (enable) {
Criteria crit = new Criteria();
crit.setAccuracy(Criteria.ACCURACY_FINE);
String provider = lm.getBestProvider(crit, true);
Criteria criteria = new Criteria();
String provider = lm.getBestProvider(criteria, true);
if (provider == null)
return;

View File

@ -178,6 +178,9 @@ public class GeckoInputConnection
if (content == null)
return null;
if ((flags & GET_EXTRACTED_TEXT_MONITOR) != 0)
mUpdateRequest = req;
ExtractedText extract = new ExtractedText();
extract.flags = 0;
extract.partialStartOffset = -1;
@ -200,6 +203,14 @@ public class GeckoInputConnection
return extract;
}
@Override
public boolean setSelection(int start, int end) {
GeckoAppShell.sendEventToGecko(
new GeckoEvent(GeckoEvent.IME_SET_SELECTION, start, end - start));
return super.setSelection(start, end);
}
@Override
public boolean setComposingText(CharSequence text, int newCursorPosition) {
replaceText(text, newCursorPosition, true);
@ -337,33 +348,64 @@ public class GeckoInputConnection
public void notifyTextChange(InputMethodManager imm, String text,
int start, int oldEnd, int newEnd) {
if (mBatchMode)
if (!mBatchMode) {
if (!text.contentEquals(mEditable)) {
if (DEBUG) Log.d(LOGTAG, String.format(". . . notifyTextChange: current mEditable=\"%s\"",
mEditable.toString()));
setEditable(text);
}
}
if (mUpdateRequest == null)
return;
if (!text.contentEquals(mEditable)) {
if (DEBUG) Log.d(LOGTAG, String.format(". . . notifyTextChange: current mEditable=\"%s\"",
mEditable.toString()));
setEditable(text);
View v = GeckoApp.mAppContext.getLayerController().getView();
if (imm == null) {
imm = (InputMethodManager)v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm == null)
return;
}
mUpdateExtract.flags = 0;
// We update from (0, oldEnd) to (0, newEnd) because some Android IMEs
// assume that updates start at zero, according to jchen.
mUpdateExtract.partialStartOffset = 0;
mUpdateExtract.partialEndOffset = oldEnd;
// Faster to not query for selection
mUpdateExtract.selectionStart = newEnd;
mUpdateExtract.selectionEnd = newEnd;
mUpdateExtract.text = text.substring(0, newEnd);
mUpdateExtract.startOffset = 0;
imm.updateExtractedText(v, mUpdateRequest.token, mUpdateExtract);
}
public void notifySelectionChange(InputMethodManager imm,
int start, int end) {
if (mBatchMode)
return;
if (!mBatchMode) {
final Editable content = getEditable();
int a = Selection.getSelectionStart(content);
int b = Selection.getSelectionEnd(content);
if (start != a || end != b) {
if (DEBUG) Log.d(LOGTAG, String.format(". . . notifySelectionChange: current editable selection: [%d, %d]", a, b));
super.setSelection(start, end);
}
}
final Editable content = getEditable();
int a = Selection.getSelectionStart(content);
int b = Selection.getSelectionEnd(content);
if (start != a || end != b) {
if (DEBUG) Log.d(LOGTAG, String.format(". . . notifySelectionChange: current editable selection: [%d, %d]", a, b));
setSelection(start, end);
if (imm != null && imm.isFullscreenMode()) {
View v = GeckoApp.mAppContext.getLayerController().getView();
imm.updateSelection(v, start, end, -1, -1);
}
}
public void reset() {
mComposing = false;
mBatchMode = false;
mUpdateRequest = null;
}
// TextWatcher
@ -504,12 +546,20 @@ public class GeckoInputConnection
// KeyListener returns true if it handled the event for us.
if (mIMEState == IME_STATE_DISABLED ||
keyCode == KeyEvent.KEYCODE_ENTER ||
keyCode == KeyEvent.KEYCODE_DEL ||
keyCode == KeyEvent.KEYCODE_TAB ||
(event.getFlags() & KeyEvent.FLAG_SOFT_KEYBOARD) != 0 ||
!mKeyListener.onKeyDown(v, mEditable, keyCode, event))
keyCode == KeyEvent.KEYCODE_ENTER ||
keyCode == KeyEvent.KEYCODE_DEL ||
keyCode == KeyEvent.KEYCODE_TAB ||
(event.getFlags() & KeyEvent.FLAG_SOFT_KEYBOARD) != 0 ||
!mKeyListener.onKeyDown(v, mEditable, keyCode, event)) {
// Make sure selection in Gecko is up-to-date
final Editable content = getEditable();
int a = Selection.getSelectionStart(content);
int b = Selection.getSelectionEnd(content);
GeckoAppShell.sendEventToGecko(
new GeckoEvent(GeckoEvent.IME_SET_SELECTION, a, b - a));
GeckoAppShell.sendEventToGecko(new GeckoEvent(event));
}
return true;
}
@ -576,11 +626,9 @@ public class GeckoInputConnection
if (v == null)
return;
if (DEBUG) Log.d(LOGTAG, "notifyIME v!= null");
switch (type) {
case NOTIFY_IME_RESETINPUTSTATE:
if (DEBUG) Log.d(LOGTAG, "notifyIME = reset");
if (DEBUG) Log.d(LOGTAG, ". . . notifyIME: reset");
// Composition event is already fired from widget.
// So reset IME flags.
@ -603,12 +651,12 @@ public class GeckoInputConnection
break;
case NOTIFY_IME_CANCELCOMPOSITION:
if (DEBUG) Log.d(LOGTAG, "notifyIME = cancel");
if (DEBUG) Log.d(LOGTAG, ". . . notifyIME: cancel");
IMEStateUpdater.resetIME();
break;
case NOTIFY_IME_FOCUSCHANGE:
if (DEBUG) Log.d(LOGTAG, "notifyIME = focus");
if (DEBUG) Log.d(LOGTAG, ". . . notifyIME: focus");
IMEStateUpdater.resetIME();
break;
}
@ -747,6 +795,9 @@ public class GeckoInputConnection
private boolean mBatchMode;
ExtractedTextRequest mUpdateRequest;
final ExtractedText mUpdateExtract = new ExtractedText();
int mSelectionStart, mSelectionLength;
SynchronousQueue<String> mQueryResult;
}
@ -867,15 +918,15 @@ class DebugGeckoInputConnection
@Override
public void notifyTextChange(InputMethodManager imm, String text,
int start, int oldEnd, int newEnd) {
Log.d(LOGTAG, String.format("IME: notifyTextChange: text=\"%s\" s=%d ne=%d oe=%d",
text, start, newEnd, oldEnd));
Log.d(LOGTAG, String.format("IME: >notifyTextChange(\"%s\", start=%d, oldEnd=%d, newEnd=%d)",
text, start, oldEnd, newEnd));
super.notifyTextChange(imm, text, start, oldEnd, newEnd);
}
@Override
public void notifySelectionChange(InputMethodManager imm,
int start, int end) {
Log.d(LOGTAG, String.format("IME: notifySelectionChange: s=%d e=%d", start, end));
Log.d(LOGTAG, String.format("IME: >notifySelectionChange(start=%d, end=%d)", start, end));
super.notifySelectionChange(imm, start, end);
}
@ -888,7 +939,7 @@ class DebugGeckoInputConnection
@Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{
Log.d(LOGTAG, String.format("IME: onTextChanged: t=\"%s\" s=%d b=%d l=%d", s, start, before, count));
Log.d(LOGTAG, String.format("IME: onTextChanged(\"%s\" start=%d, before=%d, count=%d)", s, start, before, count));
super.onTextChanged(s, start, before, count);
}
@ -945,14 +996,14 @@ class DebugGeckoInputConnection
@Override
public void notifyIME(int type, int state) {
Log.d(LOGTAG, String.format("IME: notifyIME(%d, %d)", type, state));
Log.d(LOGTAG, String.format("IME: >notifyIME(type=%d, state=%d)", type, state));
super.notifyIME(type, state);
}
@Override
public void notifyIMEChange(String text, int start, int end, int newEnd) {
Log.d(LOGTAG, String.format("IME: notifyIMEChange: t=\"%s\" s=%d ne=%d oe=%d",
text, start, newEnd, end));
Log.d(LOGTAG, String.format("IME: >notifyIMEChange(\"%s\", start=%d, end=%d, newEnd=%d)",
text, start, end, newEnd));
super.notifyIMEChange(text, start, end, newEnd);
}
}

View File

@ -178,15 +178,6 @@ public class LayerController {
mView.requestRender();
}
/** Scrolls the viewport to the given point. You must hold the monitor while calling this. */
public void scrollTo(PointF point) {
mViewportMetrics.setOrigin(point);
Log.d(LOGTAG, "scrollTo: " + mViewportMetrics);
notifyLayerClientOfGeometryChange();
GeckoApp.mAppContext.repositionPluginViews(false);
mView.requestRender();
}
/** Scrolls the viewport by the given offset. You must hold the monitor while calling this. */
public void scrollBy(PointF point) {
PointF origin = mViewportMetrics.getOrigin();
@ -199,15 +190,6 @@ public class LayerController {
mView.requestRender();
}
/** Sets the current viewport. You must hold the monitor while calling this. */
public void setViewport(RectF viewport) {
mViewportMetrics.setViewport(viewport);
Log.d(LOGTAG, "setViewport: " + mViewportMetrics);
notifyLayerClientOfGeometryChange();
GeckoApp.mAppContext.repositionPluginViews(false);
mView.requestRender();
}
/** Sets the current page size. You must hold the monitor while calling this. */
public void setPageSize(FloatSize size) {
if (mViewportMetrics.getPageSize().fuzzyEquals(size))
@ -230,15 +212,16 @@ public class LayerController {
public void setViewportMetrics(ViewportMetrics viewport) {
mViewportMetrics = new ViewportMetrics(viewport);
Log.d(LOGTAG, "setViewportMetrics: " + mViewportMetrics);
GeckoApp.mAppContext.repositionPluginViews(false);
// this function may or may not be called on the UI thread,
// but repositionPluginViews must only be called on the UI thread.
GeckoApp.mAppContext.runOnUiThread(new Runnable() {
public void run() {
GeckoApp.mAppContext.repositionPluginViews(false);
}
});
mView.requestRender();
}
/** Scales the viewport. You must hold the monitor while calling this. */
public void scaleTo(float zoomFactor) {
scaleWithFocus(zoomFactor, new PointF(0,0));
}
/**
* Scales the viewport, keeping the given focus point in the same place before and after the
* scale operation. You must hold the monitor while calling this.
@ -254,16 +237,6 @@ public class LayerController {
mView.requestRender();
}
/**
* Sets the viewport origin and scales in one operation. You must hold the monitor while
* calling this.
*/
public void scaleWithOrigin(float zoomFactor, PointF origin) {
mViewportMetrics.setOrigin(origin);
Log.d(LOGTAG, "scaleWithOrigin: " + mViewportMetrics + "; zf=" + zoomFactor);
scaleTo(zoomFactor);
}
public boolean post(Runnable action) { return mView.post(action); }
public void setOnTouchListener(OnTouchListener onTouchListener) {

View File

@ -56,10 +56,10 @@
<!ENTITY pref_clear_history_confirm "Browsing history will be deleted">
<!ENTITY pref_clear_private_data "Clear private data">
<!ENTITY pref_clear_private_data_confirm "Browsing settings, including passwords and cookies, will be deleted">
<!ENTITY pref_enable_plugins "Enable plugins">
<!ENTITY pref_enable_plugins_yes "Yes">
<!ENTITY pref_enable_plugins_tap_to_play "Tap to play">
<!ENTITY pref_enable_plugins_no "No">
<!ENTITY pref_plugins "Plugins">
<!ENTITY pref_plugins_enabled "Enabled">
<!ENTITY pref_plugins_tap_to_play "Tap to play">
<!ENTITY pref_plugins_disabled "Disabled">
<!ENTITY pref_font_size "Font size">
<!ENTITY pref_font_size_small "Small">
<!ENTITY pref_font_size_medium "Medium">

View File

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="pref_enable_plugins_entries">
<item>@string/pref_enable_plugins_yes</item>
<item>@string/pref_enable_plugins_tap_to_play</item>
<item>@string/pref_enable_plugins_no</item>
<string-array name="pref_plugins_entries">
<item>@string/pref_plugins_enabled</item>
<item>@string/pref_plugins_tap_to_play</item>
<item>@string/pref_plugins_disabled</item>
</string-array>
<string-array name="pref_enable_plugins_values">
<string-array name="pref_plugins_values">
<item>1</item>
<item>2</item>
<item>0</item>

View File

@ -20,9 +20,9 @@
android:persistent="false" />
<ListPreference android:key="plugin.enable"
android:title="@string/pref_enable_plugins"
android:entries="@array/pref_enable_plugins_entries"
android:entryValues="@array/pref_enable_plugins_values"
android:title="@string/pref_plugins"
android:entries="@array/pref_plugins_entries"
android:entryValues="@array/pref_plugins_values"
android:persistent="false" />
<ListPreference android:key="font.size.inflation.minTwips"

View File

@ -62,10 +62,10 @@
<string name="pref_clear_history_confirm">&pref_clear_history_confirm;</string>
<string name="pref_clear_private_data">&pref_clear_private_data;</string>
<string name="pref_clear_private_data_confirm">&pref_clear_private_data_confirm;</string>
<string name="pref_enable_plugins">&pref_enable_plugins;</string>
<string name="pref_enable_plugins_yes">&pref_enable_plugins_yes;</string>
<string name="pref_enable_plugins_tap_to_play">&pref_enable_plugins_tap_to_play;</string>
<string name="pref_enable_plugins_no">&pref_enable_plugins_no;</string>
<string name="pref_plugins">&pref_plugins;</string>
<string name="pref_plugins_enabled">&pref_plugins_enabled;</string>
<string name="pref_plugins_tap_to_play">&pref_plugins_tap_to_play;</string>
<string name="pref_plugins_disabled">&pref_plugins_disabled;</string>
<string name="pref_font_size">&pref_font_size;</string>
<string name="pref_font_size_small">&pref_font_size_small;</string>
<string name="pref_font_size_medium">&pref_font_size_medium;</string>

View File

@ -665,18 +665,27 @@ public class PanZoomController
FloatSize pageSize = viewportMetrics.getPageSize();
RectF viewport = viewportMetrics.getViewport();
float focusX = viewport.width() / 2.0f;
float focusY = viewport.height() / 2.0f;
float minZoomFactor = 0.0f;
if (viewport.width() > pageSize.width && pageSize.width > 0) {
float scaleFactor = viewport.width() / pageSize.width;
minZoomFactor = Math.max(minZoomFactor, zoomFactor * scaleFactor);
focusX = 0.0f;
}
if (viewport.height() > pageSize.height && pageSize.height > 0) {
float scaleFactor = viewport.height() / pageSize.height;
minZoomFactor = Math.max(minZoomFactor, zoomFactor * scaleFactor);
focusY = 0.0f;
}
if (!FloatUtils.fuzzyEquals(minZoomFactor, 0.0f)) {
PointF center = new PointF(viewport.width() / 2.0f, viewport.height() / 2.0f);
// if one (or both) of the page dimensions is smaller than the viewport,
// zoom using the top/left as the focus on that axis. this prevents the
// scenario where, if both dimensions are smaller than the viewport, but
// by different scale factors, we end up scrolled to the end on one axis
// after applying the scale
PointF center = new PointF(focusX, focusY);
viewportMetrics.scaleTo(minZoomFactor, center);
} else if (zoomFactor > MAX_ZOOM) {
PointF center = new PointF(viewport.width() / 2.0f, viewport.height() / 2.0f);

View File

@ -1501,8 +1501,8 @@ Tab.prototype = {
pageHeight = Math.max(body.scrollHeight, html.scrollHeight);
/* Transform the page width and height based on the zoom factor. */
pageWidth = Math.round(pageWidth * this._viewport.zoom);
pageHeight = Math.round(pageHeight * this._viewport.zoom);
pageWidth *= this._viewport.zoom;
pageHeight *= this._viewport.zoom;
/*
* Avoid sending page sizes of less than screen size before we hit DOMContentLoaded, because
@ -2029,15 +2029,19 @@ var BrowserEventHandler = {
} else if (aTopic == "Gesture:SingleTap") {
let element = this._highlightElement;
if (element && !FormAssistant.handleClick(element)) {
let data = JSON.parse(aData);
[data.x, data.y] = ElementTouchHelper.toScreenCoords(element.ownerDocument.defaultView, data.x, data.y);
this._sendMouseEvent("mousemove", element, data.x, data.y);
this._sendMouseEvent("mousedown", element, data.x, data.y);
this._sendMouseEvent("mouseup", element, data.x, data.y);
if (ElementTouchHelper.isElementClickable(element))
Haptic.performSimpleAction(Haptic.LongPress);
try {
let data = JSON.parse(aData);
[data.x, data.y] = ElementTouchHelper.toScreenCoords(element.ownerDocument.defaultView, data.x, data.y);
this._sendMouseEvent("mousemove", element, data.x, data.y);
this._sendMouseEvent("mousedown", element, data.x, data.y);
this._sendMouseEvent("mouseup", element, data.x, data.y);
if (ElementTouchHelper.isElementClickable(element))
Haptic.performSimpleAction(Haptic.LongPress);
} catch(e) {
Cu.reportError(e);
}
}
this._cancelTapHighlight();
} else if (aTopic == "Gesture:DoubleTap") {
@ -2146,10 +2150,15 @@ var BrowserEventHandler = {
}
}
[aX, aY] = ElementTouchHelper.toBrowserCoords(aElement.ownerDocument.defaultView, aX, aY);
let cwu = aElement.ownerDocument.defaultView.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
aButton = aButton || 0;
cwu.sendMouseEventToWindow(aName, Math.round(aX), Math.round(aY), aButton, 1, 0, true);
let window = aElement.ownerDocument.defaultView;
try {
[aX, aY] = ElementTouchHelper.toBrowserCoords(window, aX, aY);
let cwu = window.top.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
aButton = aButton || 0;
cwu.sendMouseEventToWindow(aName, Math.round(aX), Math.round(aY), aButton, 1, 0, true);
} catch(e) {
Cu.reportError(e);
}
},
_hasScrollableOverflow: function(elem) {
@ -2251,24 +2260,36 @@ const kReferenceDpi = 240; // standard "pixel" size used in some preferences
const ElementTouchHelper = {
toBrowserCoords: function(aWindow, aX, aY) {
let tab = BrowserApp.selectedTab;
if (aWindow) {
let browser = BrowserApp.getBrowserForWindow(aWindow);
tab = BrowserApp.getTabForBrowser(browser);
}
if (!aWindow)
throw "Must provide a window";
let browser = BrowserApp.getBrowserForWindow(aWindow.top);
if (!browser)
throw "Unable to find a browser";
let tab = BrowserApp.getTabForBrowser(browser);
if (!tab)
throw "Unable to find a tab";
let viewport = tab.viewport;
return [
((aX-tab.viewportExcess.x)*viewport.zoom + viewport.offsetX),
((aY-tab.viewportExcess.y)*viewport.zoom + viewport.offsetY)
((aX - tab.viewportExcess.x) * viewport.zoom + viewport.offsetX),
((aY - tab.viewportExcess.y) * viewport.zoom + viewport.offsetY)
];
},
toScreenCoords: function(aWindow, aX, aY) {
let tab = BrowserApp.selectedTab;
if (aWindow) {
let browser = BrowserApp.getBrowserForWindow(aWindow);
tab = BrowserApp.getTabForBrowser(browser);
}
if (!aWindow)
throw "Must provide a window";
let browser = BrowserApp.getBrowserForWindow(aWindow.top);
if (!browser)
throw "Unable to find a browser";
let tab = BrowserApp.getTabForBrowser(browser);
if (!tab)
throw "Unable to find a tab";
let viewport = tab.viewport;
return [
(aX - viewport.offsetX)/viewport.zoom + tab.viewportExcess.x,
@ -3637,10 +3658,16 @@ var PermissionsHelper = {
// Keep track of permissions, so we know which ones to clear
this._currentPermissions = permissions;
let host;
try {
host = uri.host;
} catch(e) {
host = uri.spec;
}
sendMessageToJava({
gecko: {
type: "Permissions:Data",
host: uri.host,
host: host,
permissions: permissions
}
});

View File

@ -86,16 +86,16 @@ nsAboutBloat::NewChannel(nsIURI *aURI, nsIChannel **result)
if (clear) {
nsTraceRefcntImpl::ResetStatistics();
const char* msg = "Bloat statistics cleared.";
rv = NS_NewCStringInputStream(getter_AddRefs(inStr), nsDependentCString(msg));
rv = NS_NewCStringInputStream(getter_AddRefs(inStr),
NS_LITERAL_CSTRING("Bloat statistics cleared."));
if (NS_FAILED(rv)) return rv;
}
else if (leaks) {
// dump the current set of leaks.
GC_gcollect();
const char* msg = "Memory leaks dumped.";
rv = NS_NewCStringInputStream(getter_AddRefs(inStr), nsDependentCString(msg));
rv = NS_NewCStringInputStream(getter_AddRefs(inStr),
NS_LITERAL_CSTRING("Memory leaks dumped."));
if (NS_FAILED(rv)) return rv;
}
else {

View File

@ -57,6 +57,7 @@
#include "nsIApplicationCacheService.h"
#include "nsIOfflineCacheUpdate.h"
#include "nsIRedirectChannelRegistrar.h"
#include "prinit.h"
namespace mozilla {
namespace net {
@ -67,6 +68,9 @@ HttpChannelParent::HttpChannelParent(PBrowserParent* iframeEmbedding)
, mStoredProgress(0)
, mStoredProgressMax(0)
, mHeadersToSyncToChild(nsnull)
, mSentRedirect1Begin(false)
, mSentRedirect1BeginFailed(false)
, mReceivedRedirect2Verify(false)
{
// Ensure gHttpHandler is initialized: we need the atom table up and running.
nsIHttpProtocolHandler* handler;
@ -329,6 +333,11 @@ HttpChannelParent::RecvUpdateAssociatedContentSecurity(const PRInt32& high,
return true;
}
// Bug 621446 investigation, we don't want conditional PR_Aborts bellow to be
// merged to a single address.
#pragma warning(disable : 4068)
#pragma GCC optimize ("O0")
bool
HttpChannelParent::RecvRedirect2Verify(const nsresult& result,
const RequestHeaderTuples& changedHeaders)
@ -346,11 +355,30 @@ HttpChannelParent::RecvRedirect2Verify(const nsresult& result,
}
}
if (!mRedirectCallback) {
// Bug 621446 investigation (optimization turned off above)
if (mReceivedRedirect2Verify)
::PR_Abort();
if (mSentRedirect1BeginFailed)
::PR_Abort();
if (mSentRedirect1Begin && NS_FAILED(result))
::PR_Abort();
if (mSentRedirect1Begin && NS_SUCCEEDED(result))
::PR_Abort();
if (!mRedirectChannel)
::PR_Abort();
}
mReceivedRedirect2Verify = true;
mRedirectCallback->OnRedirectVerifyCallback(result);
mRedirectCallback = nsnull;
return true;
}
// Bug 621446 investigation
#pragma GCC reset_options
bool
HttpChannelParent::RecvDocumentChannelCleanup()
{
@ -568,8 +596,14 @@ HttpChannelParent::StartRedirect(PRUint32 newChannelId,
redirectFlags,
responseHead ? *responseHead
: nsHttpResponseHead());
if (!result)
if (!result) {
// Bug 621446 investigation
mSentRedirect1BeginFailed = true;
return NS_BINDING_ABORTED;
}
// Bug 621446 investigation
mSentRedirect1Begin = true;
// Result is handled in RecvRedirect2Verify above

View File

@ -138,6 +138,10 @@ private:
// used while visiting headers, to send them to child: else null
RequestHeaderTuples *mHeadersToSyncToChild;
bool mSentRedirect1Begin : 1;
bool mSentRedirect1BeginFailed : 1;
bool mReceivedRedirect2Verify : 1;
};
} // namespace net

View File

@ -529,15 +529,15 @@ SpdyStream::TransmitFrame(const char *buf,
LOG3(("SpdyStream::TransmitFrame for regular session=%p "
"stream=%p result %x len=%d",
mSession, this, rv, transmittedCount));
SpdySession::LogIO(mSession, this, "Writing from Transaction Buffer",
buf + offset, transmittedCount);
if (rv == NS_BASE_STREAM_WOULD_BLOCK)
mBlockedOnWrite = 1;
if (NS_FAILED(rv)) // this will include WOULD_BLOCK
return rv;
SpdySession::LogIO(mSession, this, "Writing from Transaction Buffer",
buf + offset, transmittedCount);
if (mUpstreamState == SENDING_REQUEST_BODY) {
mTransaction->OnTransportStatus(mSocketTransport,
nsISocketTransport::STATUS_SENDING_TO,

View File

@ -190,6 +190,11 @@ nsAutoCompleteController::StartSearch(const nsAString &aSearchString)
NS_IMETHODIMP
nsAutoCompleteController::HandleText()
{
// We should do nothing during composition.
if (mIsIMEComposing) {
return NS_OK;
}
if (!mInput) {
// Stop all searches in case they are async.
StopSearch();

View File

@ -118,6 +118,9 @@
testNormalFind();
gFindBar.close();
ok(gFindBar.hidden, "Failed to close findbar after testNormalFind");
testNormalFindWithComposition();
gFindBar.close();
ok(gFindBar.hidden, "findbar should be hidden after testNormalFindWithComposition");
testAutoCaseSensitivityUI();
testQuickFindText();
gFindBar.close();
@ -226,6 +229,60 @@
}
}
function testNormalFindWithComposition() {
document.getElementById("cmd_find").doCommand();
ok(!gFindBar.hidden, "testNormalFindWithComposition: findbar should be open");
ok(document.commandDispatcher.focusedElement == gFindBar._findField.inputField,
"testNormalFindWithComposition: find field should be focused");
var matchCaseCheckbox = gFindBar.getElement("find-case-sensitive");
var clicked = false;
if (!matchCaseCheckbox.hidden & matchCaseCheckbox.checked) {
matchCaseCheckbox.click();
clicked = true;
}
gFindBar._findField.inputField.focus();
var searchStr = "text";
synthesizeComposition({ type: "compositionstart" });
synthesizeComposition({ type: "compositionupdate", data: searchStr });
synthesizeText(
{ "composition":
{ "string": searchStr,
"clauses":
[
{ "length": searchStr.length, "attr": COMPOSITION_ATTR_RAWINPUT }
]
},
"caret": { "start": searchStr.length, "length": 0 }
});
ok(gBrowser.contentWindow.getSelection().toString().toLowerCase() != searchStr,
"testNormalFindWithComposition: text shouldn't be found during composition");
synthesizeText(
{ "composition":
{ "string": searchStr,
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": searchStr.length, "length": 0 }
});
synthesizeComposition({ type: "compositionend", data: searchStr });
ok(gBrowser.contentWindow.getSelection().toString().toLowerCase() == searchStr,
"testNormalFindWithComposition: text should be found after committing composition");
if (clicked) {
matchCaseCheckbox.click();
}
}
function testAutoCaseSensitivityUI() {
var matchCaseCheckbox = gFindBar.getElement("find-case-sensitive");
var matchCaseLabel = gFindBar.getElement("match-case-status");

View File

@ -113,6 +113,14 @@
<handlers>
<handler event="input"><![CDATA[
// We should do nothing during composition. E.g., composing string
// before converting may matches a forward word of expected word.
// After that, even if user converts the composition string to the
// expected word, it may find second or later searching word in the
// document.
if (this.findbar._isIMEComposing) {
return;
}
this.findbar._find(this.value);
]]></handler>

View File

@ -4,7 +4,6 @@
<!ENTITY props.path.label "Path:">
<!ENTITY props.secure.label "Send For:">
<!ENTITY props.expires.label "Expires:">
<!ENTITY props.policy.label "Policy:">
<!ENTITY button.allow.label "Allow">
<!ENTITY button.allow.accesskey "A">

View File

@ -220,8 +220,9 @@ var DownloadTaskbarProgressUpdater =
* 1. If the active window is the download window, then we always update
* the taskbar indicator.
* 2. If the active window isn't the download window, then we update only if
* the status is Normal, i.e. one or more downloads are currently
* progressing. If we aren't, then we clear the indicator.
* the status is normal or indeterminate. i.e. one or more downloads are
* currently progressing or in scan mode. If we aren't, then we clear the
* indicator.
*/
_updateTaskbar: function DTPU_updateTaskbar()
{
@ -230,9 +231,10 @@ var DownloadTaskbarProgressUpdater =
}
// If the active window is not the download manager window, set the state
// only if it is Normal
// only if it is normal or indeterminate.
if (this._activeWindowIsDownloadWindow ||
(this._taskbarState == Ci.nsITaskbarProgress.STATE_NORMAL)) {
(this._taskbarState == Ci.nsITaskbarProgress.STATE_NORMAL ||
this._taskbarState == Ci.nsITaskbarProgress.STATE_INDETERMINATE)) {
this._activeTaskbarProgress.setProgressState(this._taskbarState,
this._totalTransferred,
this._totalSize);

View File

@ -2801,6 +2801,10 @@ var gDetailView = {
gEventManager.unregisterAddonListener(this, this._addon.id);
gEventManager.unregisterInstallListener(this);
this._addon = null;
// Flush the preferences to disk so they survive any crash
if (this.node.getElementsByTagName("setting").length)
Services.prefs.savePrefFile(null);
}
},

View File

@ -1055,7 +1055,7 @@ AndroidBridge::OpenGraphicsLibraries()
mHasNativeWindowAccess = false;
mHasNativeBitmapAccess = false;
void *handle = dlopen("/system/lib/libjnigraphics.so", RTLD_LAZY | RTLD_LOCAL);
void *handle = dlopen("libjnigraphics.so", RTLD_LAZY | RTLD_LOCAL);
if (handle) {
AndroidBitmap_getInfo = (int (*)(JNIEnv *, jobject, void *))dlsym(handle, "AndroidBitmap_getInfo");
AndroidBitmap_lockPixels = (int (*)(JNIEnv *, jobject, void **))dlsym(handle, "AndroidBitmap_lockPixels");
@ -1068,7 +1068,7 @@ AndroidBridge::OpenGraphicsLibraries()
// Try to dlopen libandroid.so for and native window access on
// Android 2.3+ (API level 9)
handle = dlopen("/system/lib/libandroid.so", RTLD_LAZY | RTLD_LOCAL);
handle = dlopen("libandroid.so", RTLD_LAZY | RTLD_LOCAL);
if (handle) {
ANativeWindow_fromSurface = (void* (*)(JNIEnv*, jobject))dlsym(handle, "ANativeWindow_fromSurface");
ANativeWindow_release = (void (*)(void*))dlsym(handle, "ANativeWindow_release");

View File

@ -62,9 +62,9 @@ typedef gfxASurface::gfxImageFormat gfxImageFormat;
#define EGL_NO_CONTEXT (EGLContext)0
#define EGL_DEFAULT_DISPLAY (void*)0
#define ANDROID_LIBUI_PATH "/system/lib/libui.so"
#define ANDROID_GLES_PATH "/system/lib/libGLESv2.so"
#define ANDROID_EGL_PATH "/system/lib/libEGL.so"
#define ANDROID_LIBUI_PATH "libui.so"
#define ANDROID_GLES_PATH "libGLESv2.so"
#define ANDROID_EGL_PATH "libEGL.so"
// Really I have no idea, but this should be big enough
#define GRAPHIC_BUFFER_SIZE 1024

View File

@ -171,7 +171,7 @@ function startTests()
},
"caret": { "start": 1, "length": 0 }
});
checkCompositionEvents(false, false, true, false, "composing");
checkCompositionEvents(false, false, true, true, "composing");
var queryText = synthesizeQueryTextContent(0, 100);
ok(queryText, "query text event result is null");
if (!queryText) {

View File

@ -1240,6 +1240,7 @@ function runCompositionEventTest()
function formEventHandlerForWindow(aEvent)
{
ok(aEvent.isTrusted, "input events must be trusted events");
windowEventCounts[aEvent.type]++;
windowEventData[aEvent.type] = input.value;
}

View File

@ -715,11 +715,11 @@ nsClipboard :: FindPlatformHTML ( IDataObject* inDataObject, UINT inIndex, void*
return false;
}
float vers = 0.0;
char version[8] = { 0 };
PRInt32 startOfData = 0;
PRInt32 endOfData = 0;
int numFound = sscanf((char*)*outData, "Version:%f\nStartHTML:%d\nEndHTML:%d",
&vers, &startOfData, &endOfData);
int numFound = sscanf((char*)*outData, "Version:%7s\nStartHTML:%d\nEndHTML:%d",
version, &startOfData, &endOfData);
if (numFound != 3 || startOfData < -1 || endOfData < -1) {
return false;

View File

@ -1803,8 +1803,9 @@ nsNativeThemeWin::GetWidgetPadding(nsDeviceContext* aContext,
if (aWidgetType == NS_THEME_WINDOW_TITLEBAR ||
aWidgetType == NS_THEME_WINDOW_TITLEBAR_MAXIMIZED) {
aResult->SizeTo(0, 0, 0, 0);
// Maximized windows have an offscreen offset equal to
// the border padding. (windows quirk)
// XXX Maximized windows have an offscreen offset equal to
// the border padding. This should be addressed in nsWindow,
// but currently can't be, see UpdateNonClientMargins.
if (aWidgetType == NS_THEME_WINDOW_TITLEBAR_MAXIMIZED)
aResult->top = GetSystemMetrics(SM_CXFRAME);
return true;

View File

@ -341,10 +341,16 @@ static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
// General purpose user32.dll hook object
static WindowsDllInterceptor sUser32Intercept;
// 2 pixel offset for eTransparencyBorderlessGlass which equals
// the size of the default window border Windows paints.
// 2 pixel offset for eTransparencyBorderlessGlass which equals the size of
// the default window border Windows paints. Glass will be extended inward
// this distance to remove the border.
static const PRInt32 kGlassMarginAdjustment = 2;
// When the client area is extended out into the default window frame area,
// this is the minimum amount of space along the edge of resizable windows
// we will always display a resize cursor in, regardless of the underlying
// content.
static const PRInt32 kResizableBorderMinSize = 3;
// We should never really try to accelerate windows bigger than this. In some
// cases this might lead to no D3D9 acceleration where we could have had it
@ -2031,49 +2037,91 @@ nsWindow::UpdateNonClientMargins(PRInt32 aSizeMode, bool aReflowWindow)
mNonClientOffset.top = mNonClientOffset.bottom =
mNonClientOffset.left = mNonClientOffset.right = 0;
mCaptionHeight = mVertResizeMargin = mHorResizeMargin = 0;
if (aSizeMode == -1)
aSizeMode = mSizeMode;
if (aSizeMode == nsSizeMode_Minimized ||
aSizeMode == nsSizeMode_Fullscreen) {
mCaptionHeight = mVertResizeMargin = mHorResizeMargin = 0;
return true;
}
// Note, for maximized windows, we need to continue to offset the client by
// thick frame margins of a normal window, since windows expects this
// in it's DwmDefWndProc hit testing.
mCaptionHeight = GetSystemMetrics(SM_CYCAPTION);
bool hasCaption = (mBorderStyle & (eBorderStyle_all |
eBorderStyle_title |
eBorderStyle_menu |
eBorderStyle_default)) > 0 ? true : false;
if (hasCaption)
mCaptionHeight = GetSystemMetrics(SM_CYCAPTION);
mHorResizeMargin = GetSystemMetrics(SM_CXFRAME);
mVertResizeMargin = GetSystemMetrics(SM_CYFRAME);
mCaptionHeight += mVertResizeMargin;
// If a margin value is 0, set the offset to the default size of the frame.
// If a margin is -1, leave as default, and if a margin > 0, set the offset
// so that the frame size is equal to the margin value.
// Custom margin offset calculations for the chrome margin attribute on a
// window. The offsets calculated here are added to the client area in the
// WM_NCCALCSIZE event:
// -1 - leave the default frame in place
// 0 - remove the frame, our frame offset equals the default frame size
// >0 - frame size equals (default frame size - margin value) with the
// restriction that the offset <= default frame size.
if (!mNonClientMargins.top)
mNonClientOffset.top = mCaptionHeight;
else if (mNonClientMargins.top > 0)
mNonClientOffset.top = mCaptionHeight - mNonClientMargins.top;
mNonClientOffset.top = NS_MIN(mCaptionHeight, mNonClientMargins.top);
if (!mNonClientMargins.left)
mNonClientOffset.left = mHorResizeMargin;
else if (mNonClientMargins.left > 0)
mNonClientOffset.left = mHorResizeMargin - mNonClientMargins.left;
mNonClientOffset.left = NS_MIN(mHorResizeMargin, mNonClientMargins.left);
if (!mNonClientMargins.right)
mNonClientOffset.right = mHorResizeMargin;
else if (mNonClientMargins.right > 0)
mNonClientOffset.right = mHorResizeMargin - mNonClientMargins.right;
mNonClientOffset.right = NS_MIN(mHorResizeMargin, mNonClientMargins.right);
if (!mNonClientMargins.bottom)
mNonClientOffset.bottom = mVertResizeMargin;
else if (mNonClientMargins.bottom > 0)
mNonClientOffset.bottom = mVertResizeMargin - mNonClientMargins.bottom;
mNonClientOffset.bottom = NS_MIN(mVertResizeMargin, mNonClientMargins.bottom);
// Disable chrome margins > 0 in two cases:
// - For non-glass desktops: The window frame is painted with textures that
// require the entire space of the default frame. We allow a full frame or
// no frame at all.
// - For maximized windows: Windows positions maximized windows such that the
// outer bounds sit off screen a distance equal to the standard frame size.
if(!nsUXThemeData::CheckForCompositor() || aSizeMode == nsSizeMode_Maximized) {
if (mNonClientMargins.top > 0)
mNonClientOffset.top = 0;
if (mNonClientMargins.bottom > 0)
mNonClientOffset.bottom = 0;
if (mNonClientMargins.left > 0)
mNonClientOffset.left = 0;
if (mNonClientMargins.right > 0)
mNonClientOffset.right = 0;
}
if (aSizeMode == nsSizeMode_Maximized) {
// For chrome margins = 0 on maximized windows, Windows places the bounds
// off screen a distance equal to the standard frame size. Remove this
// area from our expanded client area.
if (!mNonClientMargins.bottom)
mNonClientOffset.bottom = 0;
if (!mNonClientMargins.left)
mNonClientOffset.left = 0;
if (!mNonClientMargins.right)
mNonClientOffset.right = 0;
// This should be (mCaptionHeight - mVertResizeMargin). But if we offset
// the client area by just SM_CYCAPTION (placing the top of the client
// area level with the visible screen) Windows dwm def proc fails to pick
// up mouse hover and clicks on the glass control buttons. To compensate,
// we position the client area off screen by mVertResizeMargin, and add
// widget padding in nsNativeThemeWin::GetWidgetPadding().
if (!mNonClientMargins.top)
mNonClientOffset.top = mCaptionHeight;
// Address an issue with auto-hide taskbars which fall behind the window.
// Ensure a 1 pixel margin at the bottom of the monitor so that unhiding
// the taskbar works properly.
@ -3709,9 +3757,11 @@ void nsWindow::DispatchPendingEvents()
--recursionBlocker;
}
// Quickly check to see if there are any
// paint events pending.
if (::GetQueueStatus(QS_PAINT)) {
// Quickly check to see if there are any paint events pending,
// but only dispatch them if it has been long enough since the
// last paint completed.
if (::GetQueueStatus(QS_PAINT) &&
((TimeStamp::Now() - mLastPaintEndTime).ToMilliseconds() >= 50)) {
// Find the top level window.
HWND topWnd = WinUtils::GetTopLevelHWND(mWnd);
@ -5543,6 +5593,11 @@ BOOL CALLBACK nsWindow::BroadcastMsg(HWND aTopWindow, LPARAM aMsg)
PRInt32
nsWindow::ClientMarginHitTestPoint(PRInt32 mx, PRInt32 my)
{
if (mSizeMode == nsSizeMode_Minimized ||
mSizeMode == nsSizeMode_Fullscreen) {
return HTCLIENT;
}
// Calculations are done in screen coords
RECT winRect;
GetWindowRect(mWnd, &winRect);
@ -5560,72 +5615,90 @@ nsWindow::ClientMarginHitTestPoint(PRInt32 mx, PRInt32 my)
PRInt32 testResult = HTCLIENT;
bool isResizable = (mBorderStyle & (eBorderStyle_all |
eBorderStyle_resizeh |
eBorderStyle_default)) > 0 ? true : false;
if (mSizeMode == nsSizeMode_Maximized)
isResizable = false;
bool top = false;
bool bottom = false;
bool left = false;
bool right = false;
if (my >= winRect.top && my <
(winRect.top + mVertResizeMargin + (mCaptionHeight - mNonClientOffset.top)))
int topOffset = NS_MAX(mCaptionHeight - mNonClientOffset.top,
kResizableBorderMinSize);
int bottomOffset = NS_MAX(mVertResizeMargin - mNonClientOffset.bottom,
kResizableBorderMinSize);
int topBounds = winRect.top + topOffset;
int bottomBounds = winRect.bottom - bottomOffset;
if (my >= winRect.top && my < topBounds)
top = true;
else if (my < winRect.bottom && my >= (winRect.bottom - mVertResizeMargin))
else if (my <= winRect.bottom && my > bottomBounds)
bottom = true;
if (mx >= winRect.left && mx < (winRect.left +
(bottom ? (2*mHorResizeMargin) : mHorResizeMargin)))
int leftOffset = NS_MAX(mHorResizeMargin - mNonClientOffset.left,
kResizableBorderMinSize);
int rightOffset = NS_MAX(mHorResizeMargin - mNonClientOffset.right,
kResizableBorderMinSize);
// (the 2x case here doubles the resize area for corners)
int leftBounds = winRect.left +
(bottom ? (2*leftOffset) : leftOffset);
int rightBounds = winRect.right -
(bottom ? (2*rightOffset) : rightOffset);
if (mx >= winRect.left && mx < leftBounds)
left = true;
else if (mx < winRect.right && mx >= (winRect.right -
(bottom ? (2*mHorResizeMargin) : mHorResizeMargin)))
else if (mx <= winRect.right && mx > rightBounds)
right = true;
if (top) {
testResult = HTTOP;
if (left)
testResult = HTTOPLEFT;
else if (right)
testResult = HTTOPRIGHT;
} else if (bottom) {
testResult = HTBOTTOM;
if (left)
testResult = HTBOTTOMLEFT;
else if (right)
testResult = HTBOTTOMRIGHT;
if (isResizable) {
if (top) {
testResult = HTTOP;
if (left)
testResult = HTTOPLEFT;
else if (right)
testResult = HTTOPRIGHT;
} else if (bottom) {
testResult = HTBOTTOM;
if (left)
testResult = HTBOTTOMLEFT;
else if (right)
testResult = HTBOTTOMRIGHT;
} else {
if (left)
testResult = HTLEFT;
if (right)
testResult = HTRIGHT;
}
} else {
if (left)
testResult = HTLEFT;
if (right)
testResult = HTRIGHT;
if (top)
testResult = HTCAPTION;
else if (bottom || left || right)
testResult = HTBORDER;
}
bool contentOverlap = true;
if (mSizeMode == nsSizeMode_Maximized) {
// There's no HTTOP in maximized state (bug 575493)
if (testResult == HTTOP) {
testResult = HTCAPTION;
}
} else {
PRInt32 leftMargin = mNonClientMargins.left == -1 ? mHorResizeMargin : mNonClientMargins.left;
PRInt32 rightMargin = mNonClientMargins.right == -1 ? mHorResizeMargin : mNonClientMargins.right;
PRInt32 topMargin = mNonClientMargins.top == -1 ? mVertResizeMargin : mNonClientMargins.top;
PRInt32 bottomMargin = mNonClientMargins.bottom == -1 ? mVertResizeMargin : mNonClientMargins.bottom;
contentOverlap = mx >= winRect.left + leftMargin &&
mx <= winRect.right - rightMargin &&
my >= winRect.top + topMargin &&
my <= winRect.bottom - bottomMargin;
if (mSizeMode != nsSizeMode_Maximized) {
contentOverlap = mx >= winRect.left + leftOffset &&
mx <= winRect.right - rightOffset &&
my >= winRect.top + topOffset &&
my <= winRect.bottom - bottomOffset;
}
if (!sIsInMouseCapture &&
contentOverlap &&
(testResult == HTCLIENT ||
testResult == HTTOP ||
testResult == HTBORDER ||
testResult == HTTOPLEFT ||
testResult == HTCAPTION)) {
LPARAM lParam = MAKELPARAM(mx, my);
LPARAM lParamClient = lParamToClient(lParam);
bool result = DispatchMouseEvent(NS_MOUSE_MOZHITTEST, 0, lParamClient,
false, nsMouseEvent::eLeftButton, MOUSE_INPUT_SOURCE());
false, nsMouseEvent::eLeftButton, MOUSE_INPUT_SOURCE());
if (result) {
// The mouse is over a blank area
testResult = testResult == HTCLIENT ? HTCAPTION : testResult;

View File

@ -61,6 +61,8 @@
#include "nsWindowDbg.h"
#include "cairo.h"
#include "nsITimer.h"
#include "mozilla/TimeStamp.h"
#ifdef CAIRO_HAS_D2D_SURFACE
#include "gfxD2DSurface.h"
#endif
@ -94,6 +96,8 @@ class imgIContainer;
class nsWindow : public nsBaseWidget
{
typedef mozilla::TimeStamp TimeStamp;
typedef mozilla::TimeDuration TimeDuration;
typedef mozilla::widget::WindowHook WindowHook;
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
typedef mozilla::widget::TaskbarWindowPreview TaskbarWindowPreview;
@ -611,6 +615,10 @@ protected:
bool mHasTaskbarIconBeenCreated;
#endif
// The point in time at which the last paint completed. We use this to avoid
// painting too rapidly in response to frequent input events.
TimeStamp mLastPaintEndTime;
#ifdef ACCESSIBILITY
static BOOL sIsAccessibilityOn;
static HINSTANCE sAccLib;

View File

@ -605,6 +605,7 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32 aNestingLevel)
}
mPaintDC = nsnull;
mLastPaintEndTime = TimeStamp::Now();
#if defined(WIDGET_DEBUG_OUTPUT)
if (debug_WantPaintFlashing())