mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to fx-team.
This commit is contained in:
commit
33649b8921
@ -691,6 +691,8 @@ getRoleCB(AtkObject *aAtkObj)
|
||||
|
||||
if (aAtkObj->role == ATK_ROLE_LIST_BOX && !IsAtkVersionAtLeast(2, 1))
|
||||
aAtkObj->role = ATK_ROLE_LIST;
|
||||
else if (aAtkObj->role == ATK_ROLE_TABLE_ROW && !IsAtkVersionAtLeast(2, 1))
|
||||
aAtkObj->role = ATK_ROLE_LIST_ITEM;
|
||||
|
||||
return aAtkObj->role;
|
||||
}
|
||||
|
@ -39,7 +39,8 @@ extern int atkMajorVersion, atkMinorVersion;
|
||||
static inline bool
|
||||
IsAtkVersionAtLeast(int aMajor, int aMinor)
|
||||
{
|
||||
return aMajor < atkMajorVersion && aMinor < atkMinorVersion;
|
||||
return aMajor < atkMajorVersion ||
|
||||
(aMajor == atkMajorVersion && aMinor <= atkMinorVersion);
|
||||
}
|
||||
|
||||
#endif /* __NS_MAI_H__ */
|
||||
|
@ -242,7 +242,7 @@ ROLE(COLUMN,
|
||||
|
||||
ROLE(ROW,
|
||||
"row",
|
||||
ATK_ROLE_LIST_ITEM,
|
||||
ATK_ROLE_TABLE_ROW,
|
||||
NSAccessibilityRowRole,
|
||||
ROLE_SYSTEM_ROW,
|
||||
ROLE_SYSTEM_ROW,
|
||||
|
@ -203,18 +203,41 @@ App.prototype = {
|
||||
|
||||
|
||||
/**
|
||||
* The Console Watcher tracks the following metrics in apps: errors, warnings,
|
||||
* and reflows.
|
||||
* The Console Watcher tracks the following metrics in apps: reflows, warnings,
|
||||
* and errors.
|
||||
*/
|
||||
let consoleWatcher = {
|
||||
|
||||
_apps: new Map(),
|
||||
_watching: {
|
||||
reflows: false,
|
||||
warnings: false,
|
||||
errors: false
|
||||
},
|
||||
_client: null,
|
||||
|
||||
init: function cw_init(client) {
|
||||
this._client = client;
|
||||
this.consoleListener = this.consoleListener.bind(this);
|
||||
|
||||
let watching = this._watching;
|
||||
|
||||
for (let key in watching) {
|
||||
let metric = key;
|
||||
SettingsListener.observe('devtools.hud.' + metric, false, value => {
|
||||
// Watch or unwatch the metric.
|
||||
if (watching[metric] = value) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If unwatched, remove any existing widgets for that metric.
|
||||
for (let app of this._apps.values()) {
|
||||
app.metrics.set(metric, 0);
|
||||
app.display();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
client.addListener('logMessage', this.consoleListener);
|
||||
client.addListener('pageError', this.consoleListener);
|
||||
client.addListener('consoleAPICall', this.consoleListener);
|
||||
@ -246,8 +269,13 @@ let consoleWatcher = {
|
||||
},
|
||||
|
||||
bump: function cw_bump(app, metric) {
|
||||
if (!this._watching[metric]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let metrics = app.metrics;
|
||||
metrics.set(metric, metrics.get(metric) + 1);
|
||||
return true;
|
||||
},
|
||||
|
||||
consoleListener: function cw_consoleListener(type, packet) {
|
||||
@ -258,13 +286,19 @@ let consoleWatcher = {
|
||||
|
||||
case 'pageError':
|
||||
let pageError = packet.pageError;
|
||||
|
||||
if (pageError.warning || pageError.strict) {
|
||||
this.bump(app, 'warnings');
|
||||
if (!this.bump(app, 'warnings')) {
|
||||
return;
|
||||
}
|
||||
output = 'warning (';
|
||||
} else {
|
||||
this.bump(app, 'errors');
|
||||
if (!this.bump(app, 'errors')) {
|
||||
return;
|
||||
}
|
||||
output += 'error (';
|
||||
}
|
||||
|
||||
let {errorMessage, sourceName, category, lineNumber, columnNumber} = pageError;
|
||||
output += category + '): "' + (errorMessage.initial || errorMessage) +
|
||||
'" in ' + sourceName + ':' + lineNumber + ':' + columnNumber;
|
||||
@ -272,21 +306,31 @@ let consoleWatcher = {
|
||||
|
||||
case 'consoleAPICall':
|
||||
switch (packet.message.level) {
|
||||
|
||||
case 'error':
|
||||
this.bump(app, 'errors');
|
||||
if (!this.bump(app, 'errors')) {
|
||||
return;
|
||||
}
|
||||
output = 'error (console)';
|
||||
break;
|
||||
|
||||
case 'warn':
|
||||
this.bump(app, 'warnings');
|
||||
if (!this.bump(app, 'warnings')) {
|
||||
return;
|
||||
}
|
||||
output = 'warning (console)';
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'reflowActivity':
|
||||
this.bump(app, 'reflows');
|
||||
if (!this.bump(app, 'reflows')) {
|
||||
return;
|
||||
}
|
||||
|
||||
let {start, end, sourceURL} = packet;
|
||||
let duration = Math.round((end - start) * 100) / 100;
|
||||
output = 'reflow: ' + duration + 'ms';
|
||||
|
@ -12,7 +12,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2e546129dd7860ee3e62b3f86ab222647dfcaae4"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a403bdf3cf2a09b5ed0ed5aee362d8b7b31810b3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
|
||||
|
@ -6,12 +6,12 @@
|
||||
<remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
|
||||
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
|
||||
<!-- B2G specific things. -->
|
||||
<project name="platform_build" path="build" remote="b2g" revision="317f25e0a4cb3e8e86e2b76c37a14081372f0307">
|
||||
<project name="platform_build" path="build" remote="b2g" revision="97a5b461686757dbb8ecab2aac5903e41d2e1afe">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2e546129dd7860ee3e62b3f86ab222647dfcaae4"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a403bdf3cf2a09b5ed0ed5aee362d8b7b31810b3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
|
||||
@ -118,6 +118,7 @@
|
||||
<project name="platform/system/vold" path="system/vold" revision="8de05d4a52b5a91e7336e6baa4592f945a6ddbea"/>
|
||||
<default remote="caf" revision="refs/tags/android-4.3_r2.1" sync-j="4"/>
|
||||
<!-- Emulator specific things -->
|
||||
<project name="android-development" path="development" remote="b2g" revision="dab55669da8f48b6e57df95d5af9f16b4a87b0b1"/>
|
||||
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="3a9a17613cc685aa232432566ad6cc607eab4ec1"/>
|
||||
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="09485b73629856b21b2ed6073e327ab0e69a1189"/>
|
||||
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="7d33aaf740bbf6c7c6e9c34a92b371eda311b66b"/>
|
||||
@ -125,6 +126,5 @@
|
||||
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="2838a77ce4b8c09fa6a46fe25410bb3a4474cbd4"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="a962b2ed2195038cd566493c3f7968bea9d20189"/>
|
||||
<project name="platform/development" path="development" revision="1f18cfe031ce23b7fb838fe3d4379dd802b49e71"/>
|
||||
<project name="android-sdk" path="sdk" remote="b2g" revision="8b1365af38c9a653df97349ee53a3f5d64fd590a"/>
|
||||
</manifest>
|
||||
|
@ -12,7 +12,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2e546129dd7860ee3e62b3f86ab222647dfcaae4"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a403bdf3cf2a09b5ed0ed5aee362d8b7b31810b3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"revision": "9da6724d2e1af0c60e5fd64c8a79c9c9c0106c9f",
|
||||
"revision": "179466c0aa4fd4d937a6d04d9cd136e687fa2993",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2e546129dd7860ee3e62b3f86ab222647dfcaae4"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a403bdf3cf2a09b5ed0ed5aee362d8b7b31810b3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
@ -10,7 +10,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2e546129dd7860ee3e62b3f86ab222647dfcaae4"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a403bdf3cf2a09b5ed0ed5aee362d8b7b31810b3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
@ -12,7 +12,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2e546129dd7860ee3e62b3f86ab222647dfcaae4"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a403bdf3cf2a09b5ed0ed5aee362d8b7b31810b3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
@ -11,7 +11,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2e546129dd7860ee3e62b3f86ab222647dfcaae4"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a403bdf3cf2a09b5ed0ed5aee362d8b7b31810b3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
@ -6,12 +6,12 @@
|
||||
<remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
|
||||
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
|
||||
<!-- B2G specific things. -->
|
||||
<project name="platform_build" path="build" remote="b2g" revision="317f25e0a4cb3e8e86e2b76c37a14081372f0307">
|
||||
<project name="platform_build" path="build" remote="b2g" revision="97a5b461686757dbb8ecab2aac5903e41d2e1afe">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2e546129dd7860ee3e62b3f86ab222647dfcaae4"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a403bdf3cf2a09b5ed0ed5aee362d8b7b31810b3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
|
||||
|
@ -11,7 +11,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2e546129dd7860ee3e62b3f86ab222647dfcaae4"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a403bdf3cf2a09b5ed0ed5aee362d8b7b31810b3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
@ -168,7 +168,7 @@ if test -z "$BUILDING_JS" -o -n "$JS_STANDALONE"; then
|
||||
WINNT)
|
||||
ICU_TARGET=MSYS/MSVC
|
||||
;;
|
||||
*bsd*|dragonfly*)
|
||||
DragonFly|FreeBSD|NetBSD|OpenBSD|GNU_kFreeBSD)
|
||||
ICU_TARGET=BSD
|
||||
;;
|
||||
esac
|
||||
|
18
configure.in
18
configure.in
@ -1023,6 +1023,24 @@ darwin*)
|
||||
linux*)
|
||||
HOST_OS_ARCH=Linux
|
||||
;;
|
||||
kfreebsd*-gnu)
|
||||
HOST_OS_ARCH=GNU_kFreeBSD
|
||||
;;
|
||||
gnu*)
|
||||
HOST_OS_ARCH=GNU
|
||||
;;
|
||||
dragonfly*)
|
||||
HOST_OS_ARCH=DragonFly
|
||||
;;
|
||||
freebsd*)
|
||||
HOST_OS_ARCH=FreeBSD
|
||||
;;
|
||||
netbsd*)
|
||||
HOST_OS_ARCH=NetBSD
|
||||
;;
|
||||
openbsd*)
|
||||
HOST_OS_ARCH=OpenBSD
|
||||
;;
|
||||
solaris*)
|
||||
HOST_OS_ARCH=SunOS
|
||||
SOLARIS_SUNPRO_CC=
|
||||
|
@ -457,7 +457,7 @@ nsFrameMessageManager::GetDelayedFrameScripts(JSContext* aCx, JS::MutableHandle<
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, mPendingScripts.Length(), nullptr));
|
||||
JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, mPendingScripts.Length()));
|
||||
NS_ENSURE_TRUE(array, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
JS::Rooted<JSString*> url(aCx);
|
||||
@ -466,10 +466,11 @@ nsFrameMessageManager::GetDelayedFrameScripts(JSContext* aCx, JS::MutableHandle<
|
||||
url = JS_NewUCStringCopyN(aCx, mPendingScripts[i].get(), mPendingScripts[i].Length());
|
||||
NS_ENSURE_TRUE(url, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
JS::Value pairElts[] = { JS::StringValue(url),
|
||||
JS::BooleanValue(mPendingScriptsGlobalStates[i]) };
|
||||
JS::AutoValueArray<2> pairElts(aCx);
|
||||
pairElts[0].setString(url);
|
||||
pairElts[1].setBoolean(mPendingScriptsGlobalStates[i]);
|
||||
|
||||
pair = JS_NewArrayObject(aCx, 2, pairElts);
|
||||
pair = JS_NewArrayObject(aCx, pairElts);
|
||||
NS_ENSURE_TRUE(pair, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
NS_ENSURE_TRUE(JS_SetElement(aCx, array, i, pair),
|
||||
@ -598,7 +599,7 @@ nsFrameMessageManager::SendMessage(const nsAString& aMessageName,
|
||||
}
|
||||
|
||||
uint32_t len = retval.Length();
|
||||
JS::Rooted<JSObject*> dataArray(aCx, JS_NewArrayObject(aCx, len, nullptr));
|
||||
JS::Rooted<JSObject*> dataArray(aCx, JS_NewArrayObject(aCx, len));
|
||||
NS_ENSURE_TRUE(dataArray, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
|
@ -1245,14 +1245,13 @@ CanvasRenderingContext2D::SetTransform(double m11, double m12,
|
||||
JSObject*
|
||||
MatrixToJSObject(JSContext* cx, const Matrix& matrix, ErrorResult& error)
|
||||
{
|
||||
JS::Value elts[] = {
|
||||
DOUBLE_TO_JSVAL(matrix._11), DOUBLE_TO_JSVAL(matrix._12),
|
||||
DOUBLE_TO_JSVAL(matrix._21), DOUBLE_TO_JSVAL(matrix._22),
|
||||
DOUBLE_TO_JSVAL(matrix._31), DOUBLE_TO_JSVAL(matrix._32)
|
||||
};
|
||||
JS::AutoValueArray<6> elts(cx);
|
||||
elts[0].setDouble(matrix._11); elts[1].setDouble(matrix._12);
|
||||
elts[2].setDouble(matrix._21); elts[3].setDouble(matrix._22);
|
||||
elts[4].setDouble(matrix._31); elts[5].setDouble(matrix._32);
|
||||
|
||||
// XXX Should we enter GetWrapper()'s compartment?
|
||||
JSObject* obj = JS_NewArrayObject(cx, 6, elts);
|
||||
JSObject* obj = JS_NewArrayObject(cx, elts);
|
||||
if (!obj) {
|
||||
error.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
@ -158,7 +158,7 @@ DashArrayToJSVal(FallibleTArray<T>& dashes,
|
||||
return JSVAL_NULL;
|
||||
}
|
||||
JS::Rooted<JSObject*> obj(cx,
|
||||
JS_NewArrayObject(cx, dashes.Length(), nullptr));
|
||||
JS_NewArrayObject(cx, dashes.Length()));
|
||||
if (!obj) {
|
||||
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return JSVAL_NULL;
|
||||
|
@ -1907,10 +1907,10 @@ WebGLContext::GetUniform(JSContext* cx, WebGLProgram *prog,
|
||||
if (unitSize == 1) {
|
||||
return JS::BooleanValue(iv[0] ? true : false);
|
||||
} else {
|
||||
JS::Value uv[16];
|
||||
JS::AutoValueArray<16> uv(cx);
|
||||
for (int k = 0; k < unitSize; k++)
|
||||
uv[k] = JS::BooleanValue(iv[k] ? true : false);
|
||||
JSObject* obj = JS_NewArrayObject(cx, unitSize, uv);
|
||||
uv[k].setBoolean(iv[k]);
|
||||
JSObject* obj = JS_NewArrayObject(cx, JS::HandleValueArray::subarray(uv, 0, unitSize));
|
||||
if (!obj) {
|
||||
ErrorOutOfMemory("getUniform: out of memory");
|
||||
return JS::NullValue();
|
||||
|
@ -423,11 +423,12 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
|
||||
{
|
||||
realGLboolean gl_bv[4] = { 0 };
|
||||
gl->fGetBooleanv(pname, gl_bv);
|
||||
JS::Value vals[4] = { JS::BooleanValue(bool(gl_bv[0])),
|
||||
JS::BooleanValue(bool(gl_bv[1])),
|
||||
JS::BooleanValue(bool(gl_bv[2])),
|
||||
JS::BooleanValue(bool(gl_bv[3])) };
|
||||
JSObject* obj = JS_NewArrayObject(cx, 4, vals);
|
||||
JS::AutoValueArray<4> vals(cx);
|
||||
vals[0].setBoolean(gl_bv[0]);
|
||||
vals[1].setBoolean(gl_bv[1]);
|
||||
vals[2].setBoolean(gl_bv[2]);
|
||||
vals[3].setBoolean(gl_bv[3]);
|
||||
JSObject* obj = JS_NewArrayObject(cx, vals);
|
||||
if (!obj) {
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "SampleSink.h"
|
||||
#include "prlog.h"
|
||||
|
||||
#include <initguid.h>
|
||||
#include <wmsdkidl.h>
|
||||
|
||||
using namespace mozilla::media;
|
||||
|
@ -13,7 +13,6 @@ EXPORTS += [
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'AudioSinkFilter.cpp',
|
||||
'AudioSinkInputPin.cpp',
|
||||
'DirectShowDecoder.cpp',
|
||||
'DirectShowReader.cpp',
|
||||
@ -22,6 +21,10 @@ UNIFIED_SOURCES += [
|
||||
'SourceFilter.cpp',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'AudioSinkFilter.cpp',
|
||||
]
|
||||
|
||||
# If WebRTC isn't being built, we need to compile the DirectShow base classes so that
|
||||
# they're available at link time.
|
||||
if not CONFIG['MOZ_WEBRTC']:
|
||||
|
@ -255,7 +255,6 @@ ISOControl::GetBufs(nsTArray<nsTArray<uint8_t>>* aOutputBufs)
|
||||
uint32_t len = mOutBuffers.Length();
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
mOutBuffers[i].SwapElements(*aOutputBufs->AppendElement());
|
||||
mOutputSize += mOutBuffers[i].Length();
|
||||
}
|
||||
return FlushBuf();
|
||||
}
|
||||
@ -264,7 +263,6 @@ nsresult
|
||||
ISOControl::FlushBuf()
|
||||
{
|
||||
mOutBuffers.SetLength(1);
|
||||
mLastWrittenBoxPos = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -278,6 +276,8 @@ ISOControl::WriteAVData(nsTArray<uint8_t>& aArray)
|
||||
return 0;
|
||||
}
|
||||
|
||||
mOutputSize += len;
|
||||
|
||||
// The last element already has data, allocated a new element for pointer
|
||||
// swapping.
|
||||
if (mOutBuffers.LastElement().Length()) {
|
||||
@ -314,6 +314,7 @@ uint32_t
|
||||
ISOControl::Write(uint8_t* aBuf, uint32_t aSize)
|
||||
{
|
||||
mOutBuffers.LastElement().AppendElements(aBuf, aSize);
|
||||
mOutputSize += aSize;
|
||||
return aSize;
|
||||
}
|
||||
|
||||
@ -383,7 +384,7 @@ ISOControl::GenerateMoof(uint32_t aTrackType)
|
||||
|
||||
nsresult rv;
|
||||
uint32_t size;
|
||||
uint64_t first_sample_offset = mOutputSize + mLastWrittenBoxPos;
|
||||
uint64_t first_sample_offset = mOutputSize;
|
||||
nsAutoPtr<MovieFragmentBox> moof_box(new MovieFragmentBox(aTrackType, this));
|
||||
nsAutoPtr<MediaDataBox> mdat_box(new MediaDataBox(aTrackType, this));
|
||||
|
||||
|
@ -229,11 +229,7 @@ private:
|
||||
//
|
||||
nsTArray<nsTArray<uint8_t>> mOutBuffers;
|
||||
|
||||
// Last written position of current box, it is for box checking purpose and
|
||||
// calculating the sample offset in moof.
|
||||
uint32_t mLastWrittenBoxPos;
|
||||
|
||||
// Accumulate size of output fragments.
|
||||
// Accumulate output size from Write().
|
||||
uint64_t mOutputSize;
|
||||
|
||||
// Bit writing operation. Note: the mBitCount should be 0 before any
|
||||
|
@ -42,9 +42,6 @@ Box::BoxSizeChecker::~BoxSizeChecker()
|
||||
MOZ_ASSERT(false);
|
||||
}
|
||||
|
||||
// Keeps the last box size position, it is for counting the sample offset when
|
||||
// generating moof.
|
||||
mControl->mLastWrittenBoxPos += box_size;
|
||||
MOZ_COUNT_DTOR(BoxSizeChecker);
|
||||
}
|
||||
|
||||
|
@ -85,6 +85,7 @@ function startTest(test, token) {
|
||||
};
|
||||
|
||||
element.oncanplaythrough = function () {
|
||||
element.oncanplaythrough = null;
|
||||
// If content has ended, skip the test
|
||||
if (element.ended) {
|
||||
ok(true, 'ended fired before canplaythrough, skipping test');
|
||||
|
@ -55,6 +55,7 @@ function startTest(test, token) {
|
||||
}
|
||||
|
||||
element.oncanplaythrough = function () {
|
||||
element.oncanplaythrough = null;
|
||||
for (var i = 0; i < mExpectStopCount; i++) {
|
||||
mediaRecorder.start(1000);
|
||||
mediaRecorder.stop();
|
||||
|
@ -86,6 +86,7 @@ function startTest(test, token) {
|
||||
|
||||
// Start recording once canplaythrough fires
|
||||
element.oncanplaythrough = function() {
|
||||
element.oncanplaythrough = null;
|
||||
mediaRecorder.start(250);
|
||||
is(mediaRecorder.state, 'recording', 'Media recorder should be recording');
|
||||
is(mediaRecorder.stream, element.stream,
|
||||
|
@ -156,6 +156,7 @@ function startTest(test, token) {
|
||||
element.stream = element.mozCaptureStream();
|
||||
|
||||
element.oncanplaythrough = function () {
|
||||
element.oncanplaythrough = null;
|
||||
runStateTransitionTests(element.stream);
|
||||
manager.finished(token);
|
||||
};
|
||||
|
@ -12,3 +12,4 @@ support-files =
|
||||
[test_recognition_service_error.html]
|
||||
[test_success_without_recognition_service.html]
|
||||
[test_timeout.html]
|
||||
skip-if = os == "win"
|
||||
|
@ -29,7 +29,6 @@ which makes Windows Media Foundation unavailable.
|
||||
#include <mferror.h>
|
||||
#include <propvarutil.h>
|
||||
#include <wmcodecdsp.h>
|
||||
#include <initguid.h>
|
||||
#include <d3d9.h>
|
||||
#include <dxva2api.h>
|
||||
#include <wmcodecdsp.h>
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "nsWindowsHelpers.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "VideoUtils.h"
|
||||
#include <initguid.h>
|
||||
|
||||
#ifdef WMF_MUST_DEFINE_AAC_MFT_CLSID
|
||||
// Some SDK versions don't define the AAC decoder CLSID.
|
||||
|
@ -18,6 +18,9 @@ UNIFIED_SOURCES += [
|
||||
'WMFDecoder.cpp',
|
||||
'WMFReader.cpp',
|
||||
'WMFSourceReaderCallback.cpp',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'WMFUtils.cpp',
|
||||
]
|
||||
|
||||
|
@ -372,9 +372,15 @@ MessagePort::PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
|
||||
if (aTransferable.WasPassed()) {
|
||||
const Sequence<JS::Value>& realTransferable = aTransferable.Value();
|
||||
|
||||
// The input sequence only comes from the generated bindings code, which
|
||||
// ensures it is rooted.
|
||||
JS::HandleValueArray elements =
|
||||
JS::HandleValueArray::fromMarkedLocation(realTransferable.Length(),
|
||||
realTransferable.Elements());
|
||||
|
||||
JSObject* array =
|
||||
JS_NewArrayObject(aCx, realTransferable.Length(),
|
||||
const_cast<JS::Value*>(realTransferable.Elements()));
|
||||
JS_NewArrayObject(aCx, elements);
|
||||
if (!array) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
|
@ -7940,9 +7940,13 @@ nsGlobalWindow::PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
JS::Rooted<JS::Value> transferArray(aCx, JS::UndefinedValue());
|
||||
if (aTransfer.WasPassed()) {
|
||||
const Sequence<JS::Value >& values = aTransfer.Value();
|
||||
transferArray = JS::ObjectOrNullValue(JS_NewArrayObject(aCx,
|
||||
values.Length(),
|
||||
const_cast<JS::Value*>(values.Elements())));
|
||||
|
||||
// The input sequence only comes from the generated bindings code, which
|
||||
// ensures it is rooted.
|
||||
JS::HandleValueArray elements =
|
||||
JS::HandleValueArray::fromMarkedLocation(values.Length(), values.Elements());
|
||||
|
||||
transferArray = JS::ObjectOrNullValue(JS_NewArrayObject(aCx, elements));
|
||||
if (transferArray.isNull()) {
|
||||
aError.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
|
@ -1169,7 +1169,7 @@ nsJSContext::SetProperty(JS::Handle<JSObject*> aTarget, const char* aPropName, n
|
||||
}
|
||||
}
|
||||
|
||||
JSObject* array = ::JS_NewArrayObject(mContext, args.length(), args.begin());
|
||||
JSObject* array = ::JS_NewArrayObject(mContext, args);
|
||||
if (!array) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -4428,7 +4428,7 @@ if (%s.IsNull()) {
|
||||
innerTemplate = CGIndenter(CGGeneric(innerTemplate), 6).define()
|
||||
return (("""
|
||||
uint32_t length = %s.Length();
|
||||
JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length, nullptr));
|
||||
JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
|
||||
if (!returnArray) {
|
||||
%s
|
||||
}
|
||||
|
@ -758,17 +758,21 @@ BrowserElementChild.prototype = {
|
||||
|
||||
/**
|
||||
* Actually take a screenshot and foward the result up to our parent, given
|
||||
* the desired maxWidth and maxHeight, and given the DOMRequest ID associated
|
||||
* with the request from the parent.
|
||||
* the desired maxWidth and maxHeight (in CSS pixels), and given the
|
||||
* DOMRequest ID associated with the request from the parent.
|
||||
*/
|
||||
_takeScreenshot: function(maxWidth, maxHeight, mimeType, domRequestID) {
|
||||
// You can think of the screenshotting algorithm as carrying out the
|
||||
// following steps:
|
||||
//
|
||||
// - Calculate maxWidth, maxHeight, and viewport's width and height in the
|
||||
// dimension of device pixels by multiply the numbers with
|
||||
// window.devicePixelRatio.
|
||||
//
|
||||
// - Let scaleWidth be the factor by which we'd need to downscale the
|
||||
// viewport so it would fit within maxWidth. (If the viewport's width
|
||||
// is less than maxWidth, let scaleWidth be 1.) Compute scaleHeight
|
||||
// the same way.
|
||||
// viewport pixel width so it would fit within maxPixelWidth.
|
||||
// (If the viewport's pixel width is less than maxPixelWidth, let
|
||||
// scaleWidth be 1.) Compute scaleHeight the same way.
|
||||
//
|
||||
// - Scale the viewport by max(scaleWidth, scaleHeight). Now either the
|
||||
// viewport's width is no larger than maxWidth, the viewport's height is
|
||||
@ -794,13 +798,23 @@ BrowserElementChild.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
let scaleWidth = Math.min(1, maxWidth / content.innerWidth);
|
||||
let scaleHeight = Math.min(1, maxHeight / content.innerHeight);
|
||||
let devicePixelRatio = content.devicePixelRatio;
|
||||
|
||||
let maxPixelWidth = Math.round(maxWidth * devicePixelRatio);
|
||||
let maxPixelHeight = Math.round(maxHeight * devicePixelRatio);
|
||||
|
||||
let contentPixelWidth = content.innerWidth * devicePixelRatio;
|
||||
let contentPixelHeight = content.innerHeight * devicePixelRatio;
|
||||
|
||||
let scaleWidth = Math.min(1, maxPixelWidth / contentPixelWidth);
|
||||
let scaleHeight = Math.min(1, maxPixelHeight / contentPixelHeight);
|
||||
|
||||
let scale = Math.max(scaleWidth, scaleHeight);
|
||||
|
||||
let canvasWidth = Math.min(maxWidth, Math.round(content.innerWidth * scale));
|
||||
let canvasHeight = Math.min(maxHeight, Math.round(content.innerHeight * scale));
|
||||
let canvasWidth =
|
||||
Math.min(maxPixelWidth, Math.round(contentPixelWidth * scale));
|
||||
let canvasHeight =
|
||||
Math.min(maxPixelHeight, Math.round(contentPixelHeight * scale));
|
||||
|
||||
let transparent = (mimeType !== 'image/jpeg');
|
||||
|
||||
@ -812,7 +826,7 @@ BrowserElementChild.prototype = {
|
||||
canvas.height = canvasHeight;
|
||||
|
||||
var ctx = canvas.getContext("2d", { willReadFrequently: true });
|
||||
ctx.scale(scale, scale);
|
||||
ctx.scale(scale * devicePixelRatio, scale * devicePixelRatio);
|
||||
ctx.drawWindow(content, 0, 0, content.innerWidth, content.innerHeight,
|
||||
transparent ? "rgba(255,255,255,0)" : "rgb(255,255,255)");
|
||||
|
||||
|
@ -41,7 +41,9 @@ MOCHITEST_FILES = \
|
||||
test_browserElement_inproc_Metachange.html \
|
||||
test_browserElement_inproc_Opensearch.html \
|
||||
browserElement_GetScreenshot.js \
|
||||
browserElement_GetScreenshotDppx.js \
|
||||
test_browserElement_inproc_GetScreenshot.html \
|
||||
test_browserElement_inproc_GetScreenshotDppx.html \
|
||||
browserElement_BadScreenshot.js \
|
||||
test_browserElement_inproc_BadScreenshot.html \
|
||||
browserElement_SetVisible.js \
|
||||
@ -212,6 +214,7 @@ MOCHITEST_FILES += \
|
||||
test_browserElement_oop_Metachange.html \
|
||||
test_browserElement_oop_Opensearch.html \
|
||||
test_browserElement_oop_GetScreenshot.html \
|
||||
test_browserElement_oop_GetScreenshotDppx.html \
|
||||
test_browserElement_oop_BadScreenshot.html \
|
||||
test_browserElement_oop_XFrameOptions.html \
|
||||
test_browserElement_oop_XFrameOptionsDeny.html \
|
||||
|
@ -0,0 +1,108 @@
|
||||
/* Any copyright is dedicated to the public domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test the getScreenshot property for mozbrowser
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
browserElementTestHelpers.setEnabledPref(true);
|
||||
browserElementTestHelpers.addPermission();
|
||||
|
||||
function runTest() {
|
||||
var dppxPref = 'layout.css.devPixelsPerPx';
|
||||
var cssPixelWidth = 600;
|
||||
var cssPixelHeight = 400;
|
||||
|
||||
var iframe1 = document.createElement('iframe');
|
||||
iframe1.setAttribute('width', cssPixelWidth);
|
||||
iframe1.setAttribute('height', cssPixelHeight);
|
||||
SpecialPowers.wrap(iframe1).mozbrowser = true;
|
||||
|
||||
iframe1.src = 'data:text/html,<html><body>hello</body></html>';
|
||||
document.body.appendChild(iframe1);
|
||||
|
||||
var images = [];
|
||||
|
||||
function screenshotTaken(image) {
|
||||
images.push(image);
|
||||
if (images.length === 1) {
|
||||
ok(true, 'Got initial non blank screenshot');
|
||||
|
||||
if (image.width !== cssPixelWidth || image.height !== cssPixelHeight) {
|
||||
ok(false, 'The pixel width of the image received is not correct');
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
ok(true, 'The pixel width of the image received is correct');
|
||||
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{'set': [['layout.css.devPixelsPerPx', 2]]}, takeScreenshot);
|
||||
}
|
||||
else if (images.length === 2) {
|
||||
ok(true, 'Got updated screenshot after source page changed');
|
||||
|
||||
if (image.width !== cssPixelWidth * 2 ||
|
||||
image.height !== cssPixelHeight * 2) {
|
||||
ok(false, 'The pixel width of the 2dppx image received is not correct');
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
ok(true, 'The pixel width of the 2dppx image received is correct');
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
function takeScreenshot() {
|
||||
function gotImage(e) {
|
||||
// |this| is the Image.
|
||||
|
||||
URL.revokeObjectURL(this.src);
|
||||
|
||||
if (e.type === 'error' || !this.width || !this.height) {
|
||||
tryAgain();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
screenshotTaken(this);
|
||||
}
|
||||
|
||||
function tryAgain() {
|
||||
if (--attempts === 0) {
|
||||
ok(false, 'Timed out waiting for correct screenshot');
|
||||
SimpleTest.finish();
|
||||
} else {
|
||||
setTimeout(function() {
|
||||
iframe1.getScreenshot(cssPixelWidth, cssPixelHeight).onsuccess =
|
||||
getScreenshotImageData;
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
|
||||
function getScreenshotImageData(e) {
|
||||
var blob = e.target.result;
|
||||
if (blob.size === 0) {
|
||||
tryAgain();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var img = new Image();
|
||||
img.src = URL.createObjectURL(blob);
|
||||
img.onload = img.onerror = gotImage;
|
||||
}
|
||||
|
||||
var attempts = 10;
|
||||
iframe1.getScreenshot(cssPixelWidth, cssPixelHeight).onsuccess =
|
||||
getScreenshotImageData;
|
||||
}
|
||||
|
||||
function iframeLoadedHandler() {
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{'set': [['layout.css.devPixelsPerPx', 1]]}, takeScreenshot);
|
||||
}
|
||||
|
||||
iframe1.addEventListener('mozbrowserloadend', iframeLoadedHandler);
|
||||
}
|
||||
|
||||
addEventListener('testready', runTest);
|
@ -0,0 +1,19 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=959066
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 959066</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="browserElementTestHelpers.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=959066">Mozilla Bug 959066</a>
|
||||
|
||||
<script type="application/javascript;version=1.7" src='browserElement_GetScreenshotDppx.js'>
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,19 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=959066
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 959066</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="browserElementTestHelpers.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=959066">Mozilla Bug 959066</a>
|
||||
|
||||
<script type="application/javascript;version=1.7" src='browserElement_GetScreenshotDppx.js'>
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -146,7 +146,7 @@ CameraControlImpl::Get(JSContext* aCx, uint32_t aKey, JS::Value* aValue)
|
||||
|
||||
GetParameter(aKey, regionArray);
|
||||
|
||||
JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0, nullptr));
|
||||
JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
|
||||
if (!array) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ DOMCameraCapabilities::ParameterListToNewArray(JSContext* aCx,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
aArray.set(JS_NewArrayObject(aCx, 0, nullptr));
|
||||
aArray.set(JS_NewArrayObject(aCx, 0));
|
||||
if (!aArray) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
@ -378,7 +378,7 @@ DOMCameraCapabilities::GetVideoSizes(JSContext* cx, JS::MutableHandle<JS::Value>
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> array(cx, JS_NewArrayObject(cx, 0, nullptr));
|
||||
JS::Rooted<JSObject*> array(cx, JS_NewArrayObject(cx, 0));
|
||||
if (!array) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIEditor.h"
|
||||
#include "nsIMEStateManager.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsPresContext.h"
|
||||
@ -27,7 +28,8 @@ TextComposition::TextComposition(nsPresContext* aPresContext,
|
||||
mPresContext(aPresContext), mNode(aNode),
|
||||
mNativeContext(aEvent->widget->GetInputContext().mNativeIMEContext),
|
||||
mCompositionStartOffset(0), mCompositionTargetOffset(0),
|
||||
mIsSynthesizedForTests(aEvent->mFlags.mIsSynthesizedForTests)
|
||||
mIsSynthesizedForTests(aEvent->mFlags.mIsSynthesizedForTests),
|
||||
mIsComposing(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -49,6 +51,20 @@ TextComposition::DispatchEvent(WidgetGUIEvent* aEvent,
|
||||
nsEventDispatcher::Dispatch(mNode, mPresContext,
|
||||
aEvent, nullptr, aStatus, aCallBack);
|
||||
|
||||
// Emulate editor behavior of text event handler if no editor handles
|
||||
// composition/text events.
|
||||
if (aEvent->message == NS_TEXT_TEXT && !HasEditor()) {
|
||||
EditorWillHandleTextEvent(aEvent->AsTextEvent());
|
||||
EditorDidHandleTextEvent();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
else if (aEvent->message == NS_COMPOSITION_END) {
|
||||
MOZ_ASSERT(!mIsComposing, "Why is the editor still composing?");
|
||||
MOZ_ASSERT(!HasEditor(), "Why does the editor still keep to hold this?");
|
||||
}
|
||||
#endif // #ifdef DEBUG
|
||||
|
||||
// Notify composition update to widget if possible
|
||||
NotityUpdateComposition(aEvent);
|
||||
}
|
||||
@ -123,6 +139,53 @@ TextComposition::NotifyIME(widget::NotificationToIME aNotification)
|
||||
return nsIMEStateManager::NotifyIME(aNotification, mPresContext);
|
||||
}
|
||||
|
||||
void
|
||||
TextComposition::EditorWillHandleTextEvent(const WidgetTextEvent* aTextEvent)
|
||||
{
|
||||
mIsComposing = aTextEvent->IsComposing();
|
||||
|
||||
MOZ_ASSERT(mLastData == aTextEvent->theText,
|
||||
"The text of a text event must be same as previous data attribute value "
|
||||
"of the latest compositionupdate event");
|
||||
}
|
||||
|
||||
void
|
||||
TextComposition::EditorDidHandleTextEvent()
|
||||
{
|
||||
mString = mLastData;
|
||||
}
|
||||
|
||||
void
|
||||
TextComposition::StartHandlingComposition(nsIEditor* aEditor)
|
||||
{
|
||||
MOZ_ASSERT(!HasEditor(), "There is a handling editor already");
|
||||
mEditorWeak = do_GetWeakReference(aEditor);
|
||||
}
|
||||
|
||||
void
|
||||
TextComposition::EndHandlingComposition(nsIEditor* aEditor)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
nsCOMPtr<nsIEditor> editor = GetEditor();
|
||||
MOZ_ASSERT(editor == aEditor, "Another editor handled the composition?");
|
||||
#endif // #ifdef DEBUG
|
||||
mEditorWeak = nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIEditor>
|
||||
TextComposition::GetEditor() const
|
||||
{
|
||||
nsCOMPtr<nsIEditor> editor = do_QueryReferent(mEditorWeak);
|
||||
return editor.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
TextComposition::HasEditor() const
|
||||
{
|
||||
nsCOMPtr<nsIEditor> editor = GetEditor();
|
||||
return !!editor;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* TextComposition::CompositionEventDispatcher
|
||||
******************************************************************************/
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsINode.h"
|
||||
#include "nsIWeakReference.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsThreadUtils.h"
|
||||
@ -17,8 +18,8 @@
|
||||
#include "mozilla/EventForwards.h"
|
||||
|
||||
class nsDispatchingCallback;
|
||||
class nsIEditor;
|
||||
class nsIMEStateManager;
|
||||
class nsIWidget;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -47,7 +48,14 @@ public:
|
||||
nsPresContext* GetPresContext() const { return mPresContext; }
|
||||
nsINode* GetEventTargetNode() const { return mNode; }
|
||||
// The latest CompositionEvent.data value except compositionstart event.
|
||||
const nsString& GetLastData() const { return mLastData; }
|
||||
// This value is modified at dispatching compositionupdate.
|
||||
const nsString& LastData() const { return mLastData; }
|
||||
// The composition string which is already handled by the focused editor.
|
||||
// I.e., this value must be same as the composition string on the focused
|
||||
// editor. This value is modified at a call of EditorDidHandleTextEvent().
|
||||
// Note that mString and mLastData are different between dispatcing
|
||||
// compositionupdate and text event handled by focused editor.
|
||||
const nsString& String() const { return mString; }
|
||||
// Returns true if the composition is started with synthesized event which
|
||||
// came from nsDOMWindowUtils.
|
||||
bool IsSynthesizedForTests() const { return mIsSynthesizedForTests; }
|
||||
@ -73,6 +81,45 @@ public:
|
||||
*/
|
||||
uint32_t OffsetOfTargetClause() const { return mCompositionTargetOffset; }
|
||||
|
||||
/**
|
||||
* Returns true if there is non-empty composition string and it's not fixed.
|
||||
* Otherwise, false.
|
||||
*/
|
||||
bool IsComposing() const { return mIsComposing; }
|
||||
|
||||
/**
|
||||
* StartHandlingComposition() and EndHandlingComposition() are called by
|
||||
* editor when it holds a TextComposition instance and release it.
|
||||
*/
|
||||
void StartHandlingComposition(nsIEditor* aEditor);
|
||||
void EndHandlingComposition(nsIEditor* aEditor);
|
||||
|
||||
/**
|
||||
* TextEventHandlingMarker class should be created at starting to handle text
|
||||
* event in focused editor. This calls EditorWillHandleTextEvent() and
|
||||
* EditorDidHandleTextEvent() automatically.
|
||||
*/
|
||||
class MOZ_STACK_CLASS TextEventHandlingMarker
|
||||
{
|
||||
public:
|
||||
TextEventHandlingMarker(TextComposition* aComposition,
|
||||
const WidgetTextEvent* aTextEvent)
|
||||
: mComposition(aComposition)
|
||||
{
|
||||
mComposition->EditorWillHandleTextEvent(aTextEvent);
|
||||
}
|
||||
|
||||
~TextEventHandlingMarker()
|
||||
{
|
||||
mComposition->EditorDidHandleTextEvent();
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<TextComposition> mComposition;
|
||||
TextEventHandlingMarker();
|
||||
TextEventHandlingMarker(const TextEventHandlingMarker& aOther);
|
||||
};
|
||||
|
||||
private:
|
||||
// This class holds nsPresContext weak. This instance shouldn't block
|
||||
// destroying it. When the presContext is being destroyed, it's notified to
|
||||
@ -85,10 +132,17 @@ private:
|
||||
// composition. Don't access the instance, it may not be available.
|
||||
void* mNativeContext;
|
||||
|
||||
// mEditorWeak is a weak reference to the focused editor handling composition.
|
||||
nsWeakPtr mEditorWeak;
|
||||
|
||||
// mLastData stores the data attribute of the latest composition event (except
|
||||
// the compositionstart event).
|
||||
nsString mLastData;
|
||||
|
||||
// mString stores the composition text which has been handled by the focused
|
||||
// editor.
|
||||
nsString mString;
|
||||
|
||||
// Offset of the composition string from start of the editor
|
||||
uint32_t mCompositionStartOffset;
|
||||
// Offset of the selected clause of the composition string from start of the
|
||||
@ -98,10 +152,35 @@ private:
|
||||
// See the comment for IsSynthesizedForTests().
|
||||
bool mIsSynthesizedForTests;
|
||||
|
||||
// See the comment for IsComposing().
|
||||
bool mIsComposing;
|
||||
|
||||
// Hide the default constructor and copy constructor.
|
||||
TextComposition() {}
|
||||
TextComposition(const TextComposition& aOther);
|
||||
|
||||
/**
|
||||
* GetEditor() returns nsIEditor pointer of mEditorWeak.
|
||||
*/
|
||||
already_AddRefed<nsIEditor> GetEditor() const;
|
||||
|
||||
/**
|
||||
* HasEditor() returns true if mEditorWeak holds nsIEditor instance which is
|
||||
* alive. Otherwise, false.
|
||||
*/
|
||||
bool HasEditor() const;
|
||||
|
||||
/**
|
||||
* EditorWillHandleTextEvent() must be called before the focused editor
|
||||
* handles the text event.
|
||||
*/
|
||||
void EditorWillHandleTextEvent(const WidgetTextEvent* aTextEvent);
|
||||
|
||||
/**
|
||||
* EditorDidHandleTextEvent() must be called after the focused editor handles
|
||||
* a text event.
|
||||
*/
|
||||
void EditorDidHandleTextEvent();
|
||||
|
||||
/**
|
||||
* DispatchEvent() dispatches the aEvent to the mContent synchronously.
|
||||
|
@ -617,9 +617,9 @@ nsIMEStateManager::NotifyIME(NotificationToIME aNotification,
|
||||
case REQUEST_TO_COMMIT_COMPOSITION: {
|
||||
nsCOMPtr<nsIWidget> widget(aWidget);
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
if (!composition->GetLastData().IsEmpty()) {
|
||||
if (!composition->LastData().IsEmpty()) {
|
||||
WidgetTextEvent textEvent(true, NS_TEXT_TEXT, widget);
|
||||
textEvent.theText = composition->GetLastData();
|
||||
textEvent.theText = composition->LastData();
|
||||
textEvent.mFlags.mIsSynthesizedForTests = true;
|
||||
widget->DispatchEvent(&textEvent, status);
|
||||
if (widget->Destroyed()) {
|
||||
@ -629,7 +629,7 @@ nsIMEStateManager::NotifyIME(NotificationToIME aNotification,
|
||||
|
||||
status = nsEventStatus_eIgnore;
|
||||
WidgetCompositionEvent endEvent(true, NS_COMPOSITION_END, widget);
|
||||
endEvent.data = composition->GetLastData();
|
||||
endEvent.data = composition->LastData();
|
||||
endEvent.mFlags.mIsSynthesizedForTests = true;
|
||||
widget->DispatchEvent(&endEvent, status);
|
||||
|
||||
@ -638,9 +638,9 @@ nsIMEStateManager::NotifyIME(NotificationToIME aNotification,
|
||||
case REQUEST_TO_CANCEL_COMPOSITION: {
|
||||
nsCOMPtr<nsIWidget> widget(aWidget);
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
if (!composition->GetLastData().IsEmpty()) {
|
||||
if (!composition->LastData().IsEmpty()) {
|
||||
WidgetCompositionEvent updateEvent(true, NS_COMPOSITION_UPDATE, widget);
|
||||
updateEvent.data = composition->GetLastData();
|
||||
updateEvent.data = composition->LastData();
|
||||
updateEvent.mFlags.mIsSynthesizedForTests = true;
|
||||
widget->DispatchEvent(&updateEvent, status);
|
||||
if (widget->Destroyed()) {
|
||||
@ -649,7 +649,7 @@ nsIMEStateManager::NotifyIME(NotificationToIME aNotification,
|
||||
|
||||
status = nsEventStatus_eIgnore;
|
||||
WidgetTextEvent textEvent(true, NS_TEXT_TEXT, widget);
|
||||
textEvent.theText = composition->GetLastData();
|
||||
textEvent.theText = composition->LastData();
|
||||
textEvent.mFlags.mIsSynthesizedForTests = true;
|
||||
widget->DispatchEvent(&textEvent, status);
|
||||
if (widget->Destroyed()) {
|
||||
@ -659,7 +659,7 @@ nsIMEStateManager::NotifyIME(NotificationToIME aNotification,
|
||||
|
||||
status = nsEventStatus_eIgnore;
|
||||
WidgetCompositionEvent endEvent(true, NS_COMPOSITION_END, widget);
|
||||
endEvent.data = composition->GetLastData();
|
||||
endEvent.data = composition->LastData();
|
||||
endEvent.mFlags.mIsSynthesizedForTests = true;
|
||||
widget->DispatchEvent(&endEvent, status);
|
||||
|
||||
@ -1126,9 +1126,23 @@ nsIMEStateManager::GetFocusSelectionAndRoot(nsISelection** aSel,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
TextComposition*
|
||||
// static
|
||||
already_AddRefed<TextComposition>
|
||||
nsIMEStateManager::GetTextCompositionFor(nsIWidget* aWidget)
|
||||
{
|
||||
return sTextCompositions ?
|
||||
sTextCompositions->GetCompositionFor(aWidget) : nullptr;
|
||||
if (!sTextCompositions) {
|
||||
return nullptr;
|
||||
}
|
||||
nsRefPtr<TextComposition> textComposition =
|
||||
sTextCompositions->GetCompositionFor(aWidget);
|
||||
return textComposition.forget();
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<TextComposition>
|
||||
nsIMEStateManager::GetTextCompositionFor(WidgetGUIEvent* aEvent)
|
||||
{
|
||||
MOZ_ASSERT(aEvent->AsCompositionEvent() || aEvent->AsTextEvent(),
|
||||
"aEvent has to be WidgetCompositionEvent or WidgetTextEvent");
|
||||
return GetTextCompositionFor(aEvent->widget);
|
||||
}
|
||||
|
@ -98,7 +98,17 @@ public:
|
||||
/**
|
||||
* Get TextComposition from widget.
|
||||
*/
|
||||
static mozilla::TextComposition* GetTextCompositionFor(nsIWidget* aWidget);
|
||||
static already_AddRefed<mozilla::TextComposition>
|
||||
GetTextCompositionFor(nsIWidget* aWidget);
|
||||
|
||||
/**
|
||||
* Returns TextComposition instance for the event.
|
||||
*
|
||||
* @param aEvent Should be a composition event or a text event which is
|
||||
* being dispatched.
|
||||
*/
|
||||
static already_AddRefed<mozilla::TextComposition>
|
||||
GetTextCompositionFor(mozilla::WidgetGUIEvent* aEvent);
|
||||
|
||||
/**
|
||||
* Send a notification to IME. It depends on the IME or platform spec what
|
||||
|
@ -174,7 +174,7 @@ ArchiveRequest::GetFilenamesResult(JSContext* aCx,
|
||||
JS::Value* aValue,
|
||||
nsTArray<nsCOMPtr<nsIDOMFile> >& aFileList)
|
||||
{
|
||||
JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, aFileList.Length(), nullptr));
|
||||
JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, aFileList.Length()));
|
||||
nsresult rv;
|
||||
|
||||
if (!array) {
|
||||
@ -232,7 +232,7 @@ ArchiveRequest::GetFilesResult(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aValue,
|
||||
nsTArray<nsCOMPtr<nsIDOMFile> >& aFileList)
|
||||
{
|
||||
JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, aFileList.Length(), nullptr));
|
||||
JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, aFileList.Length()));
|
||||
if (!array) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ ConvertCloneReadInfosToArrayInternal(
|
||||
nsTArray<StructuredCloneReadInfo>& aReadInfos,
|
||||
JS::MutableHandle<JS::Value> aResult)
|
||||
{
|
||||
JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0, nullptr));
|
||||
JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
|
||||
if (!array) {
|
||||
IDB_WARNING("Failed to make array!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
|
@ -1447,7 +1447,7 @@ GetAllKeysHelper::GetSuccessResult(JSContext* aCx,
|
||||
nsTArray<Key> keys;
|
||||
mKeys.SwapElements(keys);
|
||||
|
||||
JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0, nullptr));
|
||||
JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
|
||||
if (!array) {
|
||||
IDB_WARNING("Failed to make array!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
|
@ -4931,7 +4931,7 @@ GetAllKeysHelper::GetSuccessResult(JSContext* aCx,
|
||||
nsTArray<Key> keys;
|
||||
mKeys.SwapElements(keys);
|
||||
|
||||
JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0, nullptr));
|
||||
JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
|
||||
if (!array) {
|
||||
IDB_WARNING("Failed to make array!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
|
@ -191,7 +191,7 @@ Key::DecodeJSValInternal(const unsigned char*& aPos, const unsigned char* aEnd,
|
||||
NS_ENSURE_TRUE(aRecursionDepth < MaxRecursionDepth, NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
|
||||
|
||||
if (*aPos - aTypeOffset >= eArray) {
|
||||
JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0, nullptr));
|
||||
JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
|
||||
if (!array) {
|
||||
NS_WARNING("Failed to make array!");
|
||||
IDB_REPORT_INTERNAL_ERR();
|
||||
|
@ -389,7 +389,7 @@ KeyPath::ExtractKeyAsJSVal(JSContext* aCx, const JS::Value& aValue,
|
||||
}
|
||||
|
||||
const uint32_t len = mStrings.Length();
|
||||
JS::Rooted<JSObject*> arrayObj(aCx, JS_NewArrayObject(aCx, len, nullptr));
|
||||
JS::Rooted<JSObject*> arrayObj(aCx, JS_NewArrayObject(aCx, len));
|
||||
if (!arrayObj) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
@ -501,7 +501,7 @@ KeyPath::ToJSVal(JSContext* aCx, JS::MutableHandle<JS::Value> aValue) const
|
||||
{
|
||||
if (IsArray()) {
|
||||
uint32_t len = mStrings.Length();
|
||||
JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, len, nullptr));
|
||||
JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, len));
|
||||
if (!array) {
|
||||
IDB_WARNING("Failed to make array!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
|
@ -483,7 +483,7 @@ MmsMessage::GetDeliveryInfo(JSContext* aCx, JS::MutableHandle<JS::Value> aDelive
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> deliveryInfo(
|
||||
aCx, JS_NewArrayObject(aCx, length, nullptr));
|
||||
aCx, JS_NewArrayObject(aCx, length));
|
||||
NS_ENSURE_TRUE(deliveryInfo, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
@ -614,7 +614,7 @@ MmsMessage::GetAttachments(JSContext* aCx, JS::MutableHandle<JS::Value> aAttachm
|
||||
uint32_t length = mAttachments.Length();
|
||||
|
||||
JS::Rooted<JSObject*> attachments(
|
||||
aCx, JS_NewArrayObject(aCx, length, nullptr));
|
||||
aCx, JS_NewArrayObject(aCx, length));
|
||||
NS_ENSURE_TRUE(attachments, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
|
@ -167,7 +167,7 @@ MobileMessageCallback::NotifyMessageDeleted(bool *aDeleted, uint32_t aSize)
|
||||
NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE);
|
||||
|
||||
JS::Rooted<JSObject*> deleteArrayObj(cx,
|
||||
JS_NewArrayObject(cx, aSize, nullptr));
|
||||
JS_NewArrayObject(cx, aSize));
|
||||
for (uint32_t i = 0; i < aSize; i++) {
|
||||
JS_SetElement(cx, deleteArrayObj, i, aDeleted[i]);
|
||||
}
|
||||
|
@ -241,7 +241,7 @@ MobileMessageManager::Send(JS::Handle<JS::Value> aNumber,
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> obj(aCx);
|
||||
obj = JS_NewArrayObject(aCx, requests.length(), requests.begin());
|
||||
obj = JS_NewArrayObject(aCx, requests);
|
||||
if (!obj) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ SmsFilter::GetNumbers(JSContext* aCx, JS::MutableHandle<JS::Value> aNumbers)
|
||||
numbers[i].setString(str);
|
||||
}
|
||||
|
||||
JSObject* obj = JS_NewArrayObject(aCx, numbers.length(), numbers.begin());
|
||||
JSObject* obj = JS_NewArrayObject(aCx, numbers);
|
||||
if (!obj) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -115,8 +115,7 @@ GetParamsFromSendMmsMessageRequest(JSContext* aCx,
|
||||
|
||||
// attachments
|
||||
JS::Rooted<JSObject*> attachmentArray(aCx, JS_NewArrayObject(aCx,
|
||||
aRequest.attachments().Length(),
|
||||
nullptr));
|
||||
aRequest.attachments().Length()));
|
||||
for (uint32_t i = 0; i < aRequest.attachments().Length(); i++) {
|
||||
JS::Rooted<JSObject*> obj(aCx,
|
||||
MmsAttachmentDataToJSObject(aCx, aRequest.attachments().ElementAt(i)));
|
||||
|
@ -576,7 +576,7 @@ NetworkStatsDB.prototype = {
|
||||
},
|
||||
|
||||
clearInterfaceStats: function clearInterfaceStats(aNetwork, aResultCb) {
|
||||
let network = [aNetwork.id, aNetwork.type];
|
||||
let network = [aNetwork.network.id, aNetwork.network.type];
|
||||
let self = this;
|
||||
|
||||
// Clear and save an empty sample to keep sync with system counters
|
||||
@ -609,7 +609,7 @@ NetworkStatsDB.prototype = {
|
||||
self._saveStats(aTxn, aStore, sample);
|
||||
}
|
||||
};
|
||||
}, aResultCb);
|
||||
}, this._resetAlarms.bind(this, aNetwork.networkId, aResultCb));
|
||||
},
|
||||
|
||||
clearStats: function clearStats(aNetworks, aResultCb) {
|
||||
@ -863,6 +863,7 @@ NetworkStatsDB.prototype = {
|
||||
let record = { networkId: aAlarm.networkId,
|
||||
absoluteThreshold: aAlarm.absoluteThreshold,
|
||||
relativeThreshold: aAlarm.relativeThreshold,
|
||||
startTime: aAlarm.startTime,
|
||||
data: aAlarm.data,
|
||||
manifestURL: aAlarm.manifestURL,
|
||||
pageURL: aAlarm.pageURL };
|
||||
@ -878,6 +879,7 @@ NetworkStatsDB.prototype = {
|
||||
let alarm = { networkId: aRecord.networkId,
|
||||
absoluteThreshold: aRecord.absoluteThreshold,
|
||||
relativeThreshold: aRecord.relativeThreshold,
|
||||
startTime: aRecord.startTime,
|
||||
data: aRecord.data,
|
||||
manifestURL: aRecord.manifestURL,
|
||||
pageURL: aRecord.pageURL };
|
||||
@ -1004,5 +1006,29 @@ NetworkStatsDB.prototype = {
|
||||
cursor.continue();
|
||||
}
|
||||
}, aResultCb);
|
||||
},
|
||||
|
||||
_resetAlarms: function _resetAlarms(aNetworkId, aResultCb) {
|
||||
this.dbNewTxn(ALARMS_STORE_NAME, "readwrite", function(txn, store) {
|
||||
if (DEBUG) {
|
||||
debug("Reset alarms for network " + aNetworkId);
|
||||
}
|
||||
|
||||
let lowerFilter = [aNetworkId, 0];
|
||||
let upperFilter = [aNetworkId, ""];
|
||||
let range = IDBKeyRange.bound(lowerFilter, upperFilter);
|
||||
|
||||
store.index("alarm").openCursor(range).onsuccess = function onsuccess(event) {
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
if (cursor.value.startTime) {
|
||||
cursor.value.relativeThreshold = cursor.value.threshold;
|
||||
cursor.update(cursor.value);
|
||||
}
|
||||
cursor.continue();
|
||||
return;
|
||||
}
|
||||
};
|
||||
}, aResultCb);
|
||||
}
|
||||
};
|
||||
|
@ -465,7 +465,9 @@ this.NetworkStatsService = {
|
||||
return;
|
||||
}
|
||||
|
||||
network = {network: network, networkId: aNetId};
|
||||
self._db.clearInterfaceStats(network, function onDBCleared(aError, aResult) {
|
||||
self._updateCurrentAlarm(aNetId);
|
||||
mm.sendAsyncMessage("NetworkStats:Clear:Return",
|
||||
{ id: msg.id, error: aError, result: aResult });
|
||||
});
|
||||
@ -482,7 +484,14 @@ this.NetworkStatsService = {
|
||||
}
|
||||
|
||||
let networks = aResult;
|
||||
networks.forEach(function(network, index) {
|
||||
networks[index] = {network: network, networkId: self.getNetworkId(network.id, network.type)};
|
||||
}, self);
|
||||
|
||||
self._db.clearStats(networks, function onDBCleared(aError, aResult) {
|
||||
networks.forEach(function(network, index) {
|
||||
self._updateCurrentAlarm(network.networkId);
|
||||
}, self);
|
||||
mm.sendAsyncMessage("NetworkStats:ClearAll:Return",
|
||||
{ id: msg.id, error: aError, result: aResult });
|
||||
});
|
||||
|
@ -19,6 +19,10 @@ function clearStore(store, callback) {
|
||||
}, callback);
|
||||
}
|
||||
|
||||
function getNetworkId(aIccId, aNetworkType) {
|
||||
return aIccId + '' + aNetworkType;
|
||||
}
|
||||
|
||||
add_test(function prepareDatabase() {
|
||||
// Clear whole database to avoid starting tests with unknown state
|
||||
// due to the previous tests.
|
||||
@ -121,6 +125,10 @@ add_test(function test_fillResultSamples_noEmptyData() {
|
||||
|
||||
add_test(function test_clear() {
|
||||
var networks = getNetworks();
|
||||
networks.forEach(function(network, index) {
|
||||
networks[index] = {network: network, networkId: getNetworkId(network.id, network.type)};
|
||||
}, this);
|
||||
|
||||
netStatsDb.clearStats(networks, function (error, result) {
|
||||
do_check_eq(error, null);
|
||||
run_next_test();
|
||||
@ -129,6 +137,10 @@ add_test(function test_clear() {
|
||||
|
||||
add_test(function test_clear_interface() {
|
||||
var networks = getNetworks();
|
||||
networks.forEach(function(network, index) {
|
||||
networks[index] = {network: network, networkId: getNetworkId(network.id, network.type)};
|
||||
}, this);
|
||||
|
||||
netStatsDb.clearInterfaceStats(networks[0], function (error, result) {
|
||||
do_check_eq(error, null);
|
||||
run_next_test();
|
||||
|
@ -19,8 +19,12 @@ add_test(function test_clearDB() {
|
||||
getNetworks(function onGetNetworks(error, result) {
|
||||
do_check_eq(error, null);
|
||||
var networks = result;
|
||||
networks.forEach(function(network, index) {
|
||||
networks[index] = {network: network, networkId: NetworkStatsService.getNetworkId(network.id, network.type)};
|
||||
}, this);
|
||||
|
||||
NetworkStatsService._db.clearStats(networks, function onDBCleared(error, result) {
|
||||
do_check_eq(result, null);
|
||||
do_check_eq(error, null);
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
|
@ -17,6 +17,8 @@ if CONFIG['MOZ_NFC']:
|
||||
'nsNfc.manifest',
|
||||
]
|
||||
|
||||
TEST_DIRS += ['tests']
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
||||
FINAL_LIBRARY = 'gklayout'
|
||||
|
64
dom/nfc/tests/marionette/head.js
Normal file
64
dom/nfc/tests/marionette/head.js
Normal file
@ -0,0 +1,64 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let pendingEmulatorCmdCount = 0;
|
||||
|
||||
function toggleNFC(enabled, callback) {
|
||||
isnot(callback, null);
|
||||
var settings = window.navigator.mozSettings;
|
||||
isnot(settings, null);
|
||||
ok(settings instanceof SettingsManager,
|
||||
'settings instanceof ' + settings.constructor +
|
||||
', expected SettingsManager');
|
||||
|
||||
let req = settings.createLock().get('nfc.enabled');
|
||||
req.onsuccess = function() {
|
||||
if (req.result['nfc.enabled'] === enabled) {
|
||||
callback();
|
||||
} else {
|
||||
let req = settings.createLock().set({'nfc.enabled': enabled});
|
||||
req.onsuccess = function() {
|
||||
window.setTimeout(callback, 5000); // give emulator time to toggle NFC
|
||||
};
|
||||
req.onerror = function() {
|
||||
ok(false,
|
||||
'Setting \'nfc.enabled\' to \'' + enabled +
|
||||
'\' failed, error ' + req.error.name);
|
||||
finish();
|
||||
};
|
||||
}
|
||||
};
|
||||
req.onerror = function() {
|
||||
ok(false, 'Getting \'nfc.enabled\' failed, error ' + req.error.name);
|
||||
finish();
|
||||
};
|
||||
}
|
||||
|
||||
function cleanUp() {
|
||||
log('Cleaning up');
|
||||
waitFor(finish(),
|
||||
function() {
|
||||
return pendingEmulatorCmdCount === 0;
|
||||
});
|
||||
}
|
||||
|
||||
function runNextTest() {
|
||||
let test = tests.shift();
|
||||
if (!test) {
|
||||
cleanUp();
|
||||
return;
|
||||
}
|
||||
test();
|
||||
}
|
||||
|
||||
// run this function to start tests
|
||||
function runTests() {
|
||||
if ('mozNfc' in window.navigator) {
|
||||
runNextTest();
|
||||
} else {
|
||||
// succeed immediately on systems without NFC
|
||||
log('Skipping test on system without NFC');
|
||||
ok(true, 'Skipping test on system without NFC');
|
||||
finish();
|
||||
}
|
||||
}
|
7
dom/nfc/tests/marionette/manifest.ini
Normal file
7
dom/nfc/tests/marionette/manifest.ini
Normal file
@ -0,0 +1,7 @@
|
||||
[DEFAULT]
|
||||
b2g=true
|
||||
browser=false
|
||||
qemu=true
|
||||
|
||||
[test_nfc_enabled.js]
|
||||
[test_nfc_manager_tech_discovered.js]
|
23
dom/nfc/tests/marionette/test_nfc_enabled.js
Normal file
23
dom/nfc/tests/marionette/test_nfc_enabled.js
Normal file
@ -0,0 +1,23 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 30000;
|
||||
MARIONETTE_HEAD_JS = 'head.js';
|
||||
|
||||
function testEnableNFC() {
|
||||
log('Running \'testEnableNFC\'');
|
||||
toggleNFC(true, runNextTest);
|
||||
}
|
||||
|
||||
function testDisableNFC() {
|
||||
log('Running \'testDisableNFC\'');
|
||||
toggleNFC(false, runNextTest);
|
||||
}
|
||||
|
||||
let tests = [
|
||||
testEnableNFC,
|
||||
testDisableNFC
|
||||
];
|
||||
|
||||
SpecialPowers.pushPermissions(
|
||||
[{'type': 'settings', 'allow': true, 'context': document}], runTests);
|
37
dom/nfc/tests/marionette/test_nfc_manager_tech_discovered.js
Normal file
37
dom/nfc/tests/marionette/test_nfc_manager_tech_discovered.js
Normal file
@ -0,0 +1,37 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 30000;
|
||||
MARIONETTE_HEAD_JS = 'head.js';
|
||||
|
||||
function handleTechnologyDiscoveredRE0(msg) {
|
||||
log('Received \'nfc-manager-tech-discovered\'');
|
||||
is(msg.type, 'techDiscovered', 'check for correct message type');
|
||||
is(msg.techList[0], 'P2P', 'check for correct tech type');
|
||||
toggleNFC(false, runNextTest);
|
||||
}
|
||||
|
||||
function activateRE0() {
|
||||
var cmd = 'nfc ntf rf_intf_activated 0';
|
||||
log('Executing \'' + cmd + '\'');
|
||||
++pendingEmulatorCmdCount;
|
||||
runEmulatorCmd(cmd, function(result) {
|
||||
--pendingEmulatorCmdCount;
|
||||
is(result.pop(), 'OK', 'check activation of RE0');
|
||||
});
|
||||
}
|
||||
|
||||
function testActivateRE0() {
|
||||
log('Running \'testActivateRE0\'');
|
||||
window.navigator.mozSetMessageHandler(
|
||||
'nfc-manager-tech-discovered', handleTechnologyDiscoveredRE0);
|
||||
toggleNFC(true, activateRE0);
|
||||
}
|
||||
|
||||
let tests = [
|
||||
testActivateRE0
|
||||
];
|
||||
|
||||
SpecialPowers.pushPermissions(
|
||||
[{'type': 'nfc-manager', 'allow': true, context: document},
|
||||
{'type': 'settings', 'allow': true, context: document}], runTests);
|
5
dom/nfc/tests/moz.build
Normal file
5
dom/nfc/tests/moz.build
Normal file
@ -0,0 +1,5 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
@ -608,7 +608,7 @@ public:
|
||||
MOZ_ASSERT(aCountdown != 0);
|
||||
JSContext* cx = aGlobal.GetContext();
|
||||
JSAutoCompartment ac(cx, aGlobal.Get());
|
||||
mValues = JS_NewArrayObject(cx, aCountdown, nullptr);
|
||||
mValues = JS_NewArrayObject(cx, aCountdown);
|
||||
mozilla::HoldJSObjects(this);
|
||||
}
|
||||
|
||||
@ -731,7 +731,7 @@ Promise::All(const GlobalObject& aGlobal, JSContext* aCx,
|
||||
}
|
||||
|
||||
if (aIterable.Length() == 0) {
|
||||
JS::Rooted<JSObject*> empty(aCx, JS_NewArrayObject(aCx, 0, nullptr));
|
||||
JS::Rooted<JSObject*> empty(aCx, JS_NewArrayObject(aCx, 0));
|
||||
if (!empty) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return nullptr;
|
||||
|
@ -48,7 +48,7 @@ public:
|
||||
MOZ_ASSERT(aPromise);
|
||||
JSContext* cx = aGlobal.GetContext();
|
||||
JSAutoCompartment ac(cx, mGlobal);
|
||||
mNotifications = JS_NewArrayObject(cx, 0, nullptr);
|
||||
mNotifications = JS_NewArrayObject(cx, 0);
|
||||
HoldData();
|
||||
}
|
||||
|
||||
|
@ -292,7 +292,7 @@ private:
|
||||
JS::Rooted<JS::Value> stackValue(cx);
|
||||
{
|
||||
JS::Rooted<JSObject*> stackObj(cx,
|
||||
JS_NewArrayObject(cx, mStackData.Length(), nullptr));
|
||||
JS_NewArrayObject(cx, mStackData.Length()));
|
||||
if (!stackObj) {
|
||||
return;
|
||||
}
|
||||
@ -447,8 +447,7 @@ WorkerConsole::Method(JSContext* aCx, const char* aMethodName,
|
||||
stack.swap(caller);
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> arguments(aCx,
|
||||
JS_NewArrayObject(aCx, aData.Length(), nullptr));
|
||||
JS::Rooted<JSObject*> arguments(aCx, JS_NewArrayObject(aCx, aData.Length()));
|
||||
if (!arguments) {
|
||||
return;
|
||||
}
|
||||
|
@ -2707,9 +2707,15 @@ WorkerPrivateParent<Derived>::PostMessageInternal(
|
||||
JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
|
||||
if (aTransferable.WasPassed()) {
|
||||
const Sequence<JS::Value>& realTransferable = aTransferable.Value();
|
||||
|
||||
// The input sequence only comes from the generated bindings code, which
|
||||
// ensures it is rooted.
|
||||
JS::HandleValueArray elements =
|
||||
JS::HandleValueArray::fromMarkedLocation(realTransferable.Length(),
|
||||
realTransferable.Elements());
|
||||
|
||||
JSObject* array =
|
||||
JS_NewArrayObject(aCx, realTransferable.Length(),
|
||||
const_cast<JS::Value*>(realTransferable.Elements()));
|
||||
JS_NewArrayObject(aCx, elements);
|
||||
if (!array) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
@ -4923,9 +4929,14 @@ WorkerPrivate::PostMessageToParentInternal(
|
||||
JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
|
||||
if (aTransferable.WasPassed()) {
|
||||
const Sequence<JS::Value>& realTransferable = aTransferable.Value();
|
||||
JSObject* array =
|
||||
JS_NewArrayObject(aCx, realTransferable.Length(),
|
||||
const_cast<jsval*>(realTransferable.Elements()));
|
||||
|
||||
// The input sequence only comes from the generated bindings code, which
|
||||
// ensures it is rooted.
|
||||
JS::HandleValueArray elements =
|
||||
JS::HandleValueArray::fromMarkedLocation(realTransferable.Length(),
|
||||
realTransferable.Elements());
|
||||
|
||||
JSObject* array = JS_NewArrayObject(aCx, elements);
|
||||
if (!array) {
|
||||
aRv = NS_ERROR_OUT_OF_MEMORY;
|
||||
return;
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "JoinElementTxn.h" // for JoinElementTxn
|
||||
#include "PlaceholderTxn.h" // for PlaceholderTxn
|
||||
#include "SplitElementTxn.h" // for SplitElementTxn
|
||||
#include "TextComposition.h" // for TextComposition
|
||||
#include "mozFlushType.h" // for mozFlushType::Flush_Frames
|
||||
#include "mozISpellCheckingEngine.h"
|
||||
#include "mozInlineSpellChecker.h" // for mozInlineSpellChecker
|
||||
@ -139,12 +140,9 @@ nsEditor::nsEditor()
|
||||
, mPlaceHolderBatch(0)
|
||||
, mAction(EditAction::none)
|
||||
, mIMETextOffset(0)
|
||||
, mIMEBufferLength(0)
|
||||
, mDirection(eNone)
|
||||
, mDocDirtyState(-1)
|
||||
, mSpellcheckCheckboxState(eTriUnset)
|
||||
, mInIMEMode(false)
|
||||
, mIsIMEComposing(false)
|
||||
, mShouldTxnSetSelection(true)
|
||||
, mDidPreDestroy(false)
|
||||
, mDidPostCreate(false)
|
||||
@ -248,8 +246,6 @@ nsEditor::Init(nsIDOMDocument *aDoc, nsIContent *aRoot, nsISelectionController *
|
||||
/* initialize IME stuff */
|
||||
mIMETextNode = nullptr;
|
||||
mIMETextOffset = 0;
|
||||
mIMEBufferLength = 0;
|
||||
|
||||
/* Show the caret */
|
||||
selCon->SetCaretReadOnly(false);
|
||||
selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
|
||||
@ -361,6 +357,10 @@ nsEditor::RemoveEventListeners()
|
||||
return;
|
||||
}
|
||||
reinterpret_cast<nsEditorEventListener*>(mEventListener.get())->Disconnect();
|
||||
if (mComposition) {
|
||||
mComposition->EndHandlingComposition(this);
|
||||
mComposition = nullptr;
|
||||
}
|
||||
mEventTarget = nullptr;
|
||||
}
|
||||
|
||||
@ -966,7 +966,9 @@ nsEditor::EndPlaceHolderTransaction()
|
||||
}
|
||||
// notify editor observers of action but if composing, it's done by
|
||||
// text event handler.
|
||||
if (!mInIMEMode) NotifyEditorObservers();
|
||||
if (!mComposition) {
|
||||
NotifyEditorObservers();
|
||||
}
|
||||
}
|
||||
}
|
||||
mPlaceHolderBatch--;
|
||||
@ -2010,11 +2012,26 @@ nsEditor::StopPreservingSelection()
|
||||
mSavedSel.MakeEmpty();
|
||||
}
|
||||
|
||||
void
|
||||
nsEditor::EnsureComposition(mozilla::WidgetGUIEvent* aEvent)
|
||||
{
|
||||
if (mComposition) {
|
||||
return;
|
||||
}
|
||||
// The compositionstart event must cause creating new TextComposition
|
||||
// instance at being dispatched by nsIMEStateManager.
|
||||
mComposition = nsIMEStateManager::GetTextCompositionFor(aEvent);
|
||||
if (!mComposition) {
|
||||
MOZ_CRASH("nsIMEStateManager doesn't return proper composition");
|
||||
}
|
||||
mComposition->StartHandlingComposition(this);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::BeginIMEComposition()
|
||||
nsEditor::BeginIMEComposition(WidgetCompositionEvent* aCompositionEvent)
|
||||
{
|
||||
mInIMEMode = true;
|
||||
MOZ_ASSERT(!mComposition, "There is composition already");
|
||||
EnsureComposition(aCompositionEvent);
|
||||
if (mPhonetic) {
|
||||
mPhonetic->Truncate(0);
|
||||
}
|
||||
@ -2024,7 +2041,7 @@ nsEditor::BeginIMEComposition()
|
||||
void
|
||||
nsEditor::EndIMEComposition()
|
||||
{
|
||||
NS_ENSURE_TRUE_VOID(mInIMEMode); // nothing to do
|
||||
NS_ENSURE_TRUE_VOID(mComposition); // nothing to do
|
||||
|
||||
// commit the IME transaction..we can get at it via the transaction mgr.
|
||||
// Note that this means IME won't work without an undo stack!
|
||||
@ -2041,9 +2058,8 @@ nsEditor::EndIMEComposition()
|
||||
/* reset the data we need to construct a transaction */
|
||||
mIMETextNode = nullptr;
|
||||
mIMETextOffset = 0;
|
||||
mIMEBufferLength = 0;
|
||||
mInIMEMode = false;
|
||||
mIsIMEComposing = false;
|
||||
mComposition->EndHandlingComposition(this);
|
||||
mComposition = nullptr;
|
||||
|
||||
// notify editor observers of action
|
||||
NotifyEditorObservers();
|
||||
@ -2073,7 +2089,7 @@ nsEditor::ForceCompositionEnd()
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
if (!mInIMEMode) {
|
||||
if (!mComposition) {
|
||||
// XXXmnakano see bug 558976, ResetInputState() has two meaning which are
|
||||
// "commit the composition" and "cursor is moved". This method name is
|
||||
// "ForceCompositionEnd", so, ResetInputState() should be used only for the
|
||||
@ -2312,7 +2328,7 @@ nsEditor::InsertTextImpl(const nsAString& aStringToInsert,
|
||||
|
||||
NS_ENSURE_TRUE(aInOutNode && *aInOutNode && aInOutOffset && aDoc,
|
||||
NS_ERROR_NULL_POINTER);
|
||||
if (!mInIMEMode && aStringToInsert.IsEmpty()) {
|
||||
if (!mComposition && aStringToInsert.IsEmpty()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2352,7 +2368,7 @@ nsEditor::InsertTextImpl(const nsAString& aStringToInsert,
|
||||
}
|
||||
|
||||
nsresult res;
|
||||
if (mInIMEMode) {
|
||||
if (mComposition) {
|
||||
if (!node->IsNodeOfType(nsINode::eTEXT)) {
|
||||
// create a text node
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc);
|
||||
@ -2407,7 +2423,7 @@ nsresult nsEditor::InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
|
||||
bool isIMETransaction = false;
|
||||
// aSuppressIME is used when editor must insert text, yet this text is not
|
||||
// part of current ime operation. example: adjusting whitespace around an ime insertion.
|
||||
if (mIMETextRangeList && mInIMEMode && !aSuppressIME)
|
||||
if (mIMETextRangeList && mComposition && !aSuppressIME)
|
||||
{
|
||||
if (!mIMETextNode)
|
||||
{
|
||||
@ -4179,45 +4195,16 @@ nsEditor::DeleteSelectionAndCreateNode(const nsAString& aTag,
|
||||
|
||||
/* Non-interface, protected methods */
|
||||
|
||||
int32_t
|
||||
nsEditor::GetIMEBufferLength()
|
||||
TextComposition*
|
||||
nsEditor::GetComposition() const
|
||||
{
|
||||
return mIMEBufferLength;
|
||||
}
|
||||
|
||||
void
|
||||
nsEditor::SetIsIMEComposing(){
|
||||
// We set mIsIMEComposing according to mIMETextRangeList.
|
||||
nsCOMPtr<nsIPrivateTextRange> rangePtr;
|
||||
uint16_t listlen, type;
|
||||
|
||||
mIsIMEComposing = false;
|
||||
listlen = mIMETextRangeList->GetLength();
|
||||
|
||||
for (uint16_t i = 0; i < listlen; i++)
|
||||
{
|
||||
rangePtr = mIMETextRangeList->Item(i);
|
||||
if (!rangePtr) continue;
|
||||
nsresult result = rangePtr->GetRangeType(&type);
|
||||
if (NS_FAILED(result)) continue;
|
||||
if ( type == nsIPrivateTextRange::TEXTRANGE_RAWINPUT ||
|
||||
type == nsIPrivateTextRange::TEXTRANGE_CONVERTEDTEXT ||
|
||||
type == nsIPrivateTextRange::TEXTRANGE_SELECTEDRAWTEXT ||
|
||||
type == nsIPrivateTextRange::TEXTRANGE_SELECTEDCONVERTEDTEXT )
|
||||
{
|
||||
mIsIMEComposing = true;
|
||||
#ifdef DEBUG_IME
|
||||
printf("nsEditor::mIsIMEComposing = true\n");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
return mComposition;
|
||||
}
|
||||
|
||||
bool
|
||||
nsEditor::IsIMEComposing() {
|
||||
return mIsIMEComposing;
|
||||
nsEditor::IsIMEComposing() const
|
||||
{
|
||||
return mComposition && mComposition->IsComposing();
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -4414,7 +4401,9 @@ nsEditor::CreateTxnForIMEText(const nsAString& aStringToInsert,
|
||||
|
||||
nsRefPtr<IMETextTxn> txn = new IMETextTxn();
|
||||
|
||||
nsresult rv = txn->Init(mIMETextNode, mIMETextOffset, mIMEBufferLength,
|
||||
// During handling IME composition, mComposition must have been initialized.
|
||||
nsresult rv = txn->Init(mIMETextNode, mIMETextOffset,
|
||||
mComposition->String().Length(),
|
||||
mIMETextRangeList, aStringToInsert, this);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
@ -5225,6 +5214,23 @@ nsEditor::IsAcceptableInputEvent(nsIDOMEvent* aEvent)
|
||||
if (!focusedContent) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
nsAutoString eventType;
|
||||
aEvent->GetType(eventType);
|
||||
// If composition event or text event isn't dispatched via widget,
|
||||
// we need to ignore them since they cannot be managed by TextComposition.
|
||||
// E.g., the event was created by chrome JS.
|
||||
// Note that if we allow to handle such events, editor may be confused by
|
||||
// strange event order.
|
||||
if (eventType.EqualsLiteral("text") ||
|
||||
eventType.EqualsLiteral("compositionstart") ||
|
||||
eventType.EqualsLiteral("compositionend")) {
|
||||
WidgetGUIEvent* widgetGUIEvent =
|
||||
aEvent->GetInternalNSEvent()->AsGUIEvent();
|
||||
if (!widgetGUIEvent || !widgetGUIEvent->widget) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isTrusted;
|
||||
|
@ -69,6 +69,7 @@ class nsTransactionManager;
|
||||
|
||||
namespace mozilla {
|
||||
class Selection;
|
||||
class TextComposition;
|
||||
|
||||
namespace dom {
|
||||
class Element;
|
||||
@ -242,9 +243,8 @@ public:
|
||||
mozilla::dom::Element** aContent);
|
||||
|
||||
// IME event handlers
|
||||
virtual nsresult BeginIMEComposition();
|
||||
virtual nsresult UpdateIMEComposition(const nsAString &aCompositionString,
|
||||
nsIPrivateTextRangeList *aTextRange)=0;
|
||||
virtual nsresult BeginIMEComposition(mozilla::WidgetCompositionEvent* aEvent);
|
||||
virtual nsresult UpdateIMEComposition(nsIDOMEvent* aDOMTextEvent) = 0;
|
||||
void EndIMEComposition();
|
||||
|
||||
void SwitchTextDirectionTo(uint32_t aDirection);
|
||||
@ -413,6 +413,13 @@ protected:
|
||||
return !IsPasswordEditor() && !IsReadonly() && !IsDisabled() && !ShouldSkipSpellCheck();
|
||||
}
|
||||
|
||||
/**
|
||||
* EnsureComposition() should be composition event handlers or text event
|
||||
* handler. This tries to get the composition for the event and set it to
|
||||
* mComposition.
|
||||
*/
|
||||
void EnsureComposition(mozilla::WidgetGUIEvent* aEvent);
|
||||
|
||||
public:
|
||||
|
||||
/** All editor operations which alter the doc should be prefaced
|
||||
@ -592,9 +599,14 @@ public:
|
||||
/** Find the deep first and last children. */
|
||||
nsINode* GetFirstEditableNode(nsINode* aRoot);
|
||||
|
||||
int32_t GetIMEBufferLength();
|
||||
bool IsIMEComposing(); /* test if IME is in composition state */
|
||||
void SetIsIMEComposing(); /* call this before |IsIMEComposing()| */
|
||||
/**
|
||||
* Returns current composition.
|
||||
*/
|
||||
mozilla::TextComposition* GetComposition() const;
|
||||
/**
|
||||
* Returns true if there is composition string and not fixed.
|
||||
*/
|
||||
bool IsIMEComposing() const;
|
||||
|
||||
/** from html rules code - migration in progress */
|
||||
static nsresult GetTagString(nsIDOMNode *aNode, nsAString& outString);
|
||||
@ -830,6 +842,9 @@ protected:
|
||||
nsIAtom *mPlaceHolderName; // name of placeholder transaction
|
||||
nsSelectionState *mSelState; // saved selection state for placeholder txn batching
|
||||
nsString *mPhonetic;
|
||||
// IME composition this is not null between compositionstart and
|
||||
// compositionend.
|
||||
nsRefPtr<mozilla::TextComposition> mComposition;
|
||||
|
||||
// various listeners
|
||||
nsCOMArray<nsIEditActionListener> mActionListeners; // listens to all low level actions on the doc
|
||||
@ -848,16 +863,11 @@ protected:
|
||||
EditAction mAction; // the current editor action
|
||||
|
||||
uint32_t mIMETextOffset; // offset in text node where IME comp string begins
|
||||
uint32_t mIMEBufferLength; // current length of IME comp string
|
||||
|
||||
EDirection mDirection; // the current direction of editor action
|
||||
int8_t mDocDirtyState; // -1 = not initialized
|
||||
uint8_t mSpellcheckCheckboxState; // a Tristate value
|
||||
|
||||
bool mInIMEMode; // are we inside an IME composition?
|
||||
bool mIsIMEComposing; // is IME in composition state?
|
||||
// This is different from mInIMEMode. see Bug 98434.
|
||||
|
||||
bool mShouldTxnSetSelection; // turn off for conservative selection adjustment by txns
|
||||
bool mDidPreDestroy; // whether PreDestroy has been called
|
||||
bool mDidPostCreate; // whether PostCreate has been called
|
||||
|
@ -5,6 +5,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
|
||||
#include "mozilla/Preferences.h" // for Preferences
|
||||
#include "mozilla/TextEvents.h" // for WidgetCompositionEvent
|
||||
#include "mozilla/dom/Element.h" // for Element
|
||||
#include "mozilla/dom/EventTarget.h" // for EventTarget
|
||||
#include "nsAString.h"
|
||||
@ -42,8 +43,6 @@
|
||||
#include "nsINode.h" // for nsINode, ::NODE_IS_EDITABLE, etc
|
||||
#include "nsIPlaintextEditor.h" // for nsIPlaintextEditor, etc
|
||||
#include "nsIPresShell.h" // for nsIPresShell
|
||||
#include "nsIPrivateTextEvent.h" // for nsIPrivateTextEvent
|
||||
#include "nsIPrivateTextRange.h" // for nsIPrivateTextRangeList
|
||||
#include "nsISelection.h" // for nsISelection
|
||||
#include "nsISelectionController.h" // for nsISelectionController, etc
|
||||
#include "nsISelectionPrivate.h" // for nsISelectionPrivate
|
||||
@ -661,24 +660,12 @@ nsEditorEventListener::HandleText(nsIDOMEvent* aTextEvent)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrivateTextEvent> textEvent = do_QueryInterface(aTextEvent);
|
||||
if (!textEvent) {
|
||||
//non-ui event passed in. bad things.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoString composedText;
|
||||
nsCOMPtr<nsIPrivateTextRangeList> textRangeList;
|
||||
|
||||
textEvent->GetText(composedText);
|
||||
textRangeList = textEvent->GetInputRange();
|
||||
|
||||
// if we are readonly or disabled, then do nothing.
|
||||
if (mEditor->IsReadonly() || mEditor->IsDisabled()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return mEditor->UpdateIMEComposition(composedText, textRangeList);
|
||||
return mEditor->UpdateIMEComposition(aTextEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -905,7 +892,9 @@ nsEditorEventListener::HandleStartComposition(nsIDOMEvent* aCompositionEvent)
|
||||
if (!mEditor->IsAcceptableInputEvent(aCompositionEvent)) {
|
||||
return NS_OK;
|
||||
}
|
||||
return mEditor->BeginIMEComposition();
|
||||
WidgetCompositionEvent* compositionStart =
|
||||
aCompositionEvent->GetInternalNSEvent()->AsCompositionEvent();
|
||||
return mEditor->BeginIMEComposition(compositionStart);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -20,6 +20,7 @@ FAIL_ON_WARNINGS = True
|
||||
LOCAL_INCLUDES += [
|
||||
'../base',
|
||||
'/content/base/src',
|
||||
'/dom/events',
|
||||
'/editor/txmgr/src',
|
||||
]
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
#include "TextComposition.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Selection.h"
|
||||
@ -39,6 +40,7 @@
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsINode.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIPrivateTextEvent.h"
|
||||
#include "nsIPrivateTextRange.h"
|
||||
#include "nsISelection.h"
|
||||
#include "nsISelectionController.h"
|
||||
@ -695,8 +697,7 @@ NS_IMETHODIMP nsPlaintextEditor::InsertText(const nsAString &aStringToInsert)
|
||||
nsCOMPtr<nsIEditRules> kungFuDeathGrip(mRules);
|
||||
|
||||
EditAction opID = EditAction::insertText;
|
||||
if (mInIMEMode)
|
||||
{
|
||||
if (mComposition) {
|
||||
opID = EditAction::insertIMEText;
|
||||
}
|
||||
nsAutoPlaceHolderBatch batch(this, nullptr);
|
||||
@ -811,9 +812,9 @@ NS_IMETHODIMP nsPlaintextEditor::InsertLineBreak()
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPlaintextEditor::BeginIMEComposition()
|
||||
nsPlaintextEditor::BeginIMEComposition(WidgetCompositionEvent* aEvent)
|
||||
{
|
||||
NS_ENSURE_TRUE(!mInIMEMode, NS_OK);
|
||||
NS_ENSURE_TRUE(!mComposition, NS_OK);
|
||||
|
||||
if (IsPasswordEditor()) {
|
||||
NS_ENSURE_TRUE(mRules, NS_ERROR_NULL_POINTER);
|
||||
@ -825,14 +826,19 @@ nsPlaintextEditor::BeginIMEComposition()
|
||||
textEditRules->ResetIMETextPWBuf();
|
||||
}
|
||||
|
||||
return nsEditor::BeginIMEComposition();
|
||||
return nsEditor::BeginIMEComposition(aEvent);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPlaintextEditor::UpdateIMEComposition(const nsAString& aCompositionString,
|
||||
nsIPrivateTextRangeList* aTextRangeList)
|
||||
nsPlaintextEditor::UpdateIMEComposition(nsIDOMEvent* aDOMTextEvent)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aTextRangeList, "aTextRangeList must not be nullptr");
|
||||
NS_ABORT_IF_FALSE(aDOMTextEvent, "aDOMTextEvent must not be nullptr");
|
||||
|
||||
WidgetTextEvent* widgetTextEvent =
|
||||
aDOMTextEvent->GetInternalNSEvent()->AsTextEvent();
|
||||
NS_ENSURE_TRUE(widgetTextEvent, NS_ERROR_INVALID_ARG);
|
||||
|
||||
EnsureComposition(widgetTextEvent);
|
||||
|
||||
nsCOMPtr<nsIPresShell> ps = GetPresShell();
|
||||
NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
|
||||
@ -843,19 +849,23 @@ nsPlaintextEditor::UpdateIMEComposition(const nsAString& aCompositionString,
|
||||
|
||||
nsRefPtr<nsCaret> caretP = ps->GetCaret();
|
||||
|
||||
// Update information of clauses in the new composition string.
|
||||
// This will be refered by followed methods.
|
||||
mIMETextRangeList = aTextRangeList;
|
||||
|
||||
// We set mIsIMEComposing properly.
|
||||
SetIsIMEComposing();
|
||||
nsCOMPtr<nsIPrivateTextEvent> privateTextEvent =
|
||||
do_QueryInterface(aDOMTextEvent);
|
||||
NS_ENSURE_TRUE(privateTextEvent, NS_ERROR_INVALID_ARG);
|
||||
|
||||
{
|
||||
TextComposition::TextEventHandlingMarker
|
||||
textEventHandlingMarker(mComposition, widgetTextEvent);
|
||||
|
||||
// Update information of clauses in the new composition string.
|
||||
// This will be refered by followed methods.
|
||||
mIMETextRangeList = privateTextEvent->GetInputRange();
|
||||
NS_ABORT_IF_FALSE(mIMETextRangeList,
|
||||
"mIMETextRangeList must not be nullptr");
|
||||
|
||||
nsAutoPlaceHolderBatch batch(this, nsGkAtoms::IMETxnName);
|
||||
|
||||
rv = InsertText(aCompositionString);
|
||||
|
||||
mIMEBufferLength = aCompositionString.Length();
|
||||
rv = InsertText(widgetTextEvent->theText);
|
||||
|
||||
if (caretP) {
|
||||
caretP->SetCaretDOMSelection(selection);
|
||||
@ -866,7 +876,7 @@ nsPlaintextEditor::UpdateIMEComposition(const nsAString& aCompositionString,
|
||||
// Note that if committed, we don't need to notify it since it will be
|
||||
// notified at followed compositionend event.
|
||||
// NOTE: We must notify after the auto batch will be gone.
|
||||
if (mIsIMEComposing) {
|
||||
if (IsIMEComposing()) {
|
||||
NotifyEditorObservers();
|
||||
}
|
||||
|
||||
|
@ -122,9 +122,8 @@ public:
|
||||
|
||||
virtual already_AddRefed<mozilla::dom::EventTarget> GetDOMEventTarget();
|
||||
|
||||
virtual nsresult BeginIMEComposition();
|
||||
virtual nsresult UpdateIMEComposition(const nsAString &aCompositionString,
|
||||
nsIPrivateTextRangeList *aTextRange);
|
||||
virtual nsresult BeginIMEComposition(mozilla::WidgetCompositionEvent* aEvent);
|
||||
virtual nsresult UpdateIMEComposition(nsIDOMEvent* aTextEvent) MOZ_OVERRIDE;
|
||||
|
||||
virtual already_AddRefed<nsIContent> GetInputEventTargetContent();
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "TextComposition.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/LookAndFeel.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
@ -1208,7 +1209,8 @@ nsTextEditRules::TruncateInsertionIfNeeded(Selection* aSelection,
|
||||
nsContentUtils::GetSelectionInTextControl(aSelection, mEditor->GetRoot(),
|
||||
start, end);
|
||||
|
||||
int32_t oldCompStrLength = mEditor->GetIMEBufferLength();
|
||||
TextComposition* composition = mEditor->GetComposition();
|
||||
int32_t oldCompStrLength = composition ? composition->String().Length() : 0;
|
||||
|
||||
const int32_t selectionLength = end - start;
|
||||
const int32_t resultingDocLength = docLength - selectionLength - oldCompStrLength;
|
||||
|
@ -3,6 +3,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <initguid.h>
|
||||
#include "DrawTargetD2D1.h"
|
||||
#include "DrawTargetD2D.h"
|
||||
#include "FilterNodeSoftware.h"
|
||||
|
@ -50,11 +50,11 @@ static const PCWSTR kXmlDescription =
|
||||
);
|
||||
|
||||
// {FB947CDA-718E-40CC-AE7B-D255830D7D14}
|
||||
DEFINE_GUID(GUID_SampleRadialGradientPS,
|
||||
0xfb947cda, 0x718e, 0x40cc, 0xae, 0x7b, 0xd2, 0x55, 0x83, 0xd, 0x7d, 0x14);
|
||||
static const GUID GUID_SampleRadialGradientPS =
|
||||
{0xfb947cda, 0x718e, 0x40cc, {0xae, 0x7b, 0xd2, 0x55, 0x83, 0xd, 0x7d, 0x14}};
|
||||
// {2C468128-6546-453C-8E25-F2DF0DE10A0F}
|
||||
DEFINE_GUID(GUID_SampleRadialGradientA0PS,
|
||||
0x2c468128, 0x6546, 0x453c, 0x8e, 0x25, 0xf2, 0xdf, 0xd, 0xe1, 0xa, 0xf);
|
||||
static const GUID GUID_SampleRadialGradientA0PS =
|
||||
{0x2c468128, 0x6546, 0x453c, {0x8e, 0x25, 0xf2, 0xdf, 0xd, 0xe1, 0xa, 0xf}};
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
@ -42,7 +42,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>INITGUID;USE_SSE2;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);GFX_LOG_DEBUG;GFX_LOG_WARNING;MFBT_STAND_ALONE;XP_WIN</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>USE_SSE2;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);GFX_LOG_DEBUG;GFX_LOG_WARNING;MFBT_STAND_ALONE;XP_WIN</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
@ -62,7 +62,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>INITGUID;USE_SSE2;WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>USE_SSE2;WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
|
@ -52,7 +52,6 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
'SourceSurfaceD2DTarget.cpp',
|
||||
]
|
||||
DEFINES['WIN32'] = True
|
||||
DEFINES['INITGUID'] = True
|
||||
# For Direct2D 1.1 we require WINSDK_MAXVER 0x06020000 or higher.
|
||||
if CONFIG['MOZ_ENABLE_DIRECT2D1_1']:
|
||||
SOURCES += [
|
||||
|
@ -76,6 +76,7 @@ static const char *sExtensionNames[] = {
|
||||
"GL_IMG_read_format",
|
||||
"GL_EXT_read_format_bgra",
|
||||
"GL_APPLE_client_storage",
|
||||
"GL_APPLE_texture_range",
|
||||
"GL_ARB_texture_non_power_of_two",
|
||||
"GL_ARB_pixel_buffer_object",
|
||||
"GL_ARB_ES2_compatibility",
|
||||
@ -756,6 +757,17 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
|
||||
}
|
||||
}
|
||||
|
||||
if (IsExtensionSupported(APPLE_texture_range)) {
|
||||
SymLoadStruct vaoSymbols[] = {
|
||||
{ (PRFuncPtr*) &mSymbols.fTextureRangeAPPLE, { "TextureRangeAPPLE", nullptr } },
|
||||
{ nullptr, { nullptr } },
|
||||
};
|
||||
|
||||
if (!LoadSymbols(&vaoSymbols[0], trygl, prefix)) {
|
||||
mSymbols.fTextureRangeAPPLE = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsExtensionSupported(ARB_vertex_array_object) ||
|
||||
IsExtensionSupported(OES_vertex_array_object)) {
|
||||
SymLoadStruct vaoSymbols[] = {
|
||||
|
@ -352,6 +352,7 @@ public:
|
||||
IMG_read_format,
|
||||
EXT_read_format_bgra,
|
||||
APPLE_client_storage,
|
||||
APPLE_texture_range,
|
||||
ARB_texture_non_power_of_two,
|
||||
ARB_pixel_buffer_object,
|
||||
ARB_ES2_compatibility,
|
||||
@ -1344,6 +1345,12 @@ public:
|
||||
AFTER_GL_CALL;
|
||||
}
|
||||
|
||||
void fTextureRangeAPPLE(GLenum target, GLsizei length, GLvoid *pointer) {
|
||||
BEFORE_GL_CALL;
|
||||
mSymbols.fTextureRangeAPPLE(target, length, pointer);
|
||||
AFTER_GL_CALL;
|
||||
}
|
||||
|
||||
void fPointParameterf(GLenum pname, GLfloat param) {
|
||||
BEFORE_GL_CALL;
|
||||
mSymbols.fPointParameterf(pname, param);
|
||||
|
@ -211,6 +211,8 @@ struct GLContextSymbols
|
||||
PFNGLTEXIMAGE2DPROC fTexImage2D;
|
||||
typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
|
||||
PFNGLTEXSUBIMAGE2DPROC fTexSubImage2D;
|
||||
typedef void (GLAPIENTRY * PFNGLTEXTURERANGEAPPLEPROC) (GLenum target, GLsizei length, GLvoid *pointer);
|
||||
PFNGLTEXTURERANGEAPPLEPROC fTextureRangeAPPLE;
|
||||
typedef void (GLAPIENTRY * PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
|
||||
PFNGLUNIFORM1FPROC fUniform1f;
|
||||
typedef void (GLAPIENTRY * PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat* value);
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "SharedSurfaceIO.h"
|
||||
#endif
|
||||
#include "ScopedGLHelpers.h"
|
||||
#include "gfx2DGlue.h"
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
@ -478,9 +479,22 @@ GLScreenBuffer::CreateRead(SharedSurface_GL* surf)
|
||||
return ReadBuffer::Create(gl, caps, formats, surf);
|
||||
}
|
||||
|
||||
void
|
||||
GLScreenBuffer::Readback(SharedSurface_GL* src, DataSourceSurface* dest)
|
||||
{
|
||||
MOZ_ASSERT(src && dest);
|
||||
DataSourceSurface::MappedSurface ms;
|
||||
dest->Map(DataSourceSurface::MapType::READ, &ms);
|
||||
nsRefPtr<gfxImageSurface> wrappedDest =
|
||||
new gfxImageSurface(ms.mData,
|
||||
ThebesIntSize(dest->GetSize()),
|
||||
ms.mStride,
|
||||
SurfaceFormatToImageFormat(dest->GetFormat()));
|
||||
DeprecatedReadback(src, wrappedDest);
|
||||
}
|
||||
|
||||
void
|
||||
GLScreenBuffer::Readback(SharedSurface_GL* src, gfxImageSurface* dest)
|
||||
GLScreenBuffer::DeprecatedReadback(SharedSurface_GL* src, gfxImageSurface* dest)
|
||||
{
|
||||
MOZ_ASSERT(src && dest);
|
||||
MOZ_ASSERT(ToIntSize(dest->GetSize()) == src->Size());
|
||||
@ -509,8 +523,6 @@ GLScreenBuffer::Readback(SharedSurface_GL* src, gfxImageSurface* dest)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
DrawBuffer*
|
||||
DrawBuffer::Create(GLContext* const gl,
|
||||
const SurfaceCaps& caps,
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "SurfaceTypes.h"
|
||||
#include "GLContextTypes.h"
|
||||
#include "GLDefs.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/gfx/Point.h"
|
||||
|
||||
// Forwards:
|
||||
@ -277,7 +278,8 @@ public:
|
||||
|
||||
bool Resize(const gfx::IntSize& size);
|
||||
|
||||
void Readback(SharedSurface_GL* src, gfxImageSurface* dest);
|
||||
void Readback(SharedSurface_GL* src, gfx::DataSourceSurface* dest);
|
||||
void DeprecatedReadback(SharedSurface_GL* src, gfxImageSurface* dest);
|
||||
|
||||
protected:
|
||||
void Attach(SharedSurface* surface, const gfx::IntSize& size);
|
||||
|
@ -64,12 +64,6 @@ const TextureFlags TEXTURE_COPY_PREVIOUS = 1 << 24;
|
||||
// deallocation.
|
||||
// The default behaviour is to deallocate on the host side.
|
||||
const TextureFlags TEXTURE_DEALLOCATE_CLIENT = 1 << 25;
|
||||
// The host side is responsible for deallocation, but that may not happen
|
||||
// immediately after the client side requests it. Exactly when the texture is
|
||||
// deallocated is up to the compositable. The texture must be deallocated by
|
||||
// the time the compositable or texture host is destroyed. A texture may not
|
||||
// have both TEXTURE_DEALLOCATE_CLIENT and TEXTURE_DEALLOCATE_DEFERRED flags.
|
||||
const TextureFlags TEXTURE_DEALLOCATE_DEFERRED = 1 << 26;
|
||||
// After being shared ith the compositor side, an immutable texture is never
|
||||
// modified, it can only be read. It is safe to not Lock/Unlock immutable
|
||||
// textures.
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "nsISupportsImpl.h" // for gfxContext::AddRef, etc
|
||||
#include "nsRect.h" // for nsIntRect
|
||||
#include "nsSize.h" // for nsIntSize
|
||||
#include "LayerUtils.h"
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::gl;
|
||||
@ -56,7 +57,8 @@ CopyableCanvasLayer::Initialize(const Data& aData)
|
||||
// `GLScreenBuffer::Morph`ing is only needed in BasicShadowableCanvasLayer.
|
||||
} else if (aData.mDrawTarget) {
|
||||
mDrawTarget = aData.mDrawTarget;
|
||||
mSurface =
|
||||
mSurface = mDrawTarget->Snapshot();
|
||||
mDeprecatedSurface =
|
||||
gfxPlatform::GetPlatform()->CreateThebesSurfaceAliasForDrawTarget_hack(mDrawTarget);
|
||||
mNeedsYFlip = false;
|
||||
} else {
|
||||
@ -73,7 +75,8 @@ CopyableCanvasLayer::IsDataValid(const Data& aData)
|
||||
}
|
||||
|
||||
void
|
||||
CopyableCanvasLayer::UpdateSurface(gfxASurface* aDestSurface, Layer* aMaskLayer)
|
||||
CopyableCanvasLayer::UpdateTarget(DrawTarget* aDestTarget,
|
||||
SourceSurface* aMaskSurface)
|
||||
{
|
||||
if (!IsDirty())
|
||||
return;
|
||||
@ -81,14 +84,105 @@ CopyableCanvasLayer::UpdateSurface(gfxASurface* aDestSurface, Layer* aMaskLayer)
|
||||
|
||||
if (mDrawTarget) {
|
||||
mDrawTarget->Flush();
|
||||
mSurface =
|
||||
mSurface = mDrawTarget->Snapshot();
|
||||
}
|
||||
|
||||
if (!mGLContext && aDestTarget) {
|
||||
PaintWithOpacity(aDestTarget, 1.0f, aMaskSurface);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mGLContext) {
|
||||
RefPtr<DataSourceSurface> readSurf;
|
||||
RefPtr<SourceSurface> resultSurf;
|
||||
|
||||
SharedSurface* sharedSurf = mGLContext->RequestFrame();
|
||||
if (!sharedSurf) {
|
||||
NS_WARNING("Null frame received.");
|
||||
return;
|
||||
}
|
||||
|
||||
IntSize readSize(sharedSurf->Size());
|
||||
SurfaceFormat format = (GetContentFlags() & CONTENT_OPAQUE)
|
||||
? SurfaceFormat::B8G8R8X8
|
||||
: SurfaceFormat::B8G8R8A8;
|
||||
|
||||
if (aDestTarget) {
|
||||
resultSurf = aDestTarget->Snapshot();
|
||||
if (!resultSurf) {
|
||||
resultSurf = GetTempSurface(readSize, format);
|
||||
}
|
||||
} else {
|
||||
resultSurf = GetTempSurface(readSize, format);
|
||||
}
|
||||
MOZ_ASSERT(resultSurf);
|
||||
MOZ_ASSERT(sharedSurf->APIType() == APITypeT::OpenGL);
|
||||
SharedSurface_GL* surfGL = SharedSurface_GL::Cast(sharedSurf);
|
||||
|
||||
if (surfGL->Type() == SharedSurfaceType::Basic) {
|
||||
// sharedSurf_Basic->mData must outlive readSurf. Alas, readSurf may not
|
||||
// leave the scope it was declared in.
|
||||
SharedSurface_Basic* sharedSurf_Basic = SharedSurface_Basic::Cast(surfGL);
|
||||
readSurf = sharedSurf_Basic->GetData();
|
||||
} else {
|
||||
if (resultSurf->GetSize() != readSize ||
|
||||
!(readSurf = resultSurf->GetDataSurface()) ||
|
||||
readSurf->GetFormat() != format)
|
||||
{
|
||||
readSurf = GetTempSurface(readSize, format);
|
||||
}
|
||||
|
||||
// Readback handles Flush/MarkDirty.
|
||||
mGLContext->Screen()->Readback(surfGL, readSurf);
|
||||
}
|
||||
MOZ_ASSERT(readSurf);
|
||||
|
||||
bool needsPremult = surfGL->HasAlpha() && !mIsGLAlphaPremult;
|
||||
if (needsPremult) {
|
||||
PremultiplySurface(readSurf);
|
||||
}
|
||||
|
||||
if (readSurf != resultSurf) {
|
||||
RefPtr<DataSourceSurface> resultDataSurface =
|
||||
resultSurf->GetDataSurface();
|
||||
RefPtr<DrawTarget> dt =
|
||||
Factory::CreateDrawTargetForData(BackendType::CAIRO,
|
||||
resultDataSurface->GetData(),
|
||||
resultDataSurface->GetSize(),
|
||||
resultDataSurface->Stride(),
|
||||
resultDataSurface->GetFormat());
|
||||
IntSize readSize = readSurf->GetSize();
|
||||
Rect r(0, 0, readSize.width, readSize.height);
|
||||
DrawOptions opts(1.0f, CompositionOp::OP_SOURCE, AntialiasMode::DEFAULT);
|
||||
dt->DrawSurface(readSurf, r, r, DrawSurfaceOptions(), opts);
|
||||
}
|
||||
|
||||
// If !aDestSurface then we will end up painting using mSurface, so
|
||||
// stick our surface into mSurface, so that the Paint() path is the same.
|
||||
if (!aDestTarget) {
|
||||
mSurface = resultSurf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CopyableCanvasLayer::DeprecatedUpdateSurface(gfxASurface* aDestSurface,
|
||||
Layer* aMaskLayer)
|
||||
{
|
||||
if (!IsDirty())
|
||||
return;
|
||||
Painted();
|
||||
|
||||
if (mDrawTarget) {
|
||||
mDrawTarget->Flush();
|
||||
mDeprecatedSurface =
|
||||
gfxPlatform::GetPlatform()->CreateThebesSurfaceAliasForDrawTarget_hack(mDrawTarget);
|
||||
}
|
||||
|
||||
if (!mGLContext && aDestSurface) {
|
||||
nsRefPtr<gfxContext> tmpCtx = new gfxContext(aDestSurface);
|
||||
tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
CopyableCanvasLayer::PaintWithOpacity(tmpCtx, 1.0f, aMaskLayer);
|
||||
DeprecatedPaintWithOpacity(tmpCtx, 1.0f, aMaskLayer);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -111,7 +205,7 @@ CopyableCanvasLayer::UpdateSurface(gfxASurface* aDestSurface, Layer* aMaskLayer)
|
||||
if (aDestSurface) {
|
||||
resultSurf = aDestSurface;
|
||||
} else {
|
||||
resultSurf = GetTempSurface(readSize, format);
|
||||
resultSurf = DeprecatedGetTempSurface(readSize, format);
|
||||
}
|
||||
MOZ_ASSERT(resultSurf);
|
||||
if (resultSurf->CairoStatus() != 0) {
|
||||
@ -136,11 +230,11 @@ CopyableCanvasLayer::UpdateSurface(gfxASurface* aDestSurface, Layer* aMaskLayer)
|
||||
!(readSurf = resultSurf->GetAsImageSurface()) ||
|
||||
readSurf->Format() != format)
|
||||
{
|
||||
readSurf = GetTempSurface(readSize, format);
|
||||
readSurf = DeprecatedGetTempSurface(readSize, format);
|
||||
}
|
||||
|
||||
// Readback handles Flush/MarkDirty.
|
||||
mGLContext->Screen()->Readback(surfGL, readSurf);
|
||||
mGLContext->Screen()->DeprecatedReadback(surfGL, readSurf);
|
||||
}
|
||||
MOZ_ASSERT(readSurf);
|
||||
|
||||
@ -150,7 +244,7 @@ CopyableCanvasLayer::UpdateSurface(gfxASurface* aDestSurface, Layer* aMaskLayer)
|
||||
gfxUtils::PremultiplyImageSurface(readSurf);
|
||||
readSurf->MarkDirty();
|
||||
}
|
||||
|
||||
|
||||
if (readSurf != resultSurf) {
|
||||
readSurf->Flush();
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(resultSurf);
|
||||
@ -162,23 +256,69 @@ CopyableCanvasLayer::UpdateSurface(gfxASurface* aDestSurface, Layer* aMaskLayer)
|
||||
// If !aDestSurface then we will end up painting using mSurface, so
|
||||
// stick our surface into mSurface, so that the Paint() path is the same.
|
||||
if (!aDestSurface) {
|
||||
mSurface = resultSurf;
|
||||
mDeprecatedSurface = resultSurf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CopyableCanvasLayer::PaintWithOpacity(gfxContext* aContext,
|
||||
CopyableCanvasLayer::PaintWithOpacity(gfx::DrawTarget* aTarget,
|
||||
float aOpacity,
|
||||
Layer* aMaskLayer,
|
||||
gfxContext::GraphicsOperator aOperator)
|
||||
SourceSurface* aMaskSurface,
|
||||
gfx::CompositionOp aOperator)
|
||||
{
|
||||
if (!mSurface) {
|
||||
NS_WARNING("No valid surface to draw!");
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<gfxPattern> pat = new gfxPattern(mSurface);
|
||||
SurfacePattern pat(mSurface, ExtendMode::CLAMP, Matrix(), ToFilter(mFilter));
|
||||
|
||||
Matrix oldTransform;
|
||||
if (mNeedsYFlip) {
|
||||
oldTransform = aTarget->GetTransform();
|
||||
Matrix flipped = oldTransform;
|
||||
flipped.Translate(0, mBounds.height);
|
||||
flipped.Scale(1.0, -1.0);
|
||||
aTarget->SetTransform(flipped);
|
||||
}
|
||||
|
||||
DrawOptions options = DrawOptions(aOpacity, CompositionOp::OP_SOURCE);
|
||||
|
||||
// If content opaque, then save off current operator and set to source.
|
||||
// This ensures that alpha is not applied even if the source surface
|
||||
// has an alpha channel
|
||||
if (GetContentFlags() & CONTENT_OPAQUE) {
|
||||
options.mCompositionOp = CompositionOp::OP_SOURCE;
|
||||
}
|
||||
|
||||
if (aOperator != CompositionOp::OP_OVER) {
|
||||
options.mCompositionOp = aOperator;
|
||||
}
|
||||
|
||||
Rect rect = Rect(0, 0, mBounds.width, mBounds.height);
|
||||
aTarget->FillRect(rect, pat, options);
|
||||
if (aMaskSurface) {
|
||||
aTarget->MaskSurface(pat, aMaskSurface, Point(0, 0), options);
|
||||
}
|
||||
|
||||
if (mNeedsYFlip) {
|
||||
aTarget->SetTransform(oldTransform);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CopyableCanvasLayer::DeprecatedPaintWithOpacity(gfxContext* aContext,
|
||||
float aOpacity,
|
||||
Layer* aMaskLayer,
|
||||
gfxContext::GraphicsOperator aOperator)
|
||||
{
|
||||
if (!mDeprecatedSurface) {
|
||||
NS_WARNING("No valid surface to draw!");
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<gfxPattern> pat = new gfxPattern(mDeprecatedSurface);
|
||||
|
||||
pat->SetFilter(mFilter);
|
||||
pat->SetExtend(gfxPattern::EXTEND_PAD);
|
||||
@ -216,27 +356,50 @@ CopyableCanvasLayer::PaintWithOpacity(gfxContext* aContext,
|
||||
}
|
||||
}
|
||||
|
||||
gfxImageSurface*
|
||||
CopyableCanvasLayer::GetTempSurface(const IntSize& aSize, const gfxImageFormat aFormat)
|
||||
DataSourceSurface*
|
||||
CopyableCanvasLayer::GetTempSurface(const IntSize& aSize,
|
||||
const SurfaceFormat aFormat)
|
||||
{
|
||||
if (!mCachedTempSurface ||
|
||||
aSize.width != mCachedSize.width ||
|
||||
aSize.height != mCachedSize.height ||
|
||||
aFormat != mCachedFormat)
|
||||
{
|
||||
mCachedTempSurface = new gfxImageSurface(ThebesIntSize(aSize), aFormat);
|
||||
mCachedTempSurface = Factory::CreateDataSourceSurface(aSize, aFormat);
|
||||
mCachedSize = aSize;
|
||||
mCachedFormat = aFormat;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mCachedTempSurface->Stride() == mCachedTempSurface->Width() * 4);
|
||||
MOZ_ASSERT(mCachedTempSurface->Stride() ==
|
||||
mCachedTempSurface->GetSize().width * 4);
|
||||
return mCachedTempSurface;
|
||||
}
|
||||
|
||||
gfxImageSurface*
|
||||
CopyableCanvasLayer::DeprecatedGetTempSurface(const IntSize& aSize,
|
||||
const gfxImageFormat aFormat)
|
||||
{
|
||||
if (!mDeprecatedCachedTempSurface ||
|
||||
aSize.width != mCachedSize.width ||
|
||||
aSize.height != mCachedSize.height ||
|
||||
aFormat != mDeprecatedCachedFormat)
|
||||
{
|
||||
mDeprecatedCachedTempSurface =
|
||||
new gfxImageSurface(ThebesIntSize(aSize), aFormat);
|
||||
mCachedSize = aSize;
|
||||
mDeprecatedCachedFormat = aFormat;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mDeprecatedCachedTempSurface->Stride() ==
|
||||
mDeprecatedCachedTempSurface->Width() * 4);
|
||||
return mDeprecatedCachedTempSurface;
|
||||
}
|
||||
|
||||
void
|
||||
CopyableCanvasLayer::DiscardTempSurface()
|
||||
{
|
||||
mCachedTempSurface = nullptr;
|
||||
mDeprecatedCachedTempSurface = nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -41,15 +41,16 @@ public:
|
||||
virtual bool IsDataValid(const Data& aData);
|
||||
|
||||
protected:
|
||||
void PaintWithOpacity(gfxContext* aContext,
|
||||
void PaintWithOpacity(gfx::DrawTarget* aTarget,
|
||||
float aOpacity,
|
||||
Layer* aMaskLayer,
|
||||
gfxContext::GraphicsOperator aOperator = gfxContext::OPERATOR_OVER);
|
||||
gfx::SourceSurface* aMaskSurface,
|
||||
gfx::CompositionOp aOperator = gfx::CompositionOp::OP_OVER);
|
||||
|
||||
void UpdateSurface(gfxASurface* aDestSurface = nullptr,
|
||||
Layer* aMaskLayer = nullptr);
|
||||
void UpdateTarget(gfx::DrawTarget* aDestTarget = nullptr,
|
||||
gfx::SourceSurface* aMaskSurface = nullptr);
|
||||
|
||||
nsRefPtr<gfxASurface> mSurface;
|
||||
RefPtr<gfx::SourceSurface> mSurface;
|
||||
nsRefPtr<gfxASurface> mDeprecatedSurface;
|
||||
nsRefPtr<mozilla::gl::GLContext> mGLContext;
|
||||
mozilla::RefPtr<mozilla::gfx::DrawTarget> mDrawTarget;
|
||||
|
||||
@ -59,13 +60,30 @@ protected:
|
||||
bool mNeedsYFlip;
|
||||
bool mForceReadback;
|
||||
|
||||
nsRefPtr<gfxImageSurface> mCachedTempSurface;
|
||||
RefPtr<gfx::DataSourceSurface> mCachedTempSurface;
|
||||
nsRefPtr<gfxImageSurface> mDeprecatedCachedTempSurface;
|
||||
gfx::IntSize mCachedSize;
|
||||
gfxImageFormat mCachedFormat;
|
||||
gfx::SurfaceFormat mCachedFormat;
|
||||
gfxImageFormat mDeprecatedCachedFormat;
|
||||
|
||||
gfxImageSurface* GetTempSurface(const gfx::IntSize& aSize, const gfxImageFormat aFormat);
|
||||
gfx::DataSourceSurface* GetTempSurface(const gfx::IntSize& aSize,
|
||||
const gfx::SurfaceFormat aFormat);
|
||||
|
||||
void DiscardTempSurface();
|
||||
|
||||
/* Deprecated thebes methods */
|
||||
protected:
|
||||
void DeprecatedPaintWithOpacity(gfxContext* aContext,
|
||||
float aOpacity,
|
||||
Layer* aMaskLayer,
|
||||
gfxContext::GraphicsOperator aOperator = gfxContext::OPERATOR_OVER);
|
||||
|
||||
void DeprecatedUpdateSurface(gfxASurface* aDestSurface = nullptr,
|
||||
Layer* aMaskLayer = nullptr);
|
||||
|
||||
gfxImageSurface* DeprecatedGetTempSurface(const gfx::IntSize& aSize,
|
||||
const gfxImageFormat aFormat);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -710,8 +710,8 @@ class AutoLockImage
|
||||
{
|
||||
public:
|
||||
AutoLockImage(ImageContainer *aContainer) : mContainer(aContainer) { mImage = mContainer->LockCurrentImage(); }
|
||||
AutoLockImage(ImageContainer *aContainer, gfxASurface **aSurface) : mContainer(aContainer) {
|
||||
*aSurface = mContainer->DeprecatedLockCurrentAsSurface(&mSize, getter_AddRefs(mImage)).get();
|
||||
AutoLockImage(ImageContainer *aContainer, RefPtr<gfx::SourceSurface> *aSurface) : mContainer(aContainer) {
|
||||
*aSurface = mContainer->LockCurrentAsSourceSurface(&mSize, getter_AddRefs(mImage));
|
||||
}
|
||||
~AutoLockImage() { if (mContainer) { mContainer->UnlockCurrentImage(); } }
|
||||
|
||||
|
79
gfx/layers/LayerUtils.cpp
Normal file
79
gfx/layers/LayerUtils.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "LayerUtils.h"
|
||||
#include "PremultiplyTables.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
static inline const uint8_t PremultiplyValue(uint8_t a, uint8_t v) {
|
||||
return PremultiplyTable[a*256+v];
|
||||
}
|
||||
|
||||
static inline const uint8_t UnpremultiplyValue(uint8_t a, uint8_t v) {
|
||||
return UnpremultiplyTable[a*256+v];
|
||||
}
|
||||
|
||||
void
|
||||
PremultiplySurface(DataSourceSurface* srcSurface,
|
||||
DataSourceSurface* destSurface)
|
||||
{
|
||||
if (!destSurface)
|
||||
destSurface = srcSurface;
|
||||
|
||||
IntSize srcSize = srcSurface->GetSize();
|
||||
MOZ_ASSERT(srcSurface->GetFormat() == destSurface->GetFormat() &&
|
||||
srcSize.width == destSurface->GetSize().width &&
|
||||
srcSize.height == destSurface->GetSize().height &&
|
||||
srcSurface->Stride() == destSurface->Stride(),
|
||||
"Source and destination surfaces don't have identical characteristics");
|
||||
|
||||
MOZ_ASSERT(srcSurface->Stride() == srcSize.width * 4,
|
||||
"Source surface stride isn't tightly packed");
|
||||
|
||||
// Only premultiply ARGB32
|
||||
if (srcSurface->GetFormat() != SurfaceFormat::B8G8R8A8) {
|
||||
if (destSurface != srcSurface) {
|
||||
memcpy(destSurface->GetData(), srcSurface->GetData(),
|
||||
srcSurface->Stride() * srcSize.height);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t *src = srcSurface->GetData();
|
||||
uint8_t *dst = destSurface->GetData();
|
||||
|
||||
uint32_t dim = srcSize.width * srcSize.height;
|
||||
for (uint32_t i = 0; i < dim; ++i) {
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
uint8_t b = *src++;
|
||||
uint8_t g = *src++;
|
||||
uint8_t r = *src++;
|
||||
uint8_t a = *src++;
|
||||
|
||||
*dst++ = PremultiplyValue(a, b);
|
||||
*dst++ = PremultiplyValue(a, g);
|
||||
*dst++ = PremultiplyValue(a, r);
|
||||
*dst++ = a;
|
||||
#else
|
||||
uint8_t a = *src++;
|
||||
uint8_t r = *src++;
|
||||
uint8_t g = *src++;
|
||||
uint8_t b = *src++;
|
||||
|
||||
*dst++ = a;
|
||||
*dst++ = PremultiplyValue(a, r);
|
||||
*dst++ = PremultiplyValue(a, g);
|
||||
*dst++ = PremultiplyValue(a, b);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
21
gfx/layers/LayerUtils.h
Normal file
21
gfx/layers/LayerUtils.h
Normal file
@ -0,0 +1,21 @@
|
||||
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MOZILLA_LAYERS_LAYERUTILS_H_
|
||||
#define MOZILLA_LAYERS_LAYERUTILS_H_
|
||||
|
||||
#include "mozilla/gfx/2D.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
void
|
||||
PremultiplySurface(gfx::DataSourceSurface* srcSurface,
|
||||
gfx::DataSourceSurface* destSurface = nullptr);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* MOZILLA_LAYERS_LAYERUTILS_H_ */
|
@ -169,7 +169,7 @@ Layer::Layer(LayerManager* aManager, void* aImplData) :
|
||||
mPostXScale(1.0f),
|
||||
mPostYScale(1.0f),
|
||||
mOpacity(1.0),
|
||||
mMixBlendMode(gfxContext::OPERATOR_OVER),
|
||||
mMixBlendMode(CompositionOp::OP_OVER),
|
||||
mForceIsolatedGroup(false),
|
||||
mContentFlags(0),
|
||||
mUseClipRect(false),
|
||||
@ -670,20 +670,26 @@ Layer::GetEffectiveOpacity()
|
||||
return opacity;
|
||||
}
|
||||
|
||||
gfxContext::GraphicsOperator
|
||||
CompositionOp
|
||||
Layer::GetEffectiveMixBlendMode()
|
||||
{
|
||||
if(mMixBlendMode != gfxContext::OPERATOR_OVER)
|
||||
if(mMixBlendMode != CompositionOp::OP_OVER)
|
||||
return mMixBlendMode;
|
||||
for (ContainerLayer* c = GetParent(); c && !c->UseIntermediateSurface();
|
||||
c = c->GetParent()) {
|
||||
if(c->mMixBlendMode != gfxContext::OPERATOR_OVER)
|
||||
if(c->mMixBlendMode != CompositionOp::OP_OVER)
|
||||
return c->mMixBlendMode;
|
||||
}
|
||||
|
||||
return mMixBlendMode;
|
||||
}
|
||||
|
||||
gfxContext::GraphicsOperator
|
||||
Layer::DeprecatedGetEffectiveMixBlendMode()
|
||||
{
|
||||
return ThebesOp(GetEffectiveMixBlendMode());
|
||||
}
|
||||
|
||||
void
|
||||
Layer::ComputeEffectiveTransformForMaskLayer(const Matrix4x4& aTransformToSurface)
|
||||
{
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "GraphicsFilter.h" // for GraphicsFilter
|
||||
#include "gfxPoint.h" // for gfxPoint
|
||||
#include "gfxRect.h" // for gfxRect
|
||||
#include "gfx2DGlue.h"
|
||||
#include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2, etc
|
||||
#include "mozilla/DebugOnly.h" // for DebugOnly
|
||||
#include "mozilla/EventForwards.h" // for nsPaintEvent
|
||||
@ -786,7 +787,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void SetMixBlendMode(gfxContext::GraphicsOperator aMixBlendMode)
|
||||
void SetMixBlendMode(gfx::CompositionOp aMixBlendMode)
|
||||
{
|
||||
if (mMixBlendMode != aMixBlendMode) {
|
||||
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) MixBlendMode", this));
|
||||
@ -795,6 +796,11 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void DeprecatedSetMixBlendMode(gfxContext::GraphicsOperator aMixBlendMode)
|
||||
{
|
||||
SetMixBlendMode(gfx::CompositionOpForOp(aMixBlendMode));
|
||||
}
|
||||
|
||||
void SetForceIsolatedGroup(bool aForceIsolatedGroup)
|
||||
{
|
||||
if(mForceIsolatedGroup != aForceIsolatedGroup) {
|
||||
@ -1033,7 +1039,7 @@ public:
|
||||
|
||||
// These getters can be used anytime.
|
||||
float GetOpacity() { return mOpacity; }
|
||||
gfxContext::GraphicsOperator GetMixBlendMode() const { return mMixBlendMode; }
|
||||
gfx::CompositionOp GetMixBlendMode() const { return mMixBlendMode; }
|
||||
const nsIntRect* GetClipRect() { return mUseClipRect ? &mClipRect : nullptr; }
|
||||
uint32_t GetContentFlags() { return mContentFlags; }
|
||||
const nsIntRegion& GetVisibleRegion() { return mVisibleRegion; }
|
||||
@ -1207,7 +1213,8 @@ public:
|
||||
/**
|
||||
* Returns the blendmode of this layer.
|
||||
*/
|
||||
gfxContext::GraphicsOperator GetEffectiveMixBlendMode();
|
||||
gfx::CompositionOp GetEffectiveMixBlendMode();
|
||||
gfxContext::GraphicsOperator DeprecatedGetEffectiveMixBlendMode();
|
||||
|
||||
/**
|
||||
* This returns the effective transform computed by
|
||||
@ -1408,7 +1415,7 @@ protected:
|
||||
AnimationArray mAnimations;
|
||||
InfallibleTArray<AnimData> mAnimationData;
|
||||
float mOpacity;
|
||||
gfxContext::GraphicsOperator mMixBlendMode;
|
||||
gfx::CompositionOp mMixBlendMode;
|
||||
bool mForceIsolatedGroup;
|
||||
nsIntRect mClipRect;
|
||||
nsIntRect mTileSourceRect;
|
||||
|
@ -13,3 +13,6 @@ CXXFLAGS += \
|
||||
$(NULL)
|
||||
|
||||
CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(TK_CFLAGS)
|
||||
|
||||
PremultiplyTables.h: $(srcdir)/genTables.py
|
||||
$(PYTHON) $(srcdir)/genTables.py
|
||||
|
@ -301,9 +301,17 @@ RotatedContentBuffer::BufferContentType()
|
||||
bool
|
||||
RotatedContentBuffer::BufferSizeOkFor(const nsIntSize& aSize)
|
||||
{
|
||||
return (aSize == mBufferRect.Size() ||
|
||||
(SizedToVisibleBounds != mBufferSizePolicy &&
|
||||
aSize < mBufferRect.Size()));
|
||||
if (aSize == mBufferRect.Size()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (SizedToVisibleBounds != mBufferSizePolicy &&
|
||||
aSize < mBufferRect.Size()) {
|
||||
return (aSize.width * 2 > mBufferRect.width) &&
|
||||
(aSize.height * 2 > mBufferRect.height);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -503,8 +511,9 @@ RotatedContentBuffer::BeginPaint(ThebesLayer* aLayer,
|
||||
// or call CreateBuffer before this call.
|
||||
FinalizeFrame(result.mRegionToDraw);
|
||||
|
||||
if (result.mRegionToDraw.IsEmpty())
|
||||
if (result.mRegionToDraw.IsEmpty()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
nsIntRect drawBounds = result.mRegionToDraw.GetBounds();
|
||||
RefPtr<DrawTarget> destDTBuffer;
|
||||
@ -614,7 +623,7 @@ RotatedContentBuffer::BeginPaint(ThebesLayer* aLayer,
|
||||
mBufferRotation = nsIntPoint(0,0);
|
||||
}
|
||||
} else {
|
||||
// The buffer's not big enough, so allocate a new one
|
||||
// The buffer's not big enough or the buffer needs to shrink, so allocate a new one
|
||||
CreateBuffer(result.mContentType, destBufferRect, bufferFlags,
|
||||
&destDTBuffer, &destDTBufferOnWhite);
|
||||
if (!destDTBuffer) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user