mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-01 17:23:59 +00:00
Merge m-c to m-i.
This commit is contained in:
commit
52fc40391f
@ -258,7 +258,7 @@ DocAccessibleWrap::DoInitialUpdate()
|
||||
|
||||
a11y::RootAccessible* rootDocument = RootAccessible();
|
||||
|
||||
mozilla::WindowsHandle nativeData = nsnull;
|
||||
mozilla::WindowsHandle nativeData = NULL;
|
||||
if (tabChild)
|
||||
tabChild->SendGetWidgetNativeData(&nativeData);
|
||||
else
|
||||
|
@ -122,11 +122,14 @@ var shell = {
|
||||
.sessionHistory = Cc["@mozilla.org/browser/shistory;1"]
|
||||
.createInstance(Ci.nsISHistory);
|
||||
|
||||
['keydown', 'keypress', 'keyup'].forEach((function listenKey(type) {
|
||||
window.addEventListener(type, this, false, true);
|
||||
window.addEventListener(type, this, true, true);
|
||||
}).bind(this));
|
||||
|
||||
// Capture all key events so we can filter out hardware buttons
|
||||
// And send them to Gaia via mozChromeEvents.
|
||||
// Ideally, hardware buttons wouldn't generate key events at all, or
|
||||
// if they did, they would use keycodes that conform to DOM 3 Events.
|
||||
// See discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=762362
|
||||
window.addEventListener('keydown', this, true);
|
||||
window.addEventListener('keypress', this, true);
|
||||
window.addEventListener('keyup', this, true);
|
||||
window.addEventListener('MozApplicationManifest', this);
|
||||
window.addEventListener('mozfullscreenchange', this);
|
||||
window.addEventListener('sizemodechange', this);
|
||||
@ -165,11 +168,9 @@ var shell = {
|
||||
},
|
||||
|
||||
stop: function shell_stop() {
|
||||
['keydown', 'keypress', 'keyup'].forEach((function unlistenKey(type) {
|
||||
window.removeEventListener(type, this, false, true);
|
||||
window.removeEventListener(type, this, true, true);
|
||||
}).bind(this));
|
||||
|
||||
window.removeEventListener('keydown', this, true);
|
||||
window.removeEventListener('keypress', this, true);
|
||||
window.removeEventListener('keyup', this, true);
|
||||
window.removeEventListener('MozApplicationManifest', this);
|
||||
window.removeEventListener('mozfullscreenchange', this);
|
||||
window.removeEventListener('sizemodechange', this);
|
||||
@ -180,15 +181,66 @@ var shell = {
|
||||
#endif
|
||||
},
|
||||
|
||||
forwardKeyToContent: function shell_forwardKeyToContent(evt) {
|
||||
let content = shell.contentBrowser.contentWindow;
|
||||
let generatedEvent = content.document.createEvent('KeyboardEvent');
|
||||
generatedEvent.initKeyEvent(evt.type, true, true, evt.view, evt.ctrlKey,
|
||||
evt.altKey, evt.shiftKey, evt.metaKey,
|
||||
evt.keyCode, evt.charCode);
|
||||
// If this key event actually represents a hardware button, filter it here
|
||||
// and send a mozChromeEvent with detail.type set to xxx-button-press or
|
||||
// xxx-button-release instead.
|
||||
filterHardwareKeys: function shell_filterHardwareKeys(evt) {
|
||||
var type;
|
||||
switch (evt.keyCode) {
|
||||
case evt.DOM_VK_HOME: // Home button
|
||||
type = 'home-button';
|
||||
break;
|
||||
case evt.DOM_VK_SLEEP: // Sleep button
|
||||
type = 'sleep-button';
|
||||
break;
|
||||
case evt.DOM_VK_PAGE_UP: // Volume up button
|
||||
type = 'volume-up-button';
|
||||
break;
|
||||
case evt.DOM_VK_PAGE_DOWN: // Volume down button
|
||||
type = 'volume-down-button';
|
||||
break;
|
||||
case evt.DOM_VK_ESCAPE: // Back button (should be disabled)
|
||||
type = 'back-button';
|
||||
break;
|
||||
case evt.DOM_VK_CONTEXT_MENU: // Menu button
|
||||
type = 'menu-button';
|
||||
break;
|
||||
default: // Anything else is a real key
|
||||
return; // Don't filter it at all; let it propagate to Gaia
|
||||
}
|
||||
|
||||
content.document.documentElement.dispatchEvent(generatedEvent);
|
||||
// If we didn't return, then the key event represents a hardware key
|
||||
// and we need to prevent it from propagating to Gaia
|
||||
evt.stopImmediatePropagation();
|
||||
evt.preventDefault(); // Prevent keypress events (when #501496 is fixed).
|
||||
|
||||
// If it is a key down or key up event, we send a chrome event to Gaia.
|
||||
// If it is a keypress event we just ignore it.
|
||||
switch (evt.type) {
|
||||
case 'keydown':
|
||||
type = type + '-press';
|
||||
break;
|
||||
case 'keyup':
|
||||
type = type + '-release';
|
||||
break;
|
||||
case 'keypress':
|
||||
return;
|
||||
}
|
||||
|
||||
// On my device, the physical hardware buttons (sleep and volume)
|
||||
// send multiple events (press press release release), but the
|
||||
// soft home button just sends one. This hack is to manually
|
||||
// "debounce" the keys. If the type of this event is the same as
|
||||
// the type of the last one, then don't send it. We'll never send
|
||||
// two presses or two releases in a row.
|
||||
// FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=761067
|
||||
if (type !== this.lastHardwareButtonEventType) {
|
||||
this.lastHardwareButtonEventType = type;
|
||||
this.sendChromeEvent({type: type});
|
||||
}
|
||||
},
|
||||
|
||||
lastHardwareButtonEventType: null, // property for the hack above
|
||||
|
||||
handleEvent: function shell_handleEvent(evt) {
|
||||
let content = this.contentBrowser.contentWindow;
|
||||
@ -196,17 +248,8 @@ var shell = {
|
||||
case 'keydown':
|
||||
case 'keyup':
|
||||
case 'keypress':
|
||||
// Redirect the HOME key to System app and stop the applications from
|
||||
// handling it.
|
||||
let rootContentEvt = (evt.target.ownerDocument.defaultView == content);
|
||||
if (!rootContentEvt && evt.eventPhase == evt.CAPTURING_PHASE &&
|
||||
evt.keyCode == evt.DOM_VK_HOME) {
|
||||
this.forwardKeyToContent(evt);
|
||||
evt.preventDefault();
|
||||
evt.stopImmediatePropagation();
|
||||
}
|
||||
this.filterHardwareKeys(evt);
|
||||
break;
|
||||
|
||||
case 'mozfullscreenchange':
|
||||
// When the screen goes fullscreen make sure to set the focus to the
|
||||
// main window so noboby can prevent the ESC key to get out fullscreen
|
||||
@ -272,6 +315,9 @@ var shell = {
|
||||
let event = content.document.createEvent('CustomEvent');
|
||||
event.initCustomEvent(type, true, true, details ? details : {});
|
||||
content.dispatchEvent(event);
|
||||
},
|
||||
sendChromeEvent: function shell_sendChromeEvent(details) {
|
||||
this.sendEvent(getContentWindow(), "mozChromeEvent", details);
|
||||
}
|
||||
};
|
||||
|
||||
@ -310,7 +356,7 @@ nsBrowserAccess.prototype = {
|
||||
Services.obs.addObserver(function onSystemMessage(subject, topic, data) {
|
||||
let msg = JSON.parse(data);
|
||||
let origin = Services.io.newURI(msg.manifest, null, null).prePath;
|
||||
shell.sendEvent(shell.contentBrowser.contentWindow, 'mozChromeEvent', {
|
||||
shell.sendChromeEvent({
|
||||
type: 'open-app',
|
||||
url: msg.uri,
|
||||
origin: origin,
|
||||
@ -415,12 +461,22 @@ var AlertsHelper = {
|
||||
return id;
|
||||
},
|
||||
|
||||
showAlertNotification: function alert_showAlertNotification(imageUrl, title, text, textClickable,
|
||||
cookie, alertListener, name) {
|
||||
showAlertNotification: function alert_showAlertNotification(imageUrl,
|
||||
title,
|
||||
text,
|
||||
textClickable,
|
||||
cookie,
|
||||
alertListener,
|
||||
name)
|
||||
{
|
||||
let id = this.registerListener(cookie, alertListener);
|
||||
let content = shell.contentBrowser.contentWindow;
|
||||
shell.sendEvent(content, "mozChromeEvent", { type: "desktop-notification", id: id, icon: imageUrl,
|
||||
title: title, text: text } );
|
||||
shell.sendChromeEvent({
|
||||
type: "desktop-notification",
|
||||
id: id,
|
||||
icon: imageUrl,
|
||||
title: title,
|
||||
text: text
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -456,7 +512,6 @@ var WebappsHelper = {
|
||||
},
|
||||
|
||||
observe: function webapps_observe(subject, topic, data) {
|
||||
let content = shell.contentBrowser.contentWindow;
|
||||
let json = JSON.parse(data);
|
||||
switch(topic) {
|
||||
case "webapps-launch":
|
||||
@ -465,7 +520,7 @@ var WebappsHelper = {
|
||||
return;
|
||||
|
||||
let manifest = new DOMApplicationManifest(aManifest, json.origin);
|
||||
shell.sendEvent(content, "mozChromeEvent", {
|
||||
shell.sendChromeEvent({
|
||||
"type": "webapps-launch",
|
||||
"url": manifest.fullLaunchPath(json.startPoint),
|
||||
"origin": json.origin
|
||||
@ -474,7 +529,11 @@ var WebappsHelper = {
|
||||
break;
|
||||
case "webapps-ask-install":
|
||||
let id = this.registerInstaller(json);
|
||||
shell.sendEvent(content, "mozChromeEvent", { type: "webapps-ask-install", id: id, app: json.app } );
|
||||
shell.sendChromeEvent({
|
||||
type: "webapps-ask-install",
|
||||
id: id,
|
||||
app: json.app
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -529,16 +588,28 @@ window.addEventListener('ContentStart', function ss_onContentStart() {
|
||||
context.drawWindow(window, 0, 0, width, height,
|
||||
'rgb(255,255,255)', flags);
|
||||
|
||||
shell.sendEvent(content, 'mozChromeEvent', {
|
||||
type: 'take-screenshot-success',
|
||||
file: canvas.mozGetAsFile('screenshot', 'image/png')
|
||||
shell.sendChromeEvent({
|
||||
type: 'take-screenshot-success',
|
||||
file: canvas.mozGetAsFile('screenshot', 'image/png')
|
||||
});
|
||||
} catch (e) {
|
||||
dump('exception while creating screenshot: ' + e + '\n');
|
||||
shell.sendEvent(content, 'mozChromeEvent', {
|
||||
shell.sendChromeEvent({
|
||||
type: 'take-screenshot-error',
|
||||
error: String(e)
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Services.obs.addObserver(function ContentHandler(subject, topic, data) {
|
||||
let handler = JSON.parse(data);
|
||||
new MozActivity({
|
||||
name: 'view',
|
||||
data: {
|
||||
type: handler.type,
|
||||
url: handler.url
|
||||
}
|
||||
});
|
||||
}, 'content-handler', false);
|
||||
|
||||
|
@ -38,3 +38,8 @@ contract @mozilla.org/dom/activities/ui-glue;1 {70a83123-7467-4389-a309-3e81c74a
|
||||
component {1a94c87a-5ece-4d11-91e1-d29c29f21b28} ProcessGlobal.js
|
||||
contract @mozilla.org/b2g-process-global;1 {1a94c87a-5ece-4d11-91e1-d29c29f21b28}
|
||||
category app-startup ProcessGlobal service,@mozilla.org/b2g-process-global;1
|
||||
|
||||
# ContentHandler.js
|
||||
component {d18d0216-d50c-11e1-ba54-efb18d0ef0ac} ContentHandler.js
|
||||
contract @mozilla.org/uriloader/content-handler;1?type=application/pdf {d18d0216-d50c-11e1-ba54-efb18d0ef0ac}
|
||||
|
||||
|
48
b2g/components/ContentHandler.js
Normal file
48
b2g/components/ContentHandler.js
Normal file
@ -0,0 +1,48 @@
|
||||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
"use strict";
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
|
||||
const PDF_CONTENT_TYPE = "application/pdf";
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function log(aMsg) {
|
||||
let msg = "ContentHandler.js: " + (aMsg.join ? aMsg.join("") : aMsg);
|
||||
Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService)
|
||||
.logStringMessage(msg);
|
||||
dump(msg + "\n");
|
||||
}
|
||||
|
||||
const NS_ERROR_WONT_HANDLE_CONTENT = 0x805d0001;
|
||||
function ContentHandler() {
|
||||
}
|
||||
|
||||
ContentHandler.prototype = {
|
||||
handleContent: function handleContent(aMimetype, aContext, aRequest) {
|
||||
if (aMimetype != PDF_CONTENT_TYPE)
|
||||
throw NS_ERROR_WONT_HANDLE_CONTENT;
|
||||
|
||||
if (!(aRequest instanceof Ci.nsIChannel))
|
||||
throw NS_ERROR_WONT_HANDLE_CONTENT;
|
||||
|
||||
let detail = {
|
||||
"type": aMimetype,
|
||||
"url": aRequest.URI.spec
|
||||
};
|
||||
Services.obs.notifyObservers(this, "content-handler", JSON.stringify(detail));
|
||||
|
||||
aRequest.cancel(Cr.NS_BINDING_ABORTED);
|
||||
},
|
||||
|
||||
classID: Components.ID("{d18d0216-d50c-11e1-ba54-efb18d0ef0ac}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentHandler])
|
||||
};
|
||||
|
||||
var NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentHandler]);
|
@ -22,7 +22,7 @@ DirectoryProvider.prototype = {
|
||||
|
||||
getFile: function dp_getFile(prop, persistent) {
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
let localProps = ["cachePDir", "webappsDir", "PrefD", "indexedDBPDir"];
|
||||
let localProps = ["cachePDir", "webappsDir", "PrefD", "indexedDBPDir", "permissionDBPDir"];
|
||||
if (localProps.indexOf(prop) != -1) {
|
||||
prop.persistent = true;
|
||||
let file = Cc["@mozilla.org/file/local;1"]
|
||||
|
@ -17,14 +17,15 @@ XPIDLSRCS = \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_PP_COMPONENTS = \
|
||||
ActivitiesGlue.js \
|
||||
AlertsService.js \
|
||||
B2GComponents.manifest \
|
||||
CameraContent.js \
|
||||
ContentHandler.js \
|
||||
ContentPermissionPrompt.js \
|
||||
DirectoryProvider.js \
|
||||
MozKeyboard.js \
|
||||
ProcessGlobal.js \
|
||||
ActivitiesGlue.js \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_UPDATER
|
||||
|
@ -684,3 +684,4 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@
|
||||
@BINPATH@/components/DirectoryProvider.js
|
||||
@BINPATH@/components/ActivitiesGlue.js
|
||||
@BINPATH@/components/ProcessGlobal.js
|
||||
@BINPATH@/components/ContentHandler.js
|
||||
|
@ -43,12 +43,26 @@ static void Output(const char *fmt, ... )
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
#if defined(XP_WIN) && !MOZ_WINCONSOLE
|
||||
PRUnichar msg[2048];
|
||||
_vsnwprintf(msg, sizeof(msg)/sizeof(msg[0]), NS_ConvertUTF8toUTF16(fmt).get(), ap);
|
||||
MessageBoxW(NULL, msg, L"XULRunner", MB_OK | MB_ICONERROR);
|
||||
#else
|
||||
#ifndef XP_WIN
|
||||
vfprintf(stderr, fmt, ap);
|
||||
#else
|
||||
char msg[2048];
|
||||
vsnprintf_s(msg, _countof(msg), _TRUNCATE, fmt, ap);
|
||||
|
||||
wchar_t wide_msg[2048];
|
||||
MultiByteToWideChar(CP_UTF8,
|
||||
0,
|
||||
msg,
|
||||
-1,
|
||||
wide_msg,
|
||||
_countof(wide_msg));
|
||||
#if MOZ_WINCONSOLE
|
||||
fwprintf_s(stderr, wide_msg);
|
||||
#else
|
||||
MessageBoxW(NULL, wide_msg, L"Firefox", MB_OK
|
||||
| MB_ICONERROR
|
||||
| MB_SETFOREGROUND);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
va_end(ap);
|
||||
|
@ -1186,3 +1186,5 @@ pref("image.mem.max_decoded_image_kb", 256000);
|
||||
// Example social provider
|
||||
pref("social.manifest.motown", "{\"origin\":\"https://motown-dev.mozillalabs.com\",\"name\":\"MoTown\",\"workerURL\":\"https://motown-dev.mozillalabs.com/social/worker.js\",\"iconURL\":\"https://motown-dev.mozillalabs.com/images/motown-icon.png\",\"sidebarURL\":\"https://motown-dev.mozillalabs.com/social/sidebar\"}");
|
||||
pref("social.sidebar.open", true);
|
||||
pref("browser.social.whitelist", "");
|
||||
pref("social.active", false);
|
||||
|
@ -332,6 +332,10 @@
|
||||
label="&preferencesCmd2.label;"
|
||||
#endif
|
||||
oncommand="openPreferences();">
|
||||
<menuitem id="appmenu_socialToggle"
|
||||
type="checkbox"
|
||||
autocheck="false"
|
||||
command="Social:Toggle"/>
|
||||
<menupopup id="appmenu_customizeMenu"
|
||||
onpopupshowing="onViewToolbarsPopupShowing(event, document.getElementById('appmenu_toggleToolbarsSeparator'));">
|
||||
<menuitem id="appmenu_preferences"
|
||||
|
@ -496,6 +496,10 @@
|
||||
accesskey="&addons.accesskey;"
|
||||
key="key_openAddons"
|
||||
command="Tools:Addons"/>
|
||||
<menuitem id="menu_socialToggle"
|
||||
type="checkbox"
|
||||
autocheck="false"
|
||||
command="Social:Toggle"/>
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
<!-- only one of sync-setup or sync-menu will be showing at once -->
|
||||
<menuitem id="sync-setup"
|
||||
|
@ -108,6 +108,7 @@
|
||||
<command id="Social:SharePage" oncommand="SocialShareButton.sharePage();"/>
|
||||
<command id="Social:UnsharePage" oncommand="SocialShareButton.unsharePage();"/>
|
||||
<command id="Social:ToggleSidebar" oncommand="Social.toggleSidebar();"/>
|
||||
<command id="Social:Toggle" oncommand="Social.toggle();" hidden="true"/>
|
||||
</commandset>
|
||||
|
||||
<commandset id="placesCommands">
|
||||
|
@ -11,6 +11,8 @@ let SocialUI = {
|
||||
|
||||
Services.prefs.addObserver("social.sidebar.open", this, false);
|
||||
|
||||
gBrowser.addEventListener("ActivateSocialFeature", this._activationEventHandler, true, true);
|
||||
|
||||
Social.init(this._providerReady.bind(this));
|
||||
},
|
||||
|
||||
@ -31,6 +33,7 @@ let SocialUI = {
|
||||
observe: function SocialUI_observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "social:pref-changed":
|
||||
this.updateToggleCommand();
|
||||
SocialShareButton.updateButtonHiddenState();
|
||||
SocialToolbar.updateButtonHiddenState();
|
||||
SocialSidebar.updateSidebar();
|
||||
@ -46,11 +49,103 @@ let SocialUI = {
|
||||
}
|
||||
},
|
||||
|
||||
get toggleCommand() {
|
||||
return document.getElementById("Social:Toggle");
|
||||
},
|
||||
|
||||
// Called once Social.jsm's provider has been set
|
||||
_providerReady: function SocialUI_providerReady() {
|
||||
// If we couldn't find a provider, nothing to do here.
|
||||
if (!Social.provider)
|
||||
return;
|
||||
|
||||
this.updateToggleCommand();
|
||||
|
||||
let toggleCommand = this.toggleCommand;
|
||||
let label = gNavigatorBundle.getFormattedString("social.enable.label",
|
||||
[Social.provider.name]);
|
||||
let accesskey = gNavigatorBundle.getString("social.enable.accesskey");
|
||||
toggleCommand.setAttribute("label", label);
|
||||
toggleCommand.setAttribute("accesskey", accesskey);
|
||||
|
||||
SocialToolbar.init();
|
||||
SocialShareButton.init();
|
||||
SocialSidebar.init();
|
||||
},
|
||||
|
||||
updateToggleCommand: function SocialUI_updateToggleCommand() {
|
||||
let toggleCommand = this.toggleCommand;
|
||||
toggleCommand.setAttribute("checked", Social.enabled);
|
||||
|
||||
// FIXME: bug 772808: menu items don't inherit the "hidden" state properly,
|
||||
// need to update them manually.
|
||||
// This should just be: toggleCommand.hidden = !Social.active;
|
||||
for (let id of ["appmenu_socialToggle", "menu_socialToggle"]) {
|
||||
let el = document.getElementById(id);
|
||||
if (!el)
|
||||
continue;
|
||||
|
||||
if (Social.active)
|
||||
el.removeAttribute("hidden");
|
||||
else
|
||||
el.setAttribute("hidden", "true");
|
||||
}
|
||||
},
|
||||
|
||||
// This handles "ActivateSocialFeature" events fired against content documents
|
||||
// in this window.
|
||||
_activationEventHandler: function SocialUI_activationHandler(e) {
|
||||
// Nothing to do if Social is already active, or we don't have a provider
|
||||
// to enable yet.
|
||||
if (Social.active || !Social.provider)
|
||||
return;
|
||||
|
||||
let targetDoc = e.target;
|
||||
|
||||
// Event must be fired against the document
|
||||
if (!(targetDoc instanceof HTMLDocument))
|
||||
return;
|
||||
|
||||
// Ignore events fired in background tabs
|
||||
if (targetDoc.defaultView.top != content)
|
||||
return;
|
||||
|
||||
// Check that the associated document's origin is in our whitelist
|
||||
let prePath = targetDoc.documentURIObject.prePath;
|
||||
let whitelist = Services.prefs.getCharPref("browser.social.whitelist");
|
||||
if (whitelist.split(",").indexOf(prePath) == -1)
|
||||
return;
|
||||
|
||||
// If the last event was received < 1s ago, ignore this one
|
||||
let now = Date.now();
|
||||
if (now - Social.lastEventReceived < 1000)
|
||||
return;
|
||||
Social.lastEventReceived = now;
|
||||
|
||||
// Enable the social functionality, and indicate that it was activated
|
||||
Social.active = true;
|
||||
|
||||
// Show a warning, allow undoing the activation
|
||||
let description = document.getElementById("social-activation-message");
|
||||
let brandShortName = document.getElementById("bundle_brand").getString("brandShortName");
|
||||
let message = gNavigatorBundle.getFormattedString("social.activated.message",
|
||||
[Social.provider.name, brandShortName]);
|
||||
description.value = message;
|
||||
|
||||
SocialUI.notificationPanel.hidden = false;
|
||||
|
||||
setTimeout(function () {
|
||||
SocialUI.notificationPanel.openPopup(SocialToolbar.button, "bottomcenter topright");
|
||||
}.bind(this), 0);
|
||||
},
|
||||
|
||||
get notificationPanel() {
|
||||
return document.getElementById("socialActivatedNotification")
|
||||
},
|
||||
|
||||
undoActivation: function SocialUI_undoActivation() {
|
||||
Social.active = false;
|
||||
this.notificationPanel.hidePopup();
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,22 +248,33 @@ var SocialToolbar = {
|
||||
// Called once, after window load, when the Social.provider object is initialized
|
||||
init: function SocialToolbar_init() {
|
||||
document.getElementById("social-provider-image").setAttribute("image", Social.provider.iconURL);
|
||||
|
||||
// handle button state
|
||||
document.getElementById("social-statusarea-popup").addEventListener("popupshowing", function(e) {
|
||||
document.getElementById("social-toolbar-button").setAttribute("open", "true");
|
||||
}, false);
|
||||
document.getElementById("social-statusarea-popup").addEventListener("popuphiding", function(e) {
|
||||
document.getElementById("social-toolbar-button").removeAttribute("open");
|
||||
}, false);
|
||||
|
||||
let removeItem = document.getElementById("social-remove-menuitem");
|
||||
let brandShortName = document.getElementById("bundle_brand").getString("brandShortName");
|
||||
let label = gNavigatorBundle.getFormattedString("social.remove.label",
|
||||
[brandShortName]);
|
||||
let accesskey = gNavigatorBundle.getString("social.remove.accesskey");
|
||||
removeItem.setAttribute("label", label);
|
||||
removeItem.setAttribute("accesskey", accesskey);
|
||||
|
||||
let statusAreaPopup = document.getElementById("social-statusarea-popup");
|
||||
statusAreaPopup.addEventListener("popupshowing", function(e) {
|
||||
this.button.setAttribute("open", "true");
|
||||
}.bind(this));
|
||||
statusAreaPopup.addEventListener("popuphidden", function(e) {
|
||||
this.button.removeAttribute("open");
|
||||
}.bind(this));
|
||||
|
||||
this.updateButton();
|
||||
this.updateProfile();
|
||||
},
|
||||
|
||||
get button() {
|
||||
return document.getElementById("social-toolbar-button");
|
||||
},
|
||||
|
||||
updateButtonHiddenState: function SocialToolbar_updateButtonHiddenState() {
|
||||
let toolbarbutton = document.getElementById("social-toolbar-button");
|
||||
toolbarbutton.hidden = !Social.uiVisible;
|
||||
this.button.hidden = !Social.uiVisible;
|
||||
},
|
||||
|
||||
updateProfile: function SocialToolbar_updateProfile() {
|
||||
@ -233,10 +339,10 @@ var SocialToolbar = {
|
||||
panel.hidden = false;
|
||||
|
||||
function sizePanelToContent() {
|
||||
// XXX Maybe we can use nsIDOMWindowUtils.getRootBounds() here?
|
||||
// XXX need to handle dynamic sizing
|
||||
// FIXME: bug 764787: Maybe we can use nsIDOMWindowUtils.getRootBounds() here?
|
||||
// Need to handle dynamic sizing
|
||||
let doc = notifBrowser.contentDocument;
|
||||
// XXX "notif" is an implementation detail that we should get rid of
|
||||
// "notif" is an implementation detail that we should get rid of
|
||||
// eventually
|
||||
let body = doc.getElementById("notif") || doc.body.firstChild;
|
||||
if (!body)
|
||||
@ -254,13 +360,13 @@ var SocialToolbar = {
|
||||
panel.addEventListener("popuphiding", function onpopuphiding() {
|
||||
panel.removeEventListener("popuphiding", onpopuphiding);
|
||||
// unload the panel
|
||||
document.getElementById("social-toolbar-button").removeAttribute("open");
|
||||
SocialToolbar.button.removeAttribute("open");
|
||||
notifBrowser.setAttribute("src", "about:blank");
|
||||
});
|
||||
|
||||
notifBrowser.setAttribute("origin", Social.provider.origin);
|
||||
notifBrowser.setAttribute("src", iconImage.getAttribute("contentPanel"));
|
||||
document.getElementById("social-toolbar-button").setAttribute("open", "true");
|
||||
this.button.setAttribute("open", "true");
|
||||
panel.openPopup(iconImage, "bottomcenter topleft", 0, 0, false, false);
|
||||
}
|
||||
}
|
||||
|
@ -182,6 +182,44 @@
|
||||
</hbox>
|
||||
</panel>
|
||||
|
||||
<panel id="socialActivatedNotification"
|
||||
type="arrow"
|
||||
hidden="true"
|
||||
consumeoutsideclicks="true"
|
||||
align="start"
|
||||
role="alert">
|
||||
<hbox flex="1">
|
||||
<image src="chrome://browser/content/social-icon.png" class="popup-notification-icon"/>
|
||||
<vbox flex="1">
|
||||
<description id="social-activation-message" class="popup-notification-description"/>
|
||||
<spacer flex="1"/>
|
||||
<hbox pack="end" align="center" class="popup-notification-button-container">
|
||||
#ifdef XP_UNIX
|
||||
<button id="social-undoactivation-button"
|
||||
label="&social.activated.button.label;"
|
||||
accesskey="&social.activated.button.accesskey;"
|
||||
onclick="SocialUI.undoActivation();"/>
|
||||
<button default="true"
|
||||
autofocus="autofocus"
|
||||
label="&social.ok.label;"
|
||||
accesskey="&social.ok.accesskey;"
|
||||
oncommand="SocialUI.notificationPanel.hidePopup();"/>
|
||||
#else
|
||||
<button default="true"
|
||||
autofocus="autofocus"
|
||||
label="&social.ok.label;"
|
||||
accesskey="&social.ok.accesskey;"
|
||||
oncommand="SocialUI.notificationPanel.hidePopup();"/>
|
||||
<button id="social-undoactivation-button"
|
||||
label="&social.activated.button.label;"
|
||||
accesskey="&social.activated.button.accesskey;"
|
||||
onclick="SocialUI.undoActivation();"/>
|
||||
#endif
|
||||
</hbox>
|
||||
</vbox>
|
||||
</hbox>
|
||||
</panel>
|
||||
|
||||
<panel id="editSharePopup"
|
||||
type="arrow"
|
||||
orient="vertical"
|
||||
@ -214,16 +252,16 @@
|
||||
class="editSharePopupBottomButton"
|
||||
default="true"
|
||||
autofocus="autofocus"
|
||||
label="&social.sharePopup.ok.label;"
|
||||
accesskey="&social.sharePopup.ok.accesskey;"
|
||||
label="&social.ok.label;"
|
||||
accesskey="&social.ok.accesskey;"
|
||||
oncommand="SocialShareButton.dismissSharePopup();"/>
|
||||
#else
|
||||
<button id="editSharePopupOkButton"
|
||||
class="editSharePopupBottomButton"
|
||||
default="true"
|
||||
autofocus="autofocus"
|
||||
label="&social.sharePopup.ok.label;"
|
||||
accesskey="&social.sharePopup.ok.accesskey;"
|
||||
label="&social.ok.label;"
|
||||
accesskey="&social.ok.accesskey;"
|
||||
oncommand="SocialShareButton.dismissSharePopup();"/>
|
||||
<button id="editSharePopupUndoButton"
|
||||
class="editSharePopupBottomButton"
|
||||
@ -638,6 +676,8 @@
|
||||
oncommand="SocialUI.showProfile(); document.getElementById('social-statusarea-popup').hidePopup();"/>
|
||||
</vbox>
|
||||
</hbox>
|
||||
<menuitem id="social-remove-menuitem"
|
||||
oncommand="Social.active = false;"/>
|
||||
<menuitem id="social-toggle-sidebar-menuitem"
|
||||
type="checkbox"
|
||||
autocheck="false"
|
||||
|
BIN
browser/base/content/social-icon.png
Normal file
BIN
browser/base/content/social-icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
@ -258,6 +258,10 @@ _BROWSER_FILES = \
|
||||
browser_bug734076.js \
|
||||
browser_social_toolbar.js \
|
||||
browser_social_sidebar.js \
|
||||
browser_social_mozSocial_API.js \
|
||||
social_panel.html \
|
||||
social_sidebar.html \
|
||||
social_worker.js \
|
||||
$(NULL)
|
||||
|
||||
ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
|
87
browser/base/content/test/browser_social_mozSocial_API.js
Normal file
87
browser/base/content/test/browser_social_mozSocial_API.js
Normal file
@ -0,0 +1,87 @@
|
||||
/* 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/. */
|
||||
|
||||
let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
|
||||
|
||||
function test() {
|
||||
// XXX Bug 775779
|
||||
if (Cc["@mozilla.org/xpcom/debug;1"].getService(Ci.nsIDebug2).isDebugBuild) {
|
||||
ok(true, "can't run social sidebar test in debug builds because they falsely report leaks");
|
||||
return;
|
||||
}
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
let manifest = { // normal provider
|
||||
name: "provider 1",
|
||||
origin: "http://example.com",
|
||||
sidebarURL: "http://example.com/browser/browser/base/content/test/social_sidebar.html",
|
||||
workerURL: "http://example.com/browser/browser/base/content/test/social_worker.js",
|
||||
iconURL: "chrome://branding/content/icon48.png"
|
||||
};
|
||||
runSocialTestWithProvider(manifest, doTest);
|
||||
}
|
||||
|
||||
function doTest() {
|
||||
let iconsReady = false;
|
||||
let gotSidebarMessage = false;
|
||||
|
||||
function checkNext() {
|
||||
if (iconsReady && gotSidebarMessage)
|
||||
triggerIconPanel();
|
||||
}
|
||||
|
||||
function triggerIconPanel() {
|
||||
let statusIcons = document.getElementById("social-status-iconbox");
|
||||
ok(!statusIcons.firstChild.collapsed, "status icon is visible");
|
||||
// Click the button to trigger its contentPanel
|
||||
let panel = document.getElementById("social-notification-panel");
|
||||
EventUtils.synthesizeMouseAtCenter(statusIcons.firstChild, {});
|
||||
}
|
||||
|
||||
let port = Social.provider.port;
|
||||
ok(port, "provider has a port");
|
||||
port.postMessage({topic: "test-init"});
|
||||
Social.provider.port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "got-panel-message":
|
||||
ok(true, "got panel message");
|
||||
// Wait for the panel to close before ending the test
|
||||
let panel = document.getElementById("social-notification-panel");
|
||||
panel.addEventListener("popuphidden", function hiddenListener() {
|
||||
panel.removeEventListener("popuphidden", hiddenListener);
|
||||
SocialService.removeProvider(Social.provider.origin, finish);
|
||||
});
|
||||
panel.hidePopup();
|
||||
break;
|
||||
case "got-sidebar-message":
|
||||
// The sidebar message will always come first, since it loads by default
|
||||
ok(true, "got sidebar message");
|
||||
info(topic);
|
||||
gotSidebarMessage = true;
|
||||
checkNext();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Our worker sets up ambient notification at the same time as it responds to
|
||||
// the workerAPI initialization. If it's already initialized, we can
|
||||
// immediately check the icons, otherwise wait for initialization by
|
||||
// observing the topic sent out by the social service.
|
||||
if (Social.provider.workerAPI.initialized) {
|
||||
iconsReady = true;
|
||||
checkNext();
|
||||
} else {
|
||||
Services.obs.addObserver(function obs() {
|
||||
Services.obs.removeObserver(obs, "social:ambient-notification-changed");
|
||||
// Let the other observers (like the one that updates the UI) run before
|
||||
// checking the icons.
|
||||
executeSoon(function () {
|
||||
iconsReady = true;
|
||||
checkNext();
|
||||
});
|
||||
}, "social:ambient-notification-changed", false);
|
||||
}
|
||||
}
|
14
browser/base/content/test/social_panel.html
Normal file
14
browser/base/content/test/social_panel.html
Normal file
@ -0,0 +1,14 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
function pingWorker() {
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "panel-message", result: "ok"});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="pingWorker();">
|
||||
<p>This is a test social panel.</p>
|
||||
</body>
|
||||
</html>
|
14
browser/base/content/test/social_sidebar.html
Normal file
14
browser/base/content/test/social_sidebar.html
Normal file
@ -0,0 +1,14 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
function pingWorker() {
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "sidebar-message", result: "ok"});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="pingWorker();">
|
||||
<p>This is a test social sidebar.</p>
|
||||
</body>
|
||||
</html>
|
40
browser/base/content/test/social_worker.js
Normal file
40
browser/base/content/test/social_worker.js
Normal file
@ -0,0 +1,40 @@
|
||||
/* 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/. */
|
||||
|
||||
let testPort;
|
||||
|
||||
onconnect = function(e) {
|
||||
let port = e.ports[0];
|
||||
port.onmessage = function onMessage(event) {
|
||||
let topic = event.data.topic;
|
||||
switch (topic) {
|
||||
case "test-init":
|
||||
testPort = port;
|
||||
break;
|
||||
case "sidebar-message":
|
||||
if (testPort && event.data.result == "ok")
|
||||
testPort.postMessage({topic:"got-sidebar-message"});
|
||||
break;
|
||||
case "panel-message":
|
||||
if (testPort && event.data.result == "ok")
|
||||
testPort.postMessage({topic:"got-panel-message"});
|
||||
break;
|
||||
case "social.initialize":
|
||||
// This is the workerAPI port, respond and set up a notification icon.
|
||||
port.postMessage({topic: "social.initialize-response"});
|
||||
let profile = {
|
||||
userName: "foo"
|
||||
};
|
||||
port.postMessage({topic: "social.user-profile", data: profile});
|
||||
let icon = {
|
||||
name: "testIcon",
|
||||
iconURL: "chrome://branding/content/icon48.png",
|
||||
contentPanel: "http://example.com/browser/browser/base/content/test/social_panel.html",
|
||||
counter: 1
|
||||
};
|
||||
port.postMessage({topic: "social.ambient-notification", data: icon});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -101,6 +101,7 @@ browser.jar:
|
||||
#ifdef XP_WIN
|
||||
* content/browser/win6BrowserOverlay.xul (content/win6BrowserOverlay.xul)
|
||||
#endif
|
||||
content/browser/social-icon.png (content/social-icon.png)
|
||||
# the following files are browser-specific overrides
|
||||
* content/browser/license.html (/toolkit/content/license.html)
|
||||
% override chrome://global/content/license.html chrome://browser/content/license.html
|
||||
|
@ -68,7 +68,7 @@ PlacesViewBase.prototype = {
|
||||
if (val) {
|
||||
this._resultNode = val.root;
|
||||
this._rootElt._placesNode = this._resultNode;
|
||||
this._domNodes = new WeakMap();
|
||||
this._domNodes = new Map();
|
||||
this._domNodes.set(this._resultNode, this._rootElt);
|
||||
|
||||
// This calls _rebuild through invalidateContainer.
|
||||
|
@ -80,7 +80,7 @@ function PlacesController(aView) {
|
||||
return Services.dirsvc.get("ProfD", Ci.nsIFile).leafName;
|
||||
});
|
||||
|
||||
this._cachedLivemarkInfoObjects = new WeakMap();
|
||||
this._cachedLivemarkInfoObjects = new Map();
|
||||
}
|
||||
|
||||
PlacesController.prototype = {
|
||||
|
@ -51,7 +51,7 @@ PlacesTreeView.prototype = {
|
||||
// Bug 761494:
|
||||
// ----------
|
||||
// Some addons use methods from nsINavHistoryResultObserver and
|
||||
// nsINavHistoryResultTreeViewer, without QIing to these intefaces first.
|
||||
// nsINavHistoryResultTreeViewer, without QIing to these interfaces first.
|
||||
// That's not a problem when the view is retrieved through the
|
||||
// <tree>.view getter (which returns the wrappedJSObject of this object),
|
||||
// it raises an issue when the view retrieved through the treeBoxObject.view
|
||||
@ -153,12 +153,21 @@ PlacesTreeView.prototype = {
|
||||
_getRowForNode:
|
||||
function PTV__getRowForNode(aNode, aForceBuild, aParentRow, aNodeIndex) {
|
||||
if (aNode == this._rootNode)
|
||||
throw "The root node is never visible";
|
||||
throw new Error("The root node is never visible");
|
||||
|
||||
let ancestors = PlacesUtils.nodeAncestors(aNode);
|
||||
for (let ancestor in ancestors) {
|
||||
// A node is removed form the view either if it has no parent or if its
|
||||
// root-ancestor is not the root node (in which case that's the node
|
||||
// for which nodeRemoved was called).
|
||||
let ancestors = [x for each (x in PlacesUtils.nodeAncestors(aNode))];
|
||||
if (ancestors.length == 0 ||
|
||||
ancestors[ancestors.length - 1] != this._rootNode) {
|
||||
throw new Error("Removed node passed to _getRowForNode");
|
||||
}
|
||||
|
||||
// Ensure that the entire chain is open, otherwise that node is invisible.
|
||||
for (let ancestor of ancestors) {
|
||||
if (!ancestor.containerOpen)
|
||||
throw "Invisible node passed to _getRowForNode";
|
||||
throw new Error("Invisible node passed to _getRowForNode");
|
||||
}
|
||||
|
||||
// Non-plain containers are initially built with their contents.
|
||||
@ -1097,7 +1106,7 @@ PlacesTreeView.prototype = {
|
||||
if (val) {
|
||||
this._result = val;
|
||||
this._rootNode = this._result.root;
|
||||
this._cellProperties = new WeakMap();
|
||||
this._cellProperties = new Map();
|
||||
this._cuttingNodes = new Set();
|
||||
}
|
||||
else if (this._result) {
|
||||
|
@ -657,11 +657,21 @@ toolbar button -->
|
||||
<!ENTITY socialToolbar.title "Social Toolbar Button">
|
||||
<!ENTITY social.notLoggedIn.label "Not logged in">
|
||||
|
||||
<!-- LOCALIZATION NOTE (social.ok.label, social.ok.accesskey): this string is
|
||||
used for the "OK" button for two different social panels. One appears when
|
||||
the feature is activated (social.activated.* below), and the other when
|
||||
the user clicks the "Share" button a second time (social.sharePopup.*
|
||||
below). -->
|
||||
<!ENTITY social.ok.label "OK">
|
||||
<!ENTITY social.ok.accesskey "O">
|
||||
|
||||
<!ENTITY social.sharePopup.undo.label "Unshare">
|
||||
<!ENTITY social.sharePopup.undo.accesskey "U">
|
||||
<!ENTITY social.sharePopup.ok.label "OK">
|
||||
<!ENTITY social.sharePopup.ok.accesskey "O">
|
||||
<!ENTITY social.sharePopup.shared.label "You shared this page.">
|
||||
<!ENTITY social.sharePopup.portrait.arialabel "User profile picture">
|
||||
|
||||
<!ENTITY social.toggleSidebar.label "Show sidebar">
|
||||
<!ENTITY social.toggleSidebar.accesskey "s">
|
||||
|
||||
<!ENTITY social.activated.button.label "Oops, undo">
|
||||
<!ENTITY social.activated.button.accesskey "u">
|
||||
|
@ -372,3 +372,14 @@ fullscreen.rememberDecision=Remember decision for %S
|
||||
social.shareButton.tooltip=Share this
|
||||
social.shareButton.sharedtooltip=You shared this
|
||||
social.pageShared.label=Page shared
|
||||
|
||||
# LOCALIZATION NOTE (social.enable.label): %S = Social networking provider
|
||||
social.enable.label=%S integration
|
||||
social.enable.accesskey=n
|
||||
|
||||
# LOCALIZATION NOTE (social.remove.label): %S = brandShortName
|
||||
social.remove.label=Remove from %S
|
||||
social.remove.accesskey=R
|
||||
|
||||
# LOCALIZATION NOTE (social.enabled.message): %1$S is the name of the social provider, %2$S is brandShortName (e.g. Firefox)
|
||||
social.activated.message=%1$S integration with %2$S has been activated.
|
||||
|
@ -17,6 +17,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "SocialService",
|
||||
"resource://gre/modules/SocialService.jsm");
|
||||
|
||||
let Social = {
|
||||
lastEventReceived: 0,
|
||||
provider: null,
|
||||
init: function Social_init(callback) {
|
||||
if (this.provider) {
|
||||
@ -38,6 +39,25 @@ let Social = {
|
||||
return this.provider && this.provider.enabled && this.provider.port;
|
||||
},
|
||||
|
||||
set enabled(val) {
|
||||
SocialService.enabled = val;
|
||||
},
|
||||
get enabled() {
|
||||
return SocialService.enabled;
|
||||
},
|
||||
|
||||
get active() {
|
||||
return Services.prefs.getBoolPref("social.active");
|
||||
},
|
||||
set active(val) {
|
||||
Services.prefs.setBoolPref("social.active", !!val);
|
||||
this.enabled = !!val;
|
||||
},
|
||||
|
||||
toggle: function Social_toggle() {
|
||||
this.enabled = !this.enabled;
|
||||
},
|
||||
|
||||
toggleSidebar: function SocialSidebar_toggle() {
|
||||
let prefValue = Services.prefs.getBoolPref("social.sidebar.open");
|
||||
Services.prefs.setBoolPref("social.sidebar.open", !prefValue);
|
||||
|
@ -6,4 +6,6 @@ setup.py:testing/mozbase/mozlog:develop
|
||||
setup.py:testing/mozbase/mozprocess:develop
|
||||
setup.py:testing/mozbase/mozprofile:develop
|
||||
setup.py:testing/mozbase/mozrunner:develop
|
||||
setup.py:build/pylib/blessings:develop
|
||||
setup.py:python/blessings:develop
|
||||
mozilla.pth:build
|
||||
mozilla.pth:config
|
||||
|
@ -5,9 +5,11 @@
|
||||
# This file contains code for populating the virtualenv environment for
|
||||
# Mozilla's build system. It is typically called as part of configure.
|
||||
|
||||
from __future__ import with_statement
|
||||
import os.path
|
||||
import subprocess
|
||||
import sys
|
||||
import distutils.sysconfig
|
||||
|
||||
def populate_virtualenv(top_source_directory, manifest_filename):
|
||||
"""Populate the virtualenv from the contents of a manifest.
|
||||
@ -38,6 +40,11 @@ def populate_virtualenv(top_source_directory, manifest_filename):
|
||||
|
||||
call_setup(os.path.join(top_source_directory, package[1]),
|
||||
package[2:])
|
||||
if package[0].endswith('.pth'):
|
||||
assert len(package) == 2
|
||||
|
||||
with open(os.path.join(distutils.sysconfig.get_python_lib(), package[0]), 'a') as f:
|
||||
f.write("%s\n" % os.path.join(top_source_directory, package[1]))
|
||||
|
||||
def call_setup(directory, arguments):
|
||||
"""Calls setup.py in a directory."""
|
||||
|
@ -161,6 +161,7 @@ PYUNITS := \
|
||||
unit-buildlist.py \
|
||||
unit-expandlibs.py \
|
||||
unit-writemozinfo.py \
|
||||
unit-mozunit.py \
|
||||
$(NULL)
|
||||
|
||||
check-preqs = \
|
||||
|
@ -126,11 +126,13 @@ class Preprocessor:
|
||||
'file': self.context['FILE'],
|
||||
'le': self.LE})
|
||||
self.writtenLines = ln
|
||||
aLine = self.applyFilters(aLine)
|
||||
filteredLine = self.applyFilters(aLine)
|
||||
if filteredLine != aLine:
|
||||
self.actionLevel = 2
|
||||
# ensure our line ending. Only need to handle \n, as we're reading
|
||||
# with universal line ending support, at least for files.
|
||||
aLine = re.sub('\n', self.LE, aLine)
|
||||
self.out.write(aLine)
|
||||
filteredLine = re.sub('\n', self.LE, filteredLine)
|
||||
self.out.write(filteredLine)
|
||||
|
||||
def handleCommandLine(self, args, defaultToStdin = False):
|
||||
"""
|
||||
|
@ -3,7 +3,10 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
from unittest import TextTestRunner as _TestRunner, TestResult as _TestResult
|
||||
import unittest
|
||||
import inspect
|
||||
from StringIO import StringIO
|
||||
import os
|
||||
|
||||
'''Helper to make python unit tests report the way that the Mozilla
|
||||
unit test infrastructure expects tests to report.
|
||||
@ -11,10 +14,10 @@ unit test infrastructure expects tests to report.
|
||||
Usage:
|
||||
|
||||
import unittest
|
||||
from mozunit import MozTestRunner
|
||||
import mozunit
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(testRunner=MozTestRunner())
|
||||
mozunit.main()
|
||||
'''
|
||||
|
||||
class _MozTestResult(_TestResult):
|
||||
@ -68,3 +71,69 @@ class MozTestRunner(_TestRunner):
|
||||
test(result)
|
||||
result.printErrorList()
|
||||
return result
|
||||
|
||||
class MockedFile(StringIO):
|
||||
def __init__(self, context, filename, content = ''):
|
||||
self.context = context
|
||||
self.name = filename
|
||||
StringIO.__init__(self, content)
|
||||
|
||||
def close(self):
|
||||
self.context.files[self.name] = self.getvalue()
|
||||
StringIO.close(self)
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
self.close()
|
||||
|
||||
class MockedOpen(object):
|
||||
'''
|
||||
Context manager diverting the open builtin such that opening files
|
||||
can open "virtual" file instances given when creating a MockedOpen.
|
||||
|
||||
with MockedOpen({'foo': 'foo', 'bar': 'bar'}):
|
||||
f = open('foo', 'r')
|
||||
|
||||
will thus open the virtual file instance for the file 'foo' to f.
|
||||
|
||||
MockedOpen also masks writes, so that creating or replacing files
|
||||
doesn't touch the file system, while subsequently opening the file
|
||||
will return the recorded content.
|
||||
|
||||
with MockedOpen():
|
||||
f = open('foo', 'w')
|
||||
f.write('foo')
|
||||
self.assertRaises(Exception,f.open('foo', 'r'))
|
||||
'''
|
||||
def __init__(self, files = {}):
|
||||
self.files = {}
|
||||
for name, content in files.iteritems():
|
||||
self.files[os.path.abspath(name)] = content
|
||||
|
||||
def __call__(self, name, mode = 'r'):
|
||||
absname = os.path.abspath(name)
|
||||
if 'w' in mode:
|
||||
file = MockedFile(self, absname)
|
||||
elif absname in self.files:
|
||||
file = MockedFile(self, absname, self.files[absname])
|
||||
elif 'a' in mode:
|
||||
file = MockedFile(self, absname, self.open(name, 'r').read())
|
||||
else:
|
||||
file = self.open(name, mode)
|
||||
if 'a' in mode:
|
||||
file.seek(0, os.SEEK_END)
|
||||
return file
|
||||
|
||||
def __enter__(self):
|
||||
import __builtin__
|
||||
self.open = __builtin__.open
|
||||
__builtin__.open = self
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
import __builtin__
|
||||
__builtin__.open = self.open
|
||||
|
||||
def main(*args):
|
||||
unittest.main(testRunner=MozTestRunner(),*args)
|
||||
|
@ -291,11 +291,9 @@ endif
|
||||
ifndef MOZ_AUTO_DEPS
|
||||
ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS))
|
||||
MDDEPFILES = $(addprefix $(MDDEPDIR)/,$(OBJS:=.pp))
|
||||
ifndef NO_GEN_XPT
|
||||
MDDEPFILES += $(addprefix $(MDDEPDIR)/,$(XPIDLSRCS:.idl=.h.pp) $(XPIDLSRCS:.idl=.xpt.pp))
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ALL_TRASH = \
|
||||
$(GARBAGE) $(TARGETS) $(OBJS) $(PROGOBJS) LOGS TAGS a.out \
|
||||
@ -1298,7 +1296,6 @@ $(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(xpidl-preqs)
|
||||
@if test -n "$(findstring $*.h, $(EXPORTS))"; \
|
||||
then echo "*** WARNING: file $*.h generated from $*.idl overrides $(srcdir)/$*.h"; else true; fi
|
||||
|
||||
ifndef NO_GEN_XPT
|
||||
# generate intermediate .xpt files into $(XPIDL_GEN_DIR), then link
|
||||
# into $(XPIDL_MODULE).xpt and export it to $(FINAL_TARGET)/components.
|
||||
$(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_DEPS) $(xpidl-preqs)
|
||||
@ -1323,8 +1320,6 @@ ifndef NO_INTERFACES_MANIFEST
|
||||
endif
|
||||
endif
|
||||
|
||||
endif # NO_GEN_XPT
|
||||
|
||||
GARBAGE_DIRS += $(XPIDL_GEN_DIR)
|
||||
|
||||
endif #} XPIDLSRCS
|
||||
|
@ -2,7 +2,7 @@ import unittest
|
||||
|
||||
import sys
|
||||
import os.path
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
|
||||
import mozunit
|
||||
|
||||
from Expression import Expression, Context
|
||||
|
||||
@ -60,4 +60,4 @@ class TestExpression(unittest.TestCase):
|
||||
self.assert_(Expression('FAIL != 1').evaluate(self.c))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
mozunit.main()
|
||||
|
@ -5,9 +5,7 @@ from filecmp import dircmp
|
||||
from tempfile import mkdtemp
|
||||
from shutil import rmtree, copy2
|
||||
from zipfile import ZipFile
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
|
||||
|
||||
from mozunit import MozTestRunner
|
||||
import mozunit
|
||||
from JarMaker import JarMaker
|
||||
|
||||
if sys.platform == "win32":
|
||||
@ -280,4 +278,4 @@ class TestJarMaker(unittest.TestCase):
|
||||
self.assertTrue(not difference, difference)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(testRunner=MozTestRunner())
|
||||
mozunit.main()
|
||||
|
@ -4,7 +4,7 @@ from StringIO import StringIO
|
||||
import os
|
||||
import sys
|
||||
import os.path
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
|
||||
import mozunit
|
||||
|
||||
from Preprocessor import Preprocessor
|
||||
|
||||
@ -43,4 +43,4 @@ class TestLineEndings(unittest.TestCase):
|
||||
self.assertEquals(self.pp.out.getvalue(), 'a\nb\nc\n')
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
mozunit.main()
|
||||
|
@ -5,41 +5,14 @@ from StringIO import StringIO
|
||||
import os
|
||||
import sys
|
||||
import os.path
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
|
||||
from mozunit import main, MockedOpen
|
||||
|
||||
from Preprocessor import Preprocessor
|
||||
|
||||
class NamedIO(StringIO):
|
||||
def __init__(self, name, content):
|
||||
self.name = name
|
||||
StringIO.__init__(self, content)
|
||||
|
||||
class MockedOpen(object):
|
||||
"""
|
||||
Context manager diverting the open builtin such that opening files
|
||||
can open NamedIO instances given when creating a MockedOpen.
|
||||
|
||||
with MockedOpen(NamedIO('foo', 'foo'), NamedIO('bar', 'bar')):
|
||||
f = open('foo', 'r')
|
||||
|
||||
will thus assign the NamedIO instance for the file 'foo' to f.
|
||||
"""
|
||||
def __init__(self, *files):
|
||||
self.files = {}
|
||||
for f in files:
|
||||
self.files[os.path.abspath(f.name)] = f
|
||||
def __call__(self, name, args):
|
||||
absname = os.path.abspath(name)
|
||||
if absname in self.files:
|
||||
return self.files[absname]
|
||||
return self.open(name, args)
|
||||
def __enter__(self):
|
||||
import __builtin__
|
||||
self.open = __builtin__.open
|
||||
__builtin__.open = self
|
||||
def __exit__(self, type, value, traceback):
|
||||
import __builtin__
|
||||
__builtin__.open = self.open
|
||||
def NamedIO(name, content):
|
||||
with open(name, 'w') as f:
|
||||
f.write(content)
|
||||
return name
|
||||
|
||||
class TestPreprocessor(unittest.TestCase):
|
||||
"""
|
||||
@ -539,13 +512,13 @@ octal value is not equal
|
||||
self.fail("Expected a Preprocessor.Error")
|
||||
|
||||
def test_include(self):
|
||||
with MockedOpen(NamedIO("foo/test", """#define foo foobarbaz
|
||||
with MockedOpen({"foo/test": """#define foo foobarbaz
|
||||
#include @inc@
|
||||
@bar@
|
||||
"""),
|
||||
NamedIO("bar", """#define bar barfoobaz
|
||||
""",
|
||||
"bar": """#define bar barfoobaz
|
||||
@foo@
|
||||
""")):
|
||||
"""}):
|
||||
f = NamedIO("include.in", """#filter substitution
|
||||
#define inc ../bar
|
||||
#include foo/test""")
|
||||
@ -575,7 +548,7 @@ barfoobaz
|
||||
self.fail("Expected a Preprocessor.Error")
|
||||
|
||||
def test_include_literal_at(self):
|
||||
with MockedOpen(NamedIO("@foo@", "#define foo foobarbaz")):
|
||||
with MockedOpen({"@foo@": "#define foo foobarbaz"}):
|
||||
f = NamedIO("include_literal_at.in", """#include @foo@
|
||||
#filter substitution
|
||||
@foo@
|
||||
@ -585,11 +558,11 @@ barfoobaz
|
||||
""")
|
||||
|
||||
def test_command_line_literal_at(self):
|
||||
with MockedOpen(NamedIO("@foo@.in", """@foo@
|
||||
""")):
|
||||
with MockedOpen({"@foo@.in": """@foo@
|
||||
"""}):
|
||||
self.pp.handleCommandLine(['-Fsubstitution', '-Dfoo=foobarbaz', '@foo@.in'])
|
||||
self.assertEqual(self.pp.out.getvalue(), """foobarbaz
|
||||
""")
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
main()
|
||||
|
@ -3,7 +3,7 @@ import unittest
|
||||
import os, sys, os.path, time
|
||||
from tempfile import mkdtemp
|
||||
from shutil import rmtree
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
|
||||
import mozunit
|
||||
|
||||
from buildlist import addEntriesToListFile
|
||||
|
||||
@ -77,4 +77,4 @@ class TestBuildList(unittest.TestCase):
|
||||
self.assertFileContains(testfile, ["a","b","c"])
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
mozunit.main()
|
||||
|
@ -6,8 +6,7 @@ import os
|
||||
import imp
|
||||
from tempfile import mkdtemp
|
||||
from shutil import rmtree
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
|
||||
from mozunit import MozTestRunner
|
||||
import mozunit
|
||||
|
||||
from UserString import UserString
|
||||
# Create a controlled configuration for use by expandlibs
|
||||
@ -385,4 +384,4 @@ class TestSymbolOrder(unittest.TestCase):
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(testRunner=MozTestRunner())
|
||||
mozunit.main()
|
||||
|
75
config/tests/unit-mozunit.py
Normal file
75
config/tests/unit-mozunit.py
Normal file
@ -0,0 +1,75 @@
|
||||
# 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/.
|
||||
|
||||
from __future__ import with_statement
|
||||
import sys
|
||||
import os
|
||||
from mozunit import main, MockedOpen
|
||||
import unittest
|
||||
from tempfile import mkstemp
|
||||
|
||||
class TestMozUnit(unittest.TestCase):
|
||||
def test_mocked_open(self):
|
||||
# Create a temporary file on the file system.
|
||||
(fd, path) = mkstemp()
|
||||
with os.fdopen(fd, 'w') as file:
|
||||
file.write('foobar');
|
||||
|
||||
with MockedOpen({'file1': 'content1',
|
||||
'file2': 'content2'}):
|
||||
# Check the contents of the files given at MockedOpen creation.
|
||||
self.assertEqual(open('file1', 'r').read(), 'content1')
|
||||
self.assertEqual(open('file2', 'r').read(), 'content2')
|
||||
|
||||
# Check that overwriting these files alters their content.
|
||||
with open('file1', 'w') as file:
|
||||
file.write('foo')
|
||||
self.assertEqual(open('file1', 'r').read(), 'foo')
|
||||
|
||||
# ... but not until the file is closed.
|
||||
file = open('file2', 'w')
|
||||
file.write('bar')
|
||||
self.assertEqual(open('file2', 'r').read(), 'content2')
|
||||
file.close()
|
||||
self.assertEqual(open('file2', 'r').read(), 'bar')
|
||||
|
||||
# Check that appending to a file does append
|
||||
with open('file1', 'a') as file:
|
||||
file.write('bar')
|
||||
self.assertEqual(open('file1', 'r').read(), 'foobar')
|
||||
|
||||
# Opening a non-existing file ought to fail.
|
||||
self.assertRaises(IOError, open, 'file3', 'r')
|
||||
|
||||
# Check that writing a new file does create the file.
|
||||
with open('file3', 'w') as file:
|
||||
file.write('baz')
|
||||
self.assertEqual(open('file3', 'r').read(), 'baz')
|
||||
|
||||
# Check the content of the file created outside MockedOpen.
|
||||
self.assertEqual(open(path, 'r').read(), 'foobar')
|
||||
|
||||
# Check that overwriting a file existing on the file system
|
||||
# does modify its content.
|
||||
with open(path, 'w') as file:
|
||||
file.write('bazqux')
|
||||
self.assertEqual(open(path, 'r').read(), 'bazqux')
|
||||
|
||||
with MockedOpen():
|
||||
# Check that appending to a file existing on the file system
|
||||
# does modify its content.
|
||||
with open(path, 'a') as file:
|
||||
file.write('bazqux')
|
||||
self.assertEqual(open(path, 'r').read(), 'foobarbazqux')
|
||||
|
||||
# Check that the file was not actually modified on the file system.
|
||||
self.assertEqual(open(path, 'r').read(), 'foobar')
|
||||
os.remove(path)
|
||||
|
||||
# Check that the file created inside MockedOpen wasn't actually
|
||||
# created.
|
||||
self.assertRaises(IOError, open, 'file3', 'r')
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -3,7 +3,7 @@ import unittest
|
||||
import os, sys, os.path, time
|
||||
from tempfile import mkdtemp
|
||||
from shutil import rmtree
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
|
||||
import mozunit
|
||||
from mozprocess import processhandler
|
||||
|
||||
from nsinstall import nsinstall
|
||||
@ -170,4 +170,4 @@ class TestNsinstall(unittest.TestCase):
|
||||
#TODO: implement -R, -l, -L and test them!
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
mozunit.main()
|
||||
|
@ -2,7 +2,7 @@ import unittest
|
||||
|
||||
import sys
|
||||
import os.path
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
|
||||
import mozunit
|
||||
|
||||
from printprereleasesuffix import get_prerelease_suffix
|
||||
|
||||
@ -77,4 +77,4 @@ class TestGetPreReleaseSuffix(unittest.TestCase):
|
||||
self.assertEqual(self.c, '')
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
mozunit.main()
|
||||
|
@ -3,8 +3,7 @@ from __future__ import with_statement
|
||||
import unittest
|
||||
import os, sys, time, tempfile
|
||||
from StringIO import StringIO
|
||||
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
|
||||
import mozunit
|
||||
|
||||
from writemozinfo import build_dict, write_json, JsonValue, jsonify
|
||||
|
||||
@ -239,5 +238,4 @@ class TestWriteJson(unittest.TestCase):
|
||||
self.assertEqual(32, d['bits'])
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
mozunit.main()
|
||||
|
16
configure.in
16
configure.in
@ -363,6 +363,10 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -n "$MOZ_WINCONSOLE"; then
|
||||
AC_DEFINE(MOZ_WINCONSOLE)
|
||||
fi
|
||||
|
||||
MOZ_TOOL_VARIABLES
|
||||
|
||||
dnl ========================================================
|
||||
@ -746,6 +750,9 @@ if test -n "$_WIN32_MSVC"; then
|
||||
AC_DEFINE(HAVE_IO_H)
|
||||
AC_DEFINE(HAVE_SETBUF)
|
||||
AC_DEFINE(HAVE_ISATTY)
|
||||
if test $_MSC_VER -ge 1600; then
|
||||
AC_DEFINE(HAVE_NULLPTR)
|
||||
fi
|
||||
fi
|
||||
|
||||
fi # COMPILE_ENVIRONMENT
|
||||
@ -4206,6 +4213,7 @@ MOZ_ANDROID_HISTORY=
|
||||
MOZ_WEBSMS_BACKEND=
|
||||
MOZ_GRAPHITE=1
|
||||
ACCESSIBILITY=1
|
||||
MOZ_SYS_MSG=
|
||||
|
||||
case "$target_os" in
|
||||
mingw*)
|
||||
@ -7313,7 +7321,7 @@ MOZ_ARG_ENABLE_BOOL(b2g-ril,
|
||||
MOZ_B2G_RIL=1,
|
||||
MOZ_B2G_RIL= )
|
||||
if test -n "$MOZ_B2G_RIL"; then
|
||||
AC_DEFINE(MOZ_B2G_RIL)
|
||||
AC_DEFINE(MOZ_B2G_RIL)
|
||||
fi
|
||||
AC_SUBST(MOZ_B2G_RIL)
|
||||
|
||||
@ -7325,14 +7333,16 @@ MOZ_ARG_ENABLE_BOOL(b2g-bt,
|
||||
MOZ_B2G_BT=1,
|
||||
MOZ_B2G_BT= )
|
||||
if test -n "$MOZ_B2G_BT"; then
|
||||
AC_DEFINE(MOZ_B2G_BT)
|
||||
AC_DEFINE(MOZ_B2G_BT)
|
||||
fi
|
||||
AC_SUBST(MOZ_B2G_BT)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Enable Support for System Messages API
|
||||
dnl ========================================================
|
||||
|
||||
if test -n "$MOZ_SYS_MSG"; then
|
||||
AC_DEFINE(MOZ_SYS_MSG)
|
||||
fi
|
||||
AC_SUBST(MOZ_SYS_MSG)
|
||||
|
||||
dnl ========================================================
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "nsChangeHint.h"
|
||||
#include "nsINode.h"
|
||||
#include "nsIDocument.h" // for IsInHTMLDocument
|
||||
#include "nsCSSProperty.h"
|
||||
|
||||
// Forward declarations
|
||||
class nsIAtom;
|
||||
|
@ -1291,6 +1291,8 @@ private:
|
||||
NodeMayHaveDOMMutationObserver,
|
||||
// Set if node is Content
|
||||
NodeIsContent,
|
||||
// Set if the node has animations or transitions
|
||||
ElementHasAnimations,
|
||||
// Guard value
|
||||
BooleanFlagCount
|
||||
};
|
||||
@ -1356,6 +1358,8 @@ public:
|
||||
bool HasPointerLock() const { return GetBoolFlag(ElementHasPointerLock); }
|
||||
void SetPointerLock() { SetBoolFlag(ElementHasPointerLock); }
|
||||
void ClearPointerLock() { ClearBoolFlag(ElementHasPointerLock); }
|
||||
bool MayHaveAnimations() { return GetBoolFlag(ElementHasAnimations); }
|
||||
void SetMayHaveAnimations() { SetBoolFlag(ElementHasAnimations); }
|
||||
protected:
|
||||
void SetParentIsContent(bool aValue) { SetBoolFlag(ParentIsContent, aValue); }
|
||||
void SetInDocument() { SetBoolFlag(IsInDocument); }
|
||||
|
@ -178,8 +178,6 @@ MOCHITEST_FILES_A = \
|
||||
file_bug426646-1.html \
|
||||
file_bug426646-2.html \
|
||||
test_bug429157.html \
|
||||
test_header.html \
|
||||
header.sjs \
|
||||
test_XHR.html \
|
||||
file_XHR_pass1.xml \
|
||||
file_XHR_pass2.txt \
|
||||
|
@ -1,8 +0,0 @@
|
||||
function handleRequest(request, response) {
|
||||
response.setHeader("Content-Type", "text/plain", false);
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
|
||||
var value = request.hasHeader("SomeHeader") ? request.getHeader("SomeHeader")
|
||||
: "";
|
||||
response.write("SomeHeader: " + value);
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for XHR header preservation</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
/** Test for Bug 421622 **/
|
||||
const SJS_URL = "http://mochi.test:8888/tests/content/base/test/header.sjs";
|
||||
const VALUE = "http://www.mozilla.org/";
|
||||
|
||||
var req = new XMLHttpRequest();
|
||||
req.open("GET", SJS_URL, false);
|
||||
req.setRequestHeader("SomeHeader", VALUE);
|
||||
req.send(null);
|
||||
|
||||
is(req.responseText,
|
||||
"SomeHeader: " + VALUE,
|
||||
"Header received by server does not match what was set");
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -26,6 +26,11 @@ public:
|
||||
Init(aX1, aY1, aX2, aY2);
|
||||
}
|
||||
|
||||
double X1() const { return mX1; }
|
||||
double Y1() const { return mY1; }
|
||||
double X2() const { return mX2; }
|
||||
double Y2() const { return mY2; }
|
||||
|
||||
void Init(double aX1, double aY1,
|
||||
double aX2, double aY2);
|
||||
|
||||
|
@ -4901,6 +4901,13 @@ nsDocShell::SetParentNativeWindow(nativeWindow parentNativeWindow)
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::GetNativeHandle(nsAString& aNativeHandle)
|
||||
{
|
||||
// the nativeHandle should be accessed from nsIXULWindow
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::GetVisibility(bool * aVisibility)
|
||||
{
|
||||
|
@ -228,8 +228,8 @@ let AlarmService = {
|
||||
|
||||
if (this._currentAlarm) {
|
||||
debug("Fire system intent: " + JSON.stringify(this._currentAlarm));
|
||||
if (this._currentAlarm.manifestURL)
|
||||
messenger.sendMessage("alarm", this._currentAlarm, this._currentAlarm.manifestURL);
|
||||
let manifestURI = Services.io.newURI(this._currentAlarm.manifestURL, null, null);
|
||||
messenger.sendMessage("alarm", this._currentAlarm, manifestURI);
|
||||
this._currentAlarm = null;
|
||||
}
|
||||
|
||||
@ -244,8 +244,8 @@ let AlarmService = {
|
||||
// fire system intent for it instead of setting it
|
||||
if (nextAlarmTime <= nowTime) {
|
||||
debug("Fire system intent: " + JSON.stringify(nextAlarm));
|
||||
if (nextAlarm.manifestURL)
|
||||
messenger.sendMessage("alarm", nextAlarm, nextAlarm.manifestURL);
|
||||
let manifestURI = Services.io.newURI(nextAlarm.manifestURL, null, null);
|
||||
messenger.sendMessage("alarm", nextAlarm, manifestURI);
|
||||
} else {
|
||||
this._currentAlarm = nextAlarm;
|
||||
break;
|
||||
|
@ -45,6 +45,11 @@ AlarmsManager.prototype = {
|
||||
add: function add(aDate, aRespectTimezone, aData) {
|
||||
debug("add()");
|
||||
|
||||
if (!this._manifestURL) {
|
||||
debug("Cannot add alarms for non-installed apps.");
|
||||
throw Components.results.NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
let isIgnoreTimezone = true;
|
||||
switch (aRespectTimezone) {
|
||||
case "honorTimezone":
|
||||
@ -150,8 +155,7 @@ AlarmsManager.prototype = {
|
||||
|
||||
// Get the manifest URL if this is an installed app
|
||||
this._manifestURL = null;
|
||||
let utils = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
let utils = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
let app = utils.getApp();
|
||||
if (app)
|
||||
this._manifestURL = app.manifestURL;
|
||||
|
@ -1298,7 +1298,7 @@ Navigator::GetMozBluetooth(nsIDOMBluetoothManager** aBluetooth)
|
||||
// nsNavigator::nsIDOMNavigatorSystemMessages
|
||||
//*****************************************************************************
|
||||
#ifdef MOZ_SYS_MSG
|
||||
NS_IMETHODIMP
|
||||
nsresult
|
||||
Navigator::EnsureMessagesManager()
|
||||
{
|
||||
if (mMessagesManager) {
|
||||
|
@ -5973,6 +5973,9 @@ DefineIDBInterfaceConstants(JSContext *cx, JSObject *obj, const nsIID *aIID)
|
||||
else if (aIID->Equals(NS_GET_IID(nsIIDBTransaction))) {
|
||||
interface = IDBConstant::IDBTransaction;
|
||||
}
|
||||
else {
|
||||
MOZ_NOT_REACHED("unexpected IID");
|
||||
}
|
||||
|
||||
for (int8_t i = 0; i < (int8_t)mozilla::ArrayLength(sIDBConstants); ++i) {
|
||||
const IDBConstant& c = sIDBConstants[i];
|
||||
|
@ -9400,9 +9400,7 @@ nsGlobalWindow::SetTimeoutOrInterval(nsIScriptTimeoutHandler *aHandler,
|
||||
|
||||
nsRefPtr<nsTimeout> copy = timeout;
|
||||
|
||||
rv = timeout->mTimer->InitWithFuncCallback(TimerCallback, timeout,
|
||||
realInterval,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
rv = timeout->InitTimer(TimerCallback, realInterval);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@ -9637,10 +9635,7 @@ nsGlobalWindow::RescheduleTimeout(nsTimeout* aTimeout, const TimeStamp& now,
|
||||
// platforms whether delay is positive or negative (which we
|
||||
// know is always positive here, but cast anyways for
|
||||
// consistency).
|
||||
nsresult rv = aTimeout->mTimer->
|
||||
InitWithFuncCallback(TimerCallback, aTimeout,
|
||||
delay.ToMilliseconds(),
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
nsresult rv = aTimeout->InitTimer(TimerCallback, delay.ToMilliseconds());
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("Error initializing timer for DOM timeout!");
|
||||
@ -9982,11 +9977,7 @@ nsresult nsGlobalWindow::ResetTimersForNonBackgroundWindow()
|
||||
timeout->mFiringDepth = firingDepth;
|
||||
timeout->Release();
|
||||
|
||||
nsresult rv =
|
||||
timeout->mTimer->InitWithFuncCallback(TimerCallback,
|
||||
timeout,
|
||||
delay.ToMilliseconds(),
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
nsresult rv = timeout->InitTimer(TimerCallback, delay.ToMilliseconds());
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Error resetting non background timer for DOM timeout!");
|
||||
@ -10499,8 +10490,7 @@ nsGlobalWindow::ResumeTimeouts(bool aThawChildren)
|
||||
t->mTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
NS_ENSURE_TRUE(t->mTimer, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
rv = t->mTimer->InitWithFuncCallback(TimerCallback, t, delay,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
rv = t->InitTimer(TimerCallback, delay);
|
||||
if (NS_FAILED(rv)) {
|
||||
t->mTimer = nsnull;
|
||||
return rv;
|
||||
|
@ -153,6 +153,11 @@ struct nsTimeout : PRCList
|
||||
return static_cast<nsTimeout*>(PR_PREV_LINK(this));
|
||||
}
|
||||
|
||||
nsresult InitTimer(nsTimerCallbackFunc aFunc, PRUint64 delay) {
|
||||
return mTimer->InitWithFuncCallback(aFunc, this, delay,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
|
||||
// Window for which this timeout fires
|
||||
nsRefPtr<nsGlobalWindow> mWindow;
|
||||
|
||||
|
@ -80,8 +80,9 @@ template<>
|
||||
struct PrimitiveConversionTraits<bool> {
|
||||
typedef JSBool jstype;
|
||||
typedef bool intermediateType;
|
||||
static inline bool converter(JSContext* cx, JS::Value v, jstype* retval) {
|
||||
return JS_ValueToBoolean(cx, v, retval);
|
||||
static inline bool converter(JSContext* /* unused */, JS::Value v, jstype* retval) {
|
||||
*retval = JS::ToBoolean(v);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -403,8 +403,10 @@ EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData)
|
||||
|
||||
DBusMessageIter iter;
|
||||
|
||||
NS_ASSERTION(dbus_message_iter_init(aMsg, &iter),
|
||||
"Can't create message iterator!");
|
||||
if (!dbus_message_iter_init(aMsg, &iter)) {
|
||||
NS_WARNING("Can't create iterator!");
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
InfallibleTArray<BluetoothNamedValue> value;
|
||||
const char* addr;
|
||||
|
@ -13,7 +13,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<body onunload="unload()">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
@ -22,11 +22,21 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
function unload() {
|
||||
delete gDataBlob;
|
||||
gDataBlob = null;
|
||||
|
||||
delete gFileReader;
|
||||
gFileReader = null;
|
||||
}
|
||||
|
||||
|
||||
devicestorage_setup();
|
||||
|
||||
var gFileName = "devicestorage/hi";
|
||||
var gData = "My name is Doug Turner. My IRC nick is DougT. I like Maple cookies."
|
||||
var gDataBlob = new Blob([gData], {type: 'text/plain'});
|
||||
var gFileReader = new FileReader();
|
||||
|
||||
function getAfterDeleteSuccess(e) {
|
||||
ok(false, "file was deleted not successfully");
|
||||
@ -63,9 +73,8 @@ function getSuccess(e) {
|
||||
|
||||
var name = e.target.result.name;
|
||||
|
||||
var reader = new FileReader();
|
||||
reader.readAsArrayBuffer(gDataBlob);
|
||||
reader.onload = function(e) {
|
||||
gFileReader.readAsArrayBuffer(gDataBlob);
|
||||
gFileReader.onload = function(e) {
|
||||
readerCallback(e);
|
||||
|
||||
request = storage[0].delete(name)
|
||||
|
@ -17,7 +17,7 @@ namespace dom {
|
||||
void
|
||||
CrashReporterParent::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
#if defined(__ANDROID__) && defined(MOZ_CRASHREPORTER)
|
||||
#if defined(MOZ_WIDGET_ANDROID) && defined(MOZ_CRASHREPORTER)
|
||||
CrashReporter::RemoveLibraryMappingsForChild(ProcessId(OtherProcess()));
|
||||
#endif
|
||||
}
|
||||
@ -25,7 +25,7 @@ CrashReporterParent::ActorDestroy(ActorDestroyReason why)
|
||||
bool
|
||||
CrashReporterParent::RecvAddLibraryMappings(const InfallibleTArray<Mapping>& mappings)
|
||||
{
|
||||
#if defined(__ANDROID__) && defined(MOZ_CRASHREPORTER)
|
||||
#if defined(MOZ_WIDGET_ANDROID) && defined(MOZ_CRASHREPORTER)
|
||||
for (PRUint32 i = 0; i < mappings.Length(); i++) {
|
||||
const Mapping& m = mappings[i];
|
||||
CrashReporter::AddLibraryMappingForChild(ProcessId(OtherProcess()),
|
||||
|
@ -1947,6 +1947,68 @@ nsPluginHost::IsLiveTag(nsIPluginTag* aPluginTag)
|
||||
return false;
|
||||
}
|
||||
|
||||
nsPluginTag*
|
||||
nsPluginHost::HaveSamePlugin(const nsPluginTag* aPluginTag)
|
||||
{
|
||||
for (nsPluginTag* tag = mPlugins; tag; tag = tag->mNext) {
|
||||
if (tag->HasSameNameAndMimes(aPluginTag)) {
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsPluginTag*
|
||||
nsPluginHost::FirstPluginWithPath(const nsCString& path)
|
||||
{
|
||||
for (nsPluginTag* tag = mPlugins; tag; tag = tag->mNext) {
|
||||
if (tag->mFullPath.Equals(path)) {
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
PRInt64 GetPluginLastModifiedTime(const nsCOMPtr<nsIFile>& localfile)
|
||||
{
|
||||
PRInt64 fileModTime = LL_ZERO;
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
// On OS X the date of a bundle's "contents" (i.e. of its Info.plist file)
|
||||
// is a much better guide to when it was last modified than the date of
|
||||
// its package directory. See bug 313700.
|
||||
nsCOMPtr<nsILocalFileMac> localFileMac = do_QueryInterface(localfile);
|
||||
if (localFileMac) {
|
||||
localFileMac->GetBundleContentsLastModifiedTime(&fileModTime);
|
||||
} else {
|
||||
localfile->GetLastModifiedTime(&fileModTime);
|
||||
}
|
||||
#else
|
||||
localfile->GetLastModifiedTime(&fileModTime);
|
||||
#endif
|
||||
|
||||
return fileModTime;
|
||||
}
|
||||
|
||||
struct CompareFilesByTime
|
||||
{
|
||||
bool
|
||||
LessThan(const nsCOMPtr<nsIFile>& a, const nsCOMPtr<nsIFile>& b) const
|
||||
{
|
||||
return LL_CMP(GetPluginLastModifiedTime(a), <, GetPluginLastModifiedTime(b));
|
||||
}
|
||||
|
||||
bool
|
||||
Equals(const nsCOMPtr<nsIFile>& a, const nsCOMPtr<nsIFile>& b) const
|
||||
{
|
||||
return LL_EQ(GetPluginLastModifiedTime(a), GetPluginLastModifiedTime(b));
|
||||
}
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
typedef NS_NPAPIPLUGIN_CALLBACK(char *, NP_GETMIMEDESCRIPTION)(void);
|
||||
|
||||
nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
|
||||
@ -1991,9 +2053,11 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
|
||||
}
|
||||
}
|
||||
|
||||
pluginFiles.Sort(CompareFilesByTime());
|
||||
|
||||
bool warnOutdated = false;
|
||||
|
||||
for (PRUint32 i = 0; i < pluginFiles.Length(); i++) {
|
||||
for (PRInt32 i = (pluginFiles.Length() - 1); i >= 0; i--) {
|
||||
nsCOMPtr<nsIFile>& localfile = pluginFiles[i];
|
||||
|
||||
nsString utf16FilePath;
|
||||
@ -2001,21 +2065,8 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
|
||||
if (NS_FAILED(rv))
|
||||
continue;
|
||||
|
||||
PRInt64 fileModTime = LL_ZERO;
|
||||
#if defined(XP_MACOSX)
|
||||
// On OS X the date of a bundle's "contents" (i.e. of its Info.plist file)
|
||||
// is a much better guide to when it was last modified than the date of
|
||||
// its package directory. See bug 313700.
|
||||
nsCOMPtr<nsILocalFileMac> localFileMac = do_QueryInterface(localfile);
|
||||
if (localFileMac) {
|
||||
localFileMac->GetBundleContentsLastModifiedTime(&fileModTime);
|
||||
} else {
|
||||
localfile->GetLastModifiedTime(&fileModTime);
|
||||
}
|
||||
#else
|
||||
localfile->GetLastModifiedTime(&fileModTime);
|
||||
#endif
|
||||
|
||||
PRInt64 fileModTime = GetPluginLastModifiedTime(localfile);
|
||||
|
||||
// Look for it in our cache
|
||||
NS_ConvertUTF16toUTF8 filePath(utf16FilePath);
|
||||
nsRefPtr<nsPluginTag> pluginTag;
|
||||
@ -2146,6 +2197,21 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
|
||||
// We have a valid new plugin so report that plugins have changed.
|
||||
*aPluginsChanged = true;
|
||||
}
|
||||
|
||||
// Avoid adding different versions of the same plugin if they are running
|
||||
// in-process, otherwise we risk undefined behaviour.
|
||||
if (!nsNPAPIPlugin::RunPluginOOP(pluginTag)) {
|
||||
if (nsPluginTag *duplicate = HaveSamePlugin(pluginTag)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Don't add the same plugin again if it hasn't changed
|
||||
if (nsPluginTag* duplicate = FirstPluginWithPath(pluginTag->mFullPath)) {
|
||||
if (LL_EQ(pluginTag->mLastModifiedTime, duplicate->mLastModifiedTime)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// If we're not creating a plugin list, simply looking for changes,
|
||||
// then we're done.
|
||||
|
@ -267,6 +267,12 @@ private:
|
||||
|
||||
// Checks to see if a tag object is in our list of live tags.
|
||||
bool IsLiveTag(nsIPluginTag* tag);
|
||||
|
||||
// Checks our list of live tags for an equivalent tag.
|
||||
nsPluginTag* HaveSamePlugin(const nsPluginTag * aPluginTag);
|
||||
|
||||
// Returns the first plugin at |path|
|
||||
nsPluginTag* FirstPluginWithPath(const nsCString& path);
|
||||
|
||||
nsresult EnsurePrivateDirServiceProvider();
|
||||
|
||||
|
@ -379,6 +379,25 @@ bool nsPluginTag::IsEnabled()
|
||||
return HasFlag(NS_PLUGIN_FLAG_ENABLED) && !HasFlag(NS_PLUGIN_FLAG_BLOCKLISTED);
|
||||
}
|
||||
|
||||
bool
|
||||
nsPluginTag::HasSameNameAndMimes(const nsPluginTag *aPluginTag) const
|
||||
{
|
||||
NS_ENSURE_TRUE(aPluginTag, false);
|
||||
|
||||
if ((!mName.Equals(aPluginTag->mName)) ||
|
||||
(mMimeTypes.Length() != aPluginTag->mMimeTypes.Length())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (PRUint32 i = 0; i < mMimeTypes.Length(); i++) {
|
||||
if (!mMimeTypes[i].Equals(aPluginTag->mMimeTypes[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void nsPluginTag::TryUnloadPlugin(bool inShutdown)
|
||||
{
|
||||
// We never want to send NPP_Shutdown to an in-process plugin unless
|
||||
|
@ -58,6 +58,7 @@ public:
|
||||
void UnMark(PRUint32 mask);
|
||||
bool HasFlag(PRUint32 flag);
|
||||
PRUint32 Flags();
|
||||
bool HasSameNameAndMimes(const nsPluginTag *aPluginTag) const;
|
||||
bool IsEnabled();
|
||||
|
||||
nsRefPtr<nsPluginTag> mNext;
|
||||
|
@ -1922,7 +1922,7 @@ bool
|
||||
PluginInstanceParent::SharedSurfaceSetWindow(const NPWindow* aWindow,
|
||||
NPRemoteWindow& aRemoteWindow)
|
||||
{
|
||||
aRemoteWindow.window = nsnull;
|
||||
aRemoteWindow.window = 0;
|
||||
aRemoteWindow.x = aWindow->x;
|
||||
aRemoteWindow.y = aWindow->y;
|
||||
aRemoteWindow.width = aWindow->width;
|
||||
|
@ -140,17 +140,17 @@ function RILContentHelper() {
|
||||
this.initMessageListener(RIL_IPC_MSG_NAMES);
|
||||
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
||||
|
||||
// Request initial state.
|
||||
let radioState = cpmm.QueryInterface(Ci.nsISyncMessageSender)
|
||||
.sendSyncMessage("RIL:GetRadioState")[0];
|
||||
// Request initial context.
|
||||
let rilContext = cpmm.QueryInterface(Ci.nsISyncMessageSender)
|
||||
.sendSyncMessage("RIL:GetRilContext")[0];
|
||||
|
||||
if (!radioState) {
|
||||
debug("Received null radioState from chrome process.");
|
||||
if (!rilContext) {
|
||||
debug("Received null rilContext from chrome process.");
|
||||
return;
|
||||
}
|
||||
this.cardState = radioState.cardState;
|
||||
this.updateConnectionInfo(radioState.voice, this.voiceConnectionInfo);
|
||||
this.updateConnectionInfo(radioState.data, this.dataConnectionInfo);
|
||||
this.cardState = rilContext.cardState;
|
||||
this.updateConnectionInfo(rilContext.voice, this.voiceConnectionInfo);
|
||||
this.updateConnectionInfo(rilContext.data, this.dataConnectionInfo);
|
||||
}
|
||||
|
||||
RILContentHelper.prototype = {
|
||||
|
@ -60,6 +60,7 @@ let RILQUIRKS_DATACALLSTATE_DOWN_IS_UP = false;
|
||||
let RILQUIRKS_V5_LEGACY = true;
|
||||
let RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL = false;
|
||||
let RILQUIRKS_MODEM_DEFAULTS_TO_EMERGENCY_MODE = false;
|
||||
let RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS = false;
|
||||
|
||||
/**
|
||||
* This object contains helpers buffering incoming data & deconstructing it
|
||||
@ -727,6 +728,10 @@ let RIL = {
|
||||
case "Qualcomm RIL 1.0":
|
||||
let product_model = libcutils.property_get("ro.product.model");
|
||||
if (DEBUG) debug("Detected product model " + product_model);
|
||||
if (product_model == "otoro1") {
|
||||
if (DEBUG) debug("Enabling RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS.");
|
||||
RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS = true;
|
||||
}
|
||||
if (DEBUG) {
|
||||
debug("Detected Qualcomm RIL 1.0, " +
|
||||
"disabling RILQUIRKS_V5_LEGACY and " +
|
||||
@ -2825,6 +2830,12 @@ RIL[REQUEST_GET_SIM_STATUS] = function REQUEST_GET_SIM_STATUS(length, options) {
|
||||
pin1: Buf.readUint32(),
|
||||
pin2: Buf.readUint32()
|
||||
});
|
||||
if (RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS) {
|
||||
Buf.readUint32();
|
||||
Buf.readUint32();
|
||||
Buf.readUint32();
|
||||
Buf.readUint32();
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG) debug("iccStatus: " + JSON.stringify(iccStatus));
|
||||
|
@ -7,7 +7,9 @@
|
||||
#include "nsEditor.h"
|
||||
#include "IMETextTxn.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsISelection.h"
|
||||
#include "mozilla/Selection.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
PlaceholderTxn::PlaceholderTxn() : EditAggregateTxn(),
|
||||
mAbsorb(true),
|
||||
@ -42,7 +44,9 @@ NS_INTERFACE_MAP_END_INHERITING(EditAggregateTxn)
|
||||
NS_IMPL_ADDREF_INHERITED(PlaceholderTxn, EditAggregateTxn)
|
||||
NS_IMPL_RELEASE_INHERITED(PlaceholderTxn, EditAggregateTxn)
|
||||
|
||||
NS_IMETHODIMP PlaceholderTxn::Init(nsIAtom *aName, nsSelectionState *aSelState, nsIEditor *aEditor)
|
||||
NS_IMETHODIMP
|
||||
PlaceholderTxn::Init(nsIAtom* aName, nsSelectionState* aSelState,
|
||||
nsEditor* aEditor)
|
||||
{
|
||||
NS_ENSURE_TRUE(aEditor && aSelState, NS_ERROR_NULL_POINTER);
|
||||
|
||||
@ -256,10 +260,9 @@ NS_IMETHODIMP PlaceholderTxn::Commit()
|
||||
|
||||
NS_IMETHODIMP PlaceholderTxn::RememberEndingSelection()
|
||||
{
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
nsresult res = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
nsRefPtr<Selection> selection = mEditor->GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
|
||||
return mEndSel.SaveSelection(selection);
|
||||
mEndSel.SaveSelection(selection);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,8 @@ public:
|
||||
|
||||
// ------------ nsIAbsorbingTransaction -----------------------
|
||||
|
||||
NS_IMETHOD Init(nsIAtom *aName, nsSelectionState *aSelState, nsIEditor *aEditor);
|
||||
NS_IMETHOD Init(nsIAtom* aName, nsSelectionState* aSelState,
|
||||
nsEditor* aEditor);
|
||||
|
||||
NS_IMETHOD GetTxnName(nsIAtom **aName);
|
||||
|
||||
@ -72,7 +73,7 @@ protected:
|
||||
// selection properly.
|
||||
nsAutoPtr<nsSelectionState> mStartSel; // use a pointer because this is constructed before we exist
|
||||
nsSelectionState mEndSel;
|
||||
nsIEditor* mEditor; /** the editor for this transaction */
|
||||
nsEditor* mEditor; /** the editor for this transaction */
|
||||
};
|
||||
|
||||
|
||||
|
18
editor/libeditor/base/crashtests/776323.html
Normal file
18
editor/libeditor/base/crashtests/776323.html
Normal file
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html contenteditable="true">
|
||||
<head>
|
||||
<script>
|
||||
|
||||
function boom()
|
||||
{
|
||||
document.execCommand("inserthtml", false, "b");
|
||||
var myrange = document.createRange();
|
||||
myrange.selectNodeContents(document.getElementsByTagName("img")[0]);
|
||||
window.getSelection().addRange(myrange);
|
||||
document.execCommand("strikethrough", false, null);
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="boom();"><img></body>
|
||||
</html>
|
@ -17,3 +17,4 @@ load 766845.xhtml
|
||||
load 768765.html
|
||||
needs-focus load 771749.html
|
||||
load 772282.html
|
||||
load 776323.html
|
||||
|
@ -904,9 +904,8 @@ nsEditor::BeginPlaceHolderTransaction(nsIAtom *aName)
|
||||
BeginUpdateViewBatch();
|
||||
mPlaceHolderTxn = nsnull;
|
||||
mPlaceHolderName = aName;
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
nsresult res = GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
nsRefPtr<Selection> selection = GetSelection();
|
||||
if (selection) {
|
||||
mSelState = new nsSelectionState();
|
||||
mSelState->SaveSelection(selection);
|
||||
}
|
||||
@ -1979,7 +1978,7 @@ nsEditor::ArePreservingSelection()
|
||||
}
|
||||
|
||||
void
|
||||
nsEditor::PreserveSelectionAcrossActions(nsISelection *aSel)
|
||||
nsEditor::PreserveSelectionAcrossActions(Selection* aSel)
|
||||
{
|
||||
mSavedSel.SaveSelection(aSel);
|
||||
mRangeUpdater.RegisterSelectionState(mSavedSel);
|
||||
|
@ -425,7 +425,7 @@ public:
|
||||
/** routines for managing the preservation of selection across
|
||||
* various editor actions */
|
||||
bool ArePreservingSelection();
|
||||
void PreserveSelectionAcrossActions(nsISelection *aSel);
|
||||
void PreserveSelectionAcrossActions(mozilla::Selection* aSel);
|
||||
nsresult RestorePreservedSelection(nsISelection *aSel);
|
||||
void StopPreservingSelection();
|
||||
|
||||
|
@ -3,7 +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 "mozilla/Selection.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsEditorUtils.h"
|
||||
@ -18,24 +18,23 @@
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsINode.h"
|
||||
#include "nsISelection.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
|
||||
class nsIDOMRange;
|
||||
class nsISupports;
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
/******************************************************************************
|
||||
* nsAutoSelectionReset
|
||||
*****************************************************************************/
|
||||
|
||||
nsAutoSelectionReset::nsAutoSelectionReset(nsISelection *aSel, nsEditor *aEd) :
|
||||
mSel(nsnull)
|
||||
,mEd(nsnull)
|
||||
nsAutoSelectionReset::nsAutoSelectionReset(Selection* aSel, nsEditor* aEd)
|
||||
: mSel(nsnull), mEd(nsnull)
|
||||
{
|
||||
if (!aSel || !aEd) return; // not much we can do, bail.
|
||||
if (aEd->ArePreservingSelection()) return; // we already have initted mSavedSel, so this must be nested call.
|
||||
mSel = do_QueryInterface(aSel);
|
||||
mSel = aSel;
|
||||
mEd = aEd;
|
||||
if (mSel)
|
||||
{
|
||||
|
@ -57,12 +57,12 @@ class NS_STACK_CLASS nsAutoSelectionReset
|
||||
{
|
||||
private:
|
||||
/** ref-counted reference to the selection that we are supposed to restore */
|
||||
nsCOMPtr<nsISelection> mSel;
|
||||
nsRefPtr<mozilla::Selection> mSel;
|
||||
nsEditor *mEd; // non-owning ref to nsEditor
|
||||
|
||||
public:
|
||||
/** constructor responsible for remembering all state needed to restore aSel */
|
||||
nsAutoSelectionReset(nsISelection *aSel, nsEditor *aEd);
|
||||
nsAutoSelectionReset(mozilla::Selection* aSel, nsEditor* aEd);
|
||||
|
||||
/** destructor restores mSel to its former state */
|
||||
~nsAutoSelectionReset();
|
||||
|
@ -32,7 +32,8 @@ public:
|
||||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IABSORBINGTRANSACTION_IID)
|
||||
|
||||
NS_IMETHOD Init(nsIAtom *aName, nsSelectionState *aSelState, nsIEditor *aEditor)=0;
|
||||
NS_IMETHOD Init(nsIAtom* aName, nsSelectionState* aSelState,
|
||||
nsEditor* aEditor) = 0;
|
||||
|
||||
NS_IMETHOD EndPlaceHolderBatch()=0;
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
|
||||
#include "mozilla/Selection.h" // for Selection
|
||||
#include "nsAString.h" // for nsAString_internal::Length
|
||||
#include "nsAutoPtr.h" // for nsRefPtr, getter_AddRefs, etc
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
@ -19,6 +20,7 @@
|
||||
#include "nsRange.h" // for nsRange
|
||||
#include "nsSelectionState.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
/***************************************************************************
|
||||
* class for recording selection info. stores selection as collection of
|
||||
@ -47,43 +49,30 @@ nsSelectionState::DoTraverse(nsCycleCollectionTraversalCallback &cb)
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSelectionState::SaveSelection(nsISelection *aSel)
|
||||
void
|
||||
nsSelectionState::SaveSelection(Selection* aSel)
|
||||
{
|
||||
NS_ENSURE_TRUE(aSel, NS_ERROR_NULL_POINTER);
|
||||
PRInt32 i,rangeCount, arrayCount = mArray.Length();
|
||||
aSel->GetRangeCount(&rangeCount);
|
||||
|
||||
MOZ_ASSERT(aSel);
|
||||
PRInt32 arrayCount = mArray.Length();
|
||||
PRInt32 rangeCount = aSel->GetRangeCount();
|
||||
|
||||
// if we need more items in the array, new them
|
||||
if (arrayCount<rangeCount)
|
||||
{
|
||||
PRInt32 count = rangeCount-arrayCount;
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
if (arrayCount < rangeCount) {
|
||||
for (PRInt32 i = arrayCount; i < rangeCount; i++) {
|
||||
mArray.AppendElement();
|
||||
mArray[i] = new nsRangeStore();
|
||||
}
|
||||
}
|
||||
|
||||
// else if we have too many, delete them
|
||||
else if (arrayCount>rangeCount)
|
||||
{
|
||||
for (i = arrayCount-1; i >= rangeCount; i--)
|
||||
{
|
||||
} else if (arrayCount > rangeCount) {
|
||||
// else if we have too many, delete them
|
||||
for (PRInt32 i = arrayCount - 1; i >= rangeCount; i--) {
|
||||
mArray.RemoveElementAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// now store the selection ranges
|
||||
nsresult res = NS_OK;
|
||||
for (i=0; i<rangeCount; i++)
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
res = aSel->GetRangeAt(i, getter_AddRefs(range));
|
||||
mArray[i]->StoreRange(range);
|
||||
for (PRInt32 i = 0; i < rangeCount; i++) {
|
||||
mArray[i]->StoreRange(aSel->GetRangeAt(i));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -18,6 +18,9 @@ class nsIDOMCharacterData;
|
||||
class nsIDOMRange;
|
||||
class nsISelection;
|
||||
class nsRange;
|
||||
namespace mozilla {
|
||||
class Selection;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* class for recording selection info. stores selection as collection of
|
||||
@ -52,7 +55,7 @@ class nsSelectionState
|
||||
void DoTraverse(nsCycleCollectionTraversalCallback &cb);
|
||||
void DoUnlink() { MakeEmpty(); }
|
||||
|
||||
nsresult SaveSelection(nsISelection *aSel);
|
||||
void SaveSelection(mozilla::Selection *aSel);
|
||||
nsresult RestoreSelection(nsISelection *aSel);
|
||||
bool IsCollapsed();
|
||||
bool IsEqual(nsSelectionState *aSelState);
|
||||
|
@ -2869,7 +2869,7 @@ nsHTMLEditRules::DidDeleteSelection(nsISelection *aSelection,
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillMakeList(nsISelection* aSelection,
|
||||
nsHTMLEditRules::WillMakeList(Selection* aSelection,
|
||||
const nsAString* aListType,
|
||||
bool aEntireList,
|
||||
const nsAString* aBulletType,
|
||||
@ -3159,7 +3159,7 @@ nsHTMLEditRules::WillMakeList(nsISelection* aSelection,
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillRemoveList(nsISelection *aSelection,
|
||||
nsHTMLEditRules::WillRemoveList(Selection* aSelection,
|
||||
bool aOrdered,
|
||||
bool *aCancel,
|
||||
bool *aHandled)
|
||||
@ -3226,7 +3226,7 @@ nsHTMLEditRules::WillRemoveList(nsISelection *aSelection,
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillMakeDefListItem(nsISelection *aSelection,
|
||||
nsHTMLEditRules::WillMakeDefListItem(Selection* aSelection,
|
||||
const nsAString *aItemType,
|
||||
bool aEntireList,
|
||||
bool *aCancel,
|
||||
@ -3238,7 +3238,7 @@ nsHTMLEditRules::WillMakeDefListItem(nsISelection *aSelection,
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillMakeBasicBlock(nsISelection *aSelection,
|
||||
nsHTMLEditRules::WillMakeBasicBlock(Selection* aSelection,
|
||||
const nsAString *aBlockType,
|
||||
bool *aCancel,
|
||||
bool *aHandled)
|
||||
@ -3395,7 +3395,8 @@ nsHTMLEditRules::DidMakeBasicBlock(nsISelection *aSelection,
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillIndent(nsISelection *aSelection, bool *aCancel, bool * aHandled)
|
||||
nsHTMLEditRules::WillIndent(Selection* aSelection,
|
||||
bool* aCancel, bool* aHandled)
|
||||
{
|
||||
nsresult res;
|
||||
if (mHTMLEditor->IsCSSEnabled()) {
|
||||
@ -3408,7 +3409,8 @@ nsHTMLEditRules::WillIndent(nsISelection *aSelection, bool *aCancel, bool * aHan
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillCSSIndent(nsISelection *aSelection, bool *aCancel, bool * aHandled)
|
||||
nsHTMLEditRules::WillCSSIndent(Selection* aSelection,
|
||||
bool* aCancel, bool* aHandled)
|
||||
{
|
||||
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
|
||||
|
||||
@ -3614,7 +3616,8 @@ nsHTMLEditRules::WillCSSIndent(nsISelection *aSelection, bool *aCancel, bool * a
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillHTMLIndent(nsISelection *aSelection, bool *aCancel, bool * aHandled)
|
||||
nsHTMLEditRules::WillHTMLIndent(Selection* aSelection,
|
||||
bool* aCancel, bool* aHandled)
|
||||
{
|
||||
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
|
||||
nsresult res = WillInsert(aSelection, aCancel);
|
||||
@ -3842,7 +3845,8 @@ nsHTMLEditRules::WillHTMLIndent(nsISelection *aSelection, bool *aCancel, bool *
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillOutdent(nsISelection *aSelection, bool *aCancel, bool *aHandled)
|
||||
nsHTMLEditRules::WillOutdent(Selection* aSelection,
|
||||
bool* aCancel, bool* aHandled)
|
||||
{
|
||||
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
|
||||
// initialize out param
|
||||
@ -4412,7 +4416,7 @@ nsHTMLEditRules::IsEmptyBlock(nsIDOMNode *aNode,
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillAlign(nsISelection *aSelection,
|
||||
nsHTMLEditRules::WillAlign(Selection* aSelection,
|
||||
const nsAString *alignType,
|
||||
bool *aCancel,
|
||||
bool *aHandled)
|
||||
@ -8570,7 +8574,8 @@ nsHTMLEditRules::RelativeChangeIndentationOfElementNode(nsIDOMNode *aNode, PRInt
|
||||
//
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillAbsolutePosition(nsISelection *aSelection, bool *aCancel, bool * aHandled)
|
||||
nsHTMLEditRules::WillAbsolutePosition(Selection* aSelection,
|
||||
bool* aCancel, bool* aHandled)
|
||||
{
|
||||
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
|
||||
nsresult res = WillInsert(aSelection, aCancel);
|
||||
@ -8786,8 +8791,8 @@ nsHTMLEditRules::DidAbsolutePosition()
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillRemoveAbsolutePosition(nsISelection *aSelection, bool *aCancel, bool * aHandled)
|
||||
{
|
||||
nsHTMLEditRules::WillRemoveAbsolutePosition(Selection* aSelection,
|
||||
bool* aCancel, bool* aHandled) {
|
||||
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
|
||||
nsresult res = WillInsert(aSelection, aCancel);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
@ -8808,7 +8813,7 @@ nsHTMLEditRules::WillRemoveAbsolutePosition(nsISelection *aSelection, bool *aCan
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillRelativeChangeZIndex(nsISelection *aSelection,
|
||||
nsHTMLEditRules::WillRelativeChangeZIndex(Selection* aSelection,
|
||||
PRInt32 aChange,
|
||||
bool *aCancel,
|
||||
bool * aHandled)
|
||||
|
@ -156,18 +156,38 @@ protected:
|
||||
nsresult MoveNodeSmart(nsIDOMNode *aSource, nsIDOMNode *aDest, PRInt32 *aOffset);
|
||||
nsresult MoveContents(nsIDOMNode *aSource, nsIDOMNode *aDest, PRInt32 *aOffset);
|
||||
nsresult DeleteNonTableElements(nsINode* aNode);
|
||||
nsresult WillMakeList(nsISelection *aSelection, const nsAString *aListType, bool aEntireList, const nsAString *aBulletType, bool *aCancel, bool *aHandled, const nsAString *aItemType=nsnull);
|
||||
nsresult WillRemoveList(nsISelection *aSelection, bool aOrderd, bool *aCancel, bool *aHandled);
|
||||
nsresult WillIndent(nsISelection *aSelection, bool *aCancel, bool *aHandled);
|
||||
nsresult WillCSSIndent(nsISelection *aSelection, bool *aCancel, bool *aHandled);
|
||||
nsresult WillHTMLIndent(nsISelection *aSelection, bool *aCancel, bool *aHandled);
|
||||
nsresult WillOutdent(nsISelection *aSelection, bool *aCancel, bool *aHandled);
|
||||
nsresult WillAlign(nsISelection *aSelection, const nsAString *alignType, bool *aCancel, bool *aHandled);
|
||||
nsresult WillAbsolutePosition(nsISelection *aSelection, bool *aCancel, bool * aHandled);
|
||||
nsresult WillRemoveAbsolutePosition(nsISelection *aSelection, bool *aCancel, bool * aHandled);
|
||||
nsresult WillRelativeChangeZIndex(nsISelection *aSelection, PRInt32 aChange, bool *aCancel, bool * aHandled);
|
||||
nsresult WillMakeDefListItem(nsISelection *aSelection, const nsAString *aBlockType, bool aEntireList, bool *aCancel, bool *aHandled);
|
||||
nsresult WillMakeBasicBlock(nsISelection *aSelection, const nsAString *aBlockType, bool *aCancel, bool *aHandled);
|
||||
nsresult WillMakeList(mozilla::Selection* aSelection,
|
||||
const nsAString* aListType,
|
||||
bool aEntireList,
|
||||
const nsAString* aBulletType,
|
||||
bool* aCancel, bool* aHandled,
|
||||
const nsAString* aItemType = nsnull);
|
||||
nsresult WillRemoveList(mozilla::Selection* aSelection,
|
||||
bool aOrdered, bool* aCancel, bool* aHandled);
|
||||
nsresult WillIndent(mozilla::Selection* aSelection,
|
||||
bool* aCancel, bool* aHandled);
|
||||
nsresult WillCSSIndent(mozilla::Selection* aSelection,
|
||||
bool* aCancel, bool* aHandled);
|
||||
nsresult WillHTMLIndent(mozilla::Selection* aSelection,
|
||||
bool* aCancel, bool* aHandled);
|
||||
nsresult WillOutdent(mozilla::Selection* aSelection,
|
||||
bool* aCancel, bool* aHandled);
|
||||
nsresult WillAlign(mozilla::Selection* aSelection,
|
||||
const nsAString* alignType,
|
||||
bool* aCancel, bool* aHandled);
|
||||
nsresult WillAbsolutePosition(mozilla::Selection* aSelection,
|
||||
bool* aCancel, bool* aHandled);
|
||||
nsresult WillRemoveAbsolutePosition(mozilla::Selection* aSelection,
|
||||
bool* aCancel, bool* aHandled);
|
||||
nsresult WillRelativeChangeZIndex(mozilla::Selection* aSelection,
|
||||
PRInt32 aChange,
|
||||
bool* aCancel, bool* aHandled);
|
||||
nsresult WillMakeDefListItem(mozilla::Selection* aSelection,
|
||||
const nsAString* aBlockType, bool aEntireList,
|
||||
bool* aCancel, bool* aHandled);
|
||||
nsresult WillMakeBasicBlock(mozilla::Selection* aSelection,
|
||||
const nsAString* aBlockType,
|
||||
bool* aCancel, bool* aHandled);
|
||||
nsresult DidMakeBasicBlock(nsISelection *aSelection, nsRulesInfo *aInfo, nsresult aResult);
|
||||
nsresult DidAbsolutePosition();
|
||||
nsresult AlignInnerBlocks(nsIDOMNode *aNode, const nsAString *alignType);
|
||||
|
@ -3379,15 +3379,13 @@ SetSelectionAroundHeadChildren(nsISelection* aSelection,
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::GetHeadContentsAsHTML(nsAString& aOutputString)
|
||||
{
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
nsresult res = GetSelection(getter_AddRefs(selection));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
nsRefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
|
||||
|
||||
// Save current selection
|
||||
nsAutoSelectionReset selectionResetter(selection, this);
|
||||
|
||||
res = SetSelectionAroundHeadChildren(selection, mDocWeak);
|
||||
nsresult res = SetSelectionAroundHeadChildren(selection, mDocWeak);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
res = OutputToString(NS_LITERAL_STRING("text/html"),
|
||||
|
@ -1535,11 +1535,8 @@ nsHTMLEditor::RelativeFontChange( PRInt32 aSizeChange)
|
||||
ForceCompositionEnd();
|
||||
|
||||
// Get the selection
|
||||
nsCOMPtr<nsISelection>selection;
|
||||
nsresult res = GetSelection(getter_AddRefs(selection));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
nsRefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsISelectionPrivate> selPriv(do_QueryInterface(selection));
|
||||
// Is the selection collapsed?
|
||||
// if it's collapsed set typing state
|
||||
if (selection->Collapsed()) {
|
||||
@ -1554,7 +1551,7 @@ nsHTMLEditor::RelativeFontChange( PRInt32 aSizeChange)
|
||||
NS_ENSURE_TRUE(selectedNode, NS_OK);
|
||||
if (IsTextNode(selectedNode)) {
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
res = selectedNode->GetParentNode(getter_AddRefs(parent));
|
||||
nsresult res = selectedNode->GetParentNode(getter_AddRefs(parent));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
selectedNode = parent;
|
||||
}
|
||||
@ -1575,7 +1572,7 @@ nsHTMLEditor::RelativeFontChange( PRInt32 aSizeChange)
|
||||
|
||||
// get selection range enumerator
|
||||
nsCOMPtr<nsIEnumerator> enumerator;
|
||||
res = selPriv->GetEnumerator(getter_AddRefs(enumerator));
|
||||
nsresult res = selection->GetEnumerator(getter_AddRefs(enumerator));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
NS_ENSURE_TRUE(enumerator, NS_ERROR_FAILURE);
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Selection.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsAString.h"
|
||||
#include "nsAlgorithm.h"
|
||||
@ -28,8 +29,6 @@
|
||||
#include "nsIHTMLEditor.h"
|
||||
#include "nsINode.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsISelection.h"
|
||||
#include "nsISelectionPrivate.h" // For nsISelectionPrivate::TABLESELECTION_ defines
|
||||
#include "nsISupportsUtils.h"
|
||||
#include "nsITableCellLayout.h" // For efficient access to table cell
|
||||
#include "nsITableEditor.h"
|
||||
@ -1953,9 +1952,7 @@ nsHTMLEditor::SwitchTableCellHeaderType(nsIDOMElement *aSourceCell, nsIDOMElemen
|
||||
// Save current selection to restore when done
|
||||
// This is needed so ReplaceContainer can monitor selection
|
||||
// when replacing nodes
|
||||
nsCOMPtr<nsISelection>selection;
|
||||
nsresult res = GetSelection(getter_AddRefs(selection));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
nsRefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
|
||||
nsAutoSelectionReset selectionResetter(selection, this);
|
||||
|
||||
@ -1965,7 +1962,8 @@ nsHTMLEditor::SwitchTableCellHeaderType(nsIDOMElement *aSourceCell, nsIDOMElemen
|
||||
|
||||
// This creates new node, moves children, copies attributes (true)
|
||||
// and manages the selection!
|
||||
res = ReplaceContainer(aSourceCell, address_of(newNode), newCellType, nsnull, nsnull, true);
|
||||
nsresult res = ReplaceContainer(aSourceCell, address_of(newNode),
|
||||
newCellType, nsnull, nsnull, true);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
NS_ENSURE_TRUE(newNode, NS_ERROR_FAILURE);
|
||||
|
||||
@ -2491,13 +2489,12 @@ nsHTMLEditor::FixBadColSpan(nsIDOMElement *aTable, PRInt32 aColIndex, PRInt32& a
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::NormalizeTable(nsIDOMElement *aTable)
|
||||
{
|
||||
nsCOMPtr<nsISelection>selection;
|
||||
nsresult res = GetSelection(getter_AddRefs(selection));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
nsRefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIDOMElement> table;
|
||||
res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), aTable, getter_AddRefs(table));
|
||||
nsresult res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"),
|
||||
aTable, getter_AddRefs(table));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
// Don't fail if we didn't find a table
|
||||
NS_ENSURE_TRUE(table, NS_OK);
|
||||
|
@ -583,6 +583,13 @@ nsDocShellTreeOwner::SetParentNativeWindow(nativeWindow aParentNativeWindow)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShellTreeOwner::GetNativeHandle(nsAString& aNativeHandle)
|
||||
{
|
||||
// the nativeHandle should be accessed from nsIXULWindow
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShellTreeOwner::GetVisibility(bool* aVisibility)
|
||||
{
|
||||
|
@ -1378,6 +1378,12 @@ NS_IMETHODIMP nsWebBrowser::SetParentNativeWindow(nativeWindow aParentNativeWind
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsWebBrowser::GetNativeHandle(nsAString& aNativeHandle)
|
||||
{
|
||||
// the nativeHandle should be accessed from nsIXULWindow
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsWebBrowser::GetVisibility(bool* visibility)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(visibility);
|
||||
|
@ -303,11 +303,13 @@ nsresult
|
||||
nsPermissionManager::InitDB(bool aRemoveFile)
|
||||
{
|
||||
nsCOMPtr<nsIFile> permissionsFile;
|
||||
NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(permissionsFile));
|
||||
if (!permissionsFile)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
nsresult rv = NS_GetSpecialDirectory(NS_APP_PERMISSION_PARENT_DIR, getter_AddRefs(permissionsFile));
|
||||
if (NS_FAILED(rv)) {
|
||||
rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(permissionsFile));
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsresult rv = permissionsFile->AppendNative(NS_LITERAL_CSTRING(kPermissionsFileName));
|
||||
rv = permissionsFile->AppendNative(NS_LITERAL_CSTRING(kPermissionsFileName));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (aRemoveFile) {
|
||||
|
@ -182,6 +182,8 @@ avoid-extend-none.patch: Avoid incorrectly using EXTEND_NONE (bug 751668)
|
||||
|
||||
win32-ExtCreatePen-zero-size.patch: Don't pass zero width or dash lengths to ExtCreatePen (bug 768348)
|
||||
|
||||
d2d-repeating-gradients.patch: Minimize number of gradient stops added to handle repeating with path fills (bug 768775)
|
||||
|
||||
==== pixman patches ====
|
||||
|
||||
pixman-android-cpu-detect.patch: Add CPU detection support for Android, where we can't reliably access /proc/self/auxv.
|
||||
|
@ -1416,7 +1416,7 @@ _cairo_d2d_create_radial_gradient_brush(cairo_d2d_surface_t *d2dsurf,
|
||||
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &top_left.x, &top_left.y);
|
||||
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &top_right.x, &top_right.y);
|
||||
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_left.x, &bottom_left.y);
|
||||
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_right.x, &top_left.y);
|
||||
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_right.x, &bottom_right.y);
|
||||
|
||||
// Find the corner furthest away from the gradient center in pattern space.
|
||||
double largest = MAX(_cairo_d2d_point_dist(top_left, gradient_center), _cairo_d2d_point_dist(top_right, gradient_center));
|
||||
@ -1536,6 +1536,7 @@ _cairo_d2d_create_radial_gradient_brush(cairo_d2d_surface_t *d2dsurf,
|
||||
|
||||
static RefPtr<ID2D1Brush>
|
||||
_cairo_d2d_create_linear_gradient_brush(cairo_d2d_surface_t *d2dsurf,
|
||||
cairo_path_fixed_t *fill_path,
|
||||
cairo_linear_pattern_t *source_pattern)
|
||||
{
|
||||
if (source_pattern->p1.x == source_pattern->p2.x &&
|
||||
@ -1569,25 +1570,36 @@ _cairo_d2d_create_linear_gradient_brush(cairo_d2d_surface_t *d2dsurf,
|
||||
D2D1_GRADIENT_STOP *stops;
|
||||
int num_stops = source_pattern->base.n_stops;
|
||||
if (source_pattern->base.base.extend == CAIRO_EXTEND_REPEAT || source_pattern->base.base.extend == CAIRO_EXTEND_REFLECT) {
|
||||
|
||||
RefPtr<IDXGISurface> surf;
|
||||
d2dsurf->surface->QueryInterface(&surf);
|
||||
DXGI_SURFACE_DESC desc;
|
||||
surf->GetDesc(&desc);
|
||||
|
||||
// Get this when the points are not transformed yet.
|
||||
double gradient_length = _cairo_d2d_point_dist(p1, p2);
|
||||
cairo_point_double_t top_left, top_right, bottom_left, bottom_right;
|
||||
|
||||
if (fill_path) {
|
||||
// Calculate the repeat count needed;
|
||||
cairo_box_t fill_extents;
|
||||
_cairo_path_fixed_extents (fill_path, &fill_extents);
|
||||
|
||||
top_left.x = bottom_left.x = _cairo_fixed_to_double (fill_extents.p1.x);
|
||||
top_left.y = top_right.y = _cairo_fixed_to_double (fill_extents.p1.y);
|
||||
top_right.x = bottom_right.x = _cairo_fixed_to_double (fill_extents.p2.x);
|
||||
bottom_right.y = bottom_left.y = _cairo_fixed_to_double (fill_extents.p2.y);
|
||||
} else {
|
||||
RefPtr<IDXGISurface> surf;
|
||||
d2dsurf->surface->QueryInterface(&surf);
|
||||
DXGI_SURFACE_DESC desc;
|
||||
surf->GetDesc(&desc);
|
||||
|
||||
top_left.x = bottom_left.x = 0;
|
||||
top_left.y = top_right.y = 0;
|
||||
top_right.x = bottom_right.x = desc.Width;
|
||||
bottom_right.y = bottom_left.y = desc.Height;
|
||||
}
|
||||
|
||||
// Calculate the repeat count needed;
|
||||
cairo_point_double_t top_left, top_right, bottom_left, bottom_right;
|
||||
top_left.x = bottom_left.x = top_left.y = top_right.y = 0;
|
||||
top_right.x = bottom_right.x = desc.Width;
|
||||
bottom_right.y = bottom_left.y = desc.Height;
|
||||
// Transform the corners of our surface to pattern space.
|
||||
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &top_left.x, &top_left.y);
|
||||
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &top_right.x, &top_right.y);
|
||||
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_left.x, &bottom_left.y);
|
||||
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_right.x, &top_left.y);
|
||||
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_right.x, &bottom_right.y);
|
||||
|
||||
cairo_point_double_t u;
|
||||
// Unit vector of the gradient direction.
|
||||
@ -1706,7 +1718,8 @@ _cairo_d2d_create_linear_gradient_brush(cairo_d2d_surface_t *d2dsurf,
|
||||
* \return A brush object
|
||||
*/
|
||||
static RefPtr<ID2D1Brush>
|
||||
_cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
|
||||
_cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
|
||||
cairo_path_fixed_t *fill_path,
|
||||
const cairo_pattern_t *pattern,
|
||||
bool unique = false)
|
||||
{
|
||||
@ -1734,7 +1747,7 @@ _cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
|
||||
} else if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR) {
|
||||
cairo_linear_pattern_t *source_pattern =
|
||||
(cairo_linear_pattern_t*)pattern;
|
||||
return _cairo_d2d_create_linear_gradient_brush(d2dsurf, source_pattern);
|
||||
return _cairo_d2d_create_linear_gradient_brush(d2dsurf, fill_path, source_pattern);
|
||||
} else if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL) {
|
||||
cairo_radial_pattern_t *source_pattern =
|
||||
(cairo_radial_pattern_t*)pattern;
|
||||
@ -3233,7 +3246,7 @@ _cairo_d2d_paint(void *surface,
|
||||
|
||||
target_rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
|
||||
|
||||
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
|
||||
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf, NULL,
|
||||
source);
|
||||
|
||||
if (!brush) {
|
||||
@ -3354,7 +3367,7 @@ _cairo_d2d_mask(void *surface,
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf, source);
|
||||
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf, NULL, source);
|
||||
if (!brush) {
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
@ -3394,7 +3407,7 @@ _cairo_d2d_mask(void *surface,
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
RefPtr<ID2D1Brush> opacityBrush = _cairo_d2d_create_brush_for_pattern(d2dsurf, mask, true);
|
||||
RefPtr<ID2D1Brush> opacityBrush = _cairo_d2d_create_brush_for_pattern(d2dsurf, NULL, mask, true);
|
||||
if (!opacityBrush) {
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
@ -3480,7 +3493,7 @@ _cairo_d2d_stroke(void *surface,
|
||||
transformed = false;
|
||||
}
|
||||
|
||||
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
|
||||
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf, NULL,
|
||||
source);
|
||||
if (!brush) {
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
@ -3607,7 +3620,7 @@ _cairo_d2d_fill(void *surface,
|
||||
float x2 = _cairo_fixed_to_float(box.p2.x);
|
||||
float y2 = _cairo_fixed_to_float(box.p2.y);
|
||||
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
|
||||
source);
|
||||
path, source);
|
||||
if (!brush) {
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
@ -3621,7 +3634,7 @@ _cairo_d2d_fill(void *surface,
|
||||
RefPtr<ID2D1Geometry> d2dpath = _cairo_d2d_create_path_geometry_for_path(path, fill_rule, D2D1_FIGURE_BEGIN_FILLED);
|
||||
|
||||
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
|
||||
source);
|
||||
path, source);
|
||||
if (!brush) {
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
@ -4143,7 +4156,7 @@ _cairo_dwrite_show_glyphs_on_d2d_surface(void *surface,
|
||||
fontArea.height = bounds.bottom - bounds.top;
|
||||
}
|
||||
|
||||
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(dst,
|
||||
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(dst, NULL,
|
||||
source);
|
||||
|
||||
if (!brush) {
|
||||
|
271
gfx/cairo/d2d-repeating-gradients.patch
Normal file
271
gfx/cairo/d2d-repeating-gradients.patch
Normal file
@ -0,0 +1,271 @@
|
||||
From: Robert O'Callahan <robert@ocallahan.org>
|
||||
Bug 768775. Improve the precision of the calculation of the number of stops that need to be added to handle 'repeat' and 'reflect', when we're filling a path. r=bas
|
||||
|
||||
diff --git a/gfx/cairo/cairo/src/cairo-d2d-surface.cpp b/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
|
||||
--- a/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
|
||||
+++ b/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
|
||||
@@ -1411,17 +1411,17 @@ static RefPtr<ID2D1Brush>
|
||||
|
||||
gradient_center.x = _cairo_fixed_to_float(source_pattern->c1.x);
|
||||
gradient_center.y = _cairo_fixed_to_float(source_pattern->c1.y);
|
||||
|
||||
// Transform surface corners into pattern coordinates.
|
||||
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &top_left.x, &top_left.y);
|
||||
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &top_right.x, &top_right.y);
|
||||
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_left.x, &bottom_left.y);
|
||||
- cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_right.x, &top_left.y);
|
||||
+ cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_right.x, &bottom_right.y);
|
||||
|
||||
// Find the corner furthest away from the gradient center in pattern space.
|
||||
double largest = MAX(_cairo_d2d_point_dist(top_left, gradient_center), _cairo_d2d_point_dist(top_right, gradient_center));
|
||||
largest = MAX(largest, _cairo_d2d_point_dist(bottom_left, gradient_center));
|
||||
largest = MAX(largest, _cairo_d2d_point_dist(bottom_right, gradient_center));
|
||||
|
||||
unsigned int minSize = (unsigned int)ceil(largest);
|
||||
|
||||
@@ -1531,16 +1531,17 @@ static RefPtr<ID2D1Brush>
|
||||
stopCollection,
|
||||
&brush);
|
||||
delete [] stops;
|
||||
return brush;
|
||||
}
|
||||
|
||||
static RefPtr<ID2D1Brush>
|
||||
_cairo_d2d_create_linear_gradient_brush(cairo_d2d_surface_t *d2dsurf,
|
||||
+ cairo_path_fixed_t *fill_path,
|
||||
cairo_linear_pattern_t *source_pattern)
|
||||
{
|
||||
if (source_pattern->p1.x == source_pattern->p2.x &&
|
||||
source_pattern->p1.y == source_pattern->p2.y) {
|
||||
// Cairo behavior in this situation is to draw a solid color the size of the last stop.
|
||||
RefPtr<ID2D1SolidColorBrush> brush;
|
||||
d2dsurf->rt->CreateSolidColorBrush(
|
||||
_cairo_d2d_color_from_cairo_color_stop(source_pattern->base.stops[source_pattern->base.n_stops - 1].color),
|
||||
@@ -1564,35 +1565,46 @@ static RefPtr<ID2D1Brush>
|
||||
p1.x = _cairo_fixed_to_float(source_pattern->p1.x);
|
||||
p1.y = _cairo_fixed_to_float(source_pattern->p1.y);
|
||||
p2.x = _cairo_fixed_to_float(source_pattern->p2.x);
|
||||
p2.y = _cairo_fixed_to_float(source_pattern->p2.y);
|
||||
|
||||
D2D1_GRADIENT_STOP *stops;
|
||||
int num_stops = source_pattern->base.n_stops;
|
||||
if (source_pattern->base.base.extend == CAIRO_EXTEND_REPEAT || source_pattern->base.base.extend == CAIRO_EXTEND_REFLECT) {
|
||||
-
|
||||
- RefPtr<IDXGISurface> surf;
|
||||
- d2dsurf->surface->QueryInterface(&surf);
|
||||
- DXGI_SURFACE_DESC desc;
|
||||
- surf->GetDesc(&desc);
|
||||
-
|
||||
// Get this when the points are not transformed yet.
|
||||
double gradient_length = _cairo_d2d_point_dist(p1, p2);
|
||||
-
|
||||
- // Calculate the repeat count needed;
|
||||
- cairo_point_double_t top_left, top_right, bottom_left, bottom_right;
|
||||
- top_left.x = bottom_left.x = top_left.y = top_right.y = 0;
|
||||
- top_right.x = bottom_right.x = desc.Width;
|
||||
- bottom_right.y = bottom_left.y = desc.Height;
|
||||
+ cairo_point_double_t top_left, top_right, bottom_left, bottom_right;
|
||||
+
|
||||
+ if (fill_path) {
|
||||
+ // Calculate the repeat count needed;
|
||||
+ cairo_box_t fill_extents;
|
||||
+ _cairo_path_fixed_extents (fill_path, &fill_extents);
|
||||
+
|
||||
+ top_left.x = bottom_left.x = _cairo_fixed_to_double (fill_extents.p1.x);
|
||||
+ top_left.y = top_right.y = _cairo_fixed_to_double (fill_extents.p1.y);
|
||||
+ top_right.x = bottom_right.x = _cairo_fixed_to_double (fill_extents.p2.x);
|
||||
+ bottom_right.y = bottom_left.y = _cairo_fixed_to_double (fill_extents.p2.y);
|
||||
+ } else {
|
||||
+ RefPtr<IDXGISurface> surf;
|
||||
+ d2dsurf->surface->QueryInterface(&surf);
|
||||
+ DXGI_SURFACE_DESC desc;
|
||||
+ surf->GetDesc(&desc);
|
||||
+
|
||||
+ top_left.x = bottom_left.x = 0;
|
||||
+ top_left.y = top_right.y = 0;
|
||||
+ top_right.x = bottom_right.x = desc.Width;
|
||||
+ bottom_right.y = bottom_left.y = desc.Height;
|
||||
+ }
|
||||
+
|
||||
// Transform the corners of our surface to pattern space.
|
||||
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &top_left.x, &top_left.y);
|
||||
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &top_right.x, &top_right.y);
|
||||
cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_left.x, &bottom_left.y);
|
||||
- cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_right.x, &top_left.y);
|
||||
+ cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_right.x, &bottom_right.y);
|
||||
|
||||
cairo_point_double_t u;
|
||||
// Unit vector of the gradient direction.
|
||||
u = _cairo_d2d_subtract_point(p2, p1);
|
||||
_cairo_d2d_normalize_point(&u);
|
||||
|
||||
// (corner - p1) . u = |corner - p1| cos(a) where a is the angle between the two vectors.
|
||||
// Coincidentally |corner - p1| cos(a) is actually also the distance our gradient needs to cover since
|
||||
@@ -1701,17 +1713,18 @@ static RefPtr<ID2D1Brush>
|
||||
* \param d2dsurf Surface to create a brush for
|
||||
* \param pattern The pattern to create a brush for
|
||||
* \param unique We cache the bitmap/color brush for speed. If this
|
||||
* needs a brush that is unique (i.e. when more than one is needed),
|
||||
* this will make the function return a seperate brush.
|
||||
* \return A brush object
|
||||
*/
|
||||
static RefPtr<ID2D1Brush>
|
||||
-_cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
|
||||
+_cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
|
||||
+ cairo_path_fixed_t *fill_path,
|
||||
const cairo_pattern_t *pattern,
|
||||
bool unique = false)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
|
||||
cairo_solid_pattern_t *sourcePattern =
|
||||
(cairo_solid_pattern_t*)pattern;
|
||||
@@ -1729,17 +1742,17 @@ static RefPtr<ID2D1Brush>
|
||||
d2dsurf->solidColorBrush->SetColor(color);
|
||||
}
|
||||
return d2dsurf->solidColorBrush;
|
||||
}
|
||||
|
||||
} else if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR) {
|
||||
cairo_linear_pattern_t *source_pattern =
|
||||
(cairo_linear_pattern_t*)pattern;
|
||||
- return _cairo_d2d_create_linear_gradient_brush(d2dsurf, source_pattern);
|
||||
+ return _cairo_d2d_create_linear_gradient_brush(d2dsurf, fill_path, source_pattern);
|
||||
} else if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL) {
|
||||
cairo_radial_pattern_t *source_pattern =
|
||||
(cairo_radial_pattern_t*)pattern;
|
||||
return _cairo_d2d_create_radial_gradient_brush(d2dsurf, source_pattern);
|
||||
} else if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
|
||||
cairo_matrix_t mat = pattern->matrix;
|
||||
cairo_matrix_invert(&mat);
|
||||
|
||||
@@ -3228,17 +3241,17 @@ static cairo_int_status_t
|
||||
|
||||
if (unlikely(status))
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
target_rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
|
||||
|
||||
- RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
|
||||
+ RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf, NULL,
|
||||
source);
|
||||
|
||||
if (!brush) {
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
D2D1_SIZE_F size = target_rt->GetSize();
|
||||
target_rt->FillRectangle(D2D1::RectF((FLOAT)0,
|
||||
@@ -3349,17 +3362,17 @@ static cairo_int_status_t
|
||||
source->filter,
|
||||
solidAlphaValue);
|
||||
if (rv != CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf, source);
|
||||
+ RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf, NULL, source);
|
||||
if (!brush) {
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
RefPtr<ID2D1RenderTarget> target_rt = d2dsurf->rt;
|
||||
#ifndef ALWAYS_MANUAL_COMPOSITE
|
||||
if (op != CAIRO_OPERATOR_OVER) {
|
||||
#endif
|
||||
@@ -3389,17 +3402,17 @@ static cairo_int_status_t
|
||||
brush->SetOpacity(1.0);
|
||||
|
||||
if (target_rt.get() != d2dsurf->rt.get()) {
|
||||
return _cairo_d2d_blend_temp_surface(d2dsurf, op, target_rt, clip);
|
||||
}
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
- RefPtr<ID2D1Brush> opacityBrush = _cairo_d2d_create_brush_for_pattern(d2dsurf, mask, true);
|
||||
+ RefPtr<ID2D1Brush> opacityBrush = _cairo_d2d_create_brush_for_pattern(d2dsurf, NULL, mask, true);
|
||||
if (!opacityBrush) {
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (!d2dsurf->maskLayer) {
|
||||
d2dsurf->rt->CreateLayer(&d2dsurf->maskLayer);
|
||||
}
|
||||
target_rt->PushLayer(D2D1::LayerParameters(D2D1::InfiniteRect(),
|
||||
@@ -3475,17 +3488,17 @@ static cairo_int_status_t
|
||||
D2D1_FIGURE_BEGIN_FILLED);
|
||||
|
||||
bool transformed = true;
|
||||
|
||||
if (_cairo_matrix_is_identity(ctm)) {
|
||||
transformed = false;
|
||||
}
|
||||
|
||||
- RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
|
||||
+ RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf, NULL,
|
||||
source);
|
||||
if (!brush) {
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
D2D1::Matrix3x2F mat;
|
||||
if (transformed) {
|
||||
// If we are transformed we will draw the geometry multiplied by the
|
||||
@@ -3602,31 +3615,31 @@ static cairo_int_status_t
|
||||
}
|
||||
|
||||
if (is_box) {
|
||||
float x1 = _cairo_fixed_to_float(box.p1.x);
|
||||
float y1 = _cairo_fixed_to_float(box.p1.y);
|
||||
float x2 = _cairo_fixed_to_float(box.p2.x);
|
||||
float y2 = _cairo_fixed_to_float(box.p2.y);
|
||||
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
|
||||
- source);
|
||||
+ path, source);
|
||||
if (!brush) {
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
target_rt->FillRectangle(D2D1::RectF(x1,
|
||||
y1,
|
||||
x2,
|
||||
y2),
|
||||
brush);
|
||||
} else {
|
||||
RefPtr<ID2D1Geometry> d2dpath = _cairo_d2d_create_path_geometry_for_path(path, fill_rule, D2D1_FIGURE_BEGIN_FILLED);
|
||||
|
||||
RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
|
||||
- source);
|
||||
+ path, source);
|
||||
if (!brush) {
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
target_rt->FillGeometry(d2dpath, brush);
|
||||
}
|
||||
|
||||
if (target_rt.get() != d2dsurf->rt.get()) {
|
||||
double x1, y1, x2, y2;
|
||||
@@ -4138,17 +4151,17 @@ static cairo_int_status_t
|
||||
DWRITE_TEXTURE_ALIASED_1x1 : DWRITE_TEXTURE_CLEARTYPE_3x1,
|
||||
&bounds);
|
||||
fontArea.x = bounds.left;
|
||||
fontArea.y = bounds.top;
|
||||
fontArea.width = bounds.right - bounds.left;
|
||||
fontArea.height = bounds.bottom - bounds.top;
|
||||
}
|
||||
|
||||
- RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(dst,
|
||||
+ RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(dst, NULL,
|
||||
source);
|
||||
|
||||
if (!brush) {
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (transform) {
|
||||
D2D1::Matrix3x2F mat_inverse = _cairo_d2d_matrix_from_matrix(&dwritesf->mat_inverse);
|
@ -888,10 +888,10 @@ SharedTextureHandle
|
||||
GLContextEGL::CreateSharedHandle(TextureImage::TextureShareType aType)
|
||||
{
|
||||
if (aType != TextureImage::ThreadShared)
|
||||
return nsnull;
|
||||
return 0;
|
||||
|
||||
if (!mShareWithEGLImage)
|
||||
return nsnull;
|
||||
return 0;
|
||||
|
||||
MakeCurrent();
|
||||
GLuint texture = 0;
|
||||
@ -903,7 +903,7 @@ GLContextEGL::CreateSharedHandle(TextureImage::TextureShareType aType)
|
||||
if (!tex->CreateEGLImage()) {
|
||||
NS_ERROR("EGLImage creation for EGLTextureWrapper failed");
|
||||
ReleaseSharedHandle(aType, (SharedTextureHandle)tex);
|
||||
return nsnull;
|
||||
return 0;
|
||||
}
|
||||
// Raw pointer shared across threads
|
||||
return (SharedTextureHandle)tex;
|
||||
@ -917,35 +917,35 @@ GLContextEGL::CreateSharedHandle(TextureImage::TextureShareType aType,
|
||||
// Both EGLImage and SurfaceTexture only support ThreadShared currently, but
|
||||
// it's possible to make SurfaceTexture work across processes. We should do that.
|
||||
if (aType != TextureImage::ThreadShared)
|
||||
return nsnull;
|
||||
return 0;
|
||||
|
||||
switch (aBufferType) {
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
case SharedTextureBufferType::SurfaceTexture:
|
||||
if (!IsExtensionSupported(GLContext::OES_EGL_image_external)) {
|
||||
NS_WARNING("Missing GL_OES_EGL_image_external");
|
||||
return nsnull;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (SharedTextureHandle) new SurfaceTextureWrapper(reinterpret_cast<nsSurfaceTexture*>(aBuffer));
|
||||
#endif
|
||||
case SharedTextureBufferType::TextureID: {
|
||||
if (!mShareWithEGLImage)
|
||||
return nsnull;
|
||||
return 0;
|
||||
|
||||
GLuint texture = (GLuint)aBuffer;
|
||||
EGLTextureWrapper* tex = new EGLTextureWrapper(this, texture, false);
|
||||
if (!tex->CreateEGLImage()) {
|
||||
NS_ERROR("EGLImage creation for EGLTextureWrapper failed");
|
||||
delete tex;
|
||||
return nsnull;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (SharedTextureHandle)tex;
|
||||
}
|
||||
default:
|
||||
NS_ERROR("Unknown shared texture buffer type");
|
||||
return nsnull;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "nsPrintfCString.h"
|
||||
#include "mozilla/Util.h"
|
||||
#include "LayerSorter.h"
|
||||
#include "AnimationCommon.h"
|
||||
|
||||
using namespace mozilla::layers;
|
||||
using namespace mozilla::gfx;
|
||||
@ -220,6 +221,245 @@ LayerManager::CreateAsynchronousImageContainer()
|
||||
//--------------------------------------------------
|
||||
// Layer
|
||||
|
||||
Layer::Layer(LayerManager* aManager, void* aImplData) :
|
||||
mManager(aManager),
|
||||
mParent(nsnull),
|
||||
mNextSibling(nsnull),
|
||||
mPrevSibling(nsnull),
|
||||
mImplData(aImplData),
|
||||
mMaskLayer(nsnull),
|
||||
mXScale(1.0f),
|
||||
mYScale(1.0f),
|
||||
mOpacity(1.0),
|
||||
mContentFlags(0),
|
||||
mUseClipRect(false),
|
||||
mUseTileSourceRect(false),
|
||||
mIsFixedPosition(false),
|
||||
mDebugColorIndex(0)
|
||||
{}
|
||||
|
||||
Layer::~Layer()
|
||||
{}
|
||||
|
||||
void
|
||||
Layer::AddAnimation(const Animation& aAnimation)
|
||||
{
|
||||
if (!AsShadowableLayer() || !AsShadowableLayer()->HasShadow())
|
||||
return;
|
||||
|
||||
MOZ_ASSERT(aAnimation.segments().Length() >= 1);
|
||||
|
||||
mAnimations.AppendElement(aAnimation);
|
||||
Mutated();
|
||||
}
|
||||
|
||||
void
|
||||
Layer::ClearAnimations()
|
||||
{
|
||||
mAnimations.Clear();
|
||||
mAnimationData.Clear();
|
||||
Mutated();
|
||||
}
|
||||
|
||||
static nsCSSValueList*
|
||||
CreateCSSValueList(const InfallibleTArray<TransformFunction>& aFunctions)
|
||||
{
|
||||
nsAutoPtr<nsCSSValueList> result;
|
||||
nsCSSValueList** resultTail = getter_Transfers(result);
|
||||
for (PRUint32 i = 0; i < aFunctions.Length(); i++) {
|
||||
nsRefPtr<nsCSSValue::Array> arr;
|
||||
switch (aFunctions[i].type()) {
|
||||
case TransformFunction::TRotationX:
|
||||
{
|
||||
float theta = aFunctions[i].get_RotationX().radians();
|
||||
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_rotatex, resultTail);
|
||||
arr->Item(1).SetFloatValue(theta, eCSSUnit_Radian);
|
||||
break;
|
||||
}
|
||||
case TransformFunction::TRotationY:
|
||||
{
|
||||
float theta = aFunctions[i].get_RotationY().radians();
|
||||
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_rotatey, resultTail);
|
||||
arr->Item(1).SetFloatValue(theta, eCSSUnit_Radian);
|
||||
break;
|
||||
}
|
||||
case TransformFunction::TRotationZ:
|
||||
{
|
||||
float theta = aFunctions[i].get_RotationZ().radians();
|
||||
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_rotatez, resultTail);
|
||||
arr->Item(1).SetFloatValue(theta, eCSSUnit_Radian);
|
||||
break;
|
||||
}
|
||||
case TransformFunction::TRotation:
|
||||
{
|
||||
float theta = aFunctions[i].get_Rotation().radians();
|
||||
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_rotate, resultTail);
|
||||
arr->Item(1).SetFloatValue(theta, eCSSUnit_Radian);
|
||||
break;
|
||||
}
|
||||
case TransformFunction::TRotation3D:
|
||||
{
|
||||
float x = aFunctions[i].get_Rotation3D().x();
|
||||
float y = aFunctions[i].get_Rotation3D().y();
|
||||
float z = aFunctions[i].get_Rotation3D().z();
|
||||
float theta = aFunctions[i].get_Rotation3D().radians();
|
||||
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_rotate3d, resultTail);
|
||||
arr->Item(1).SetFloatValue(x, eCSSUnit_Number);
|
||||
arr->Item(2).SetFloatValue(y, eCSSUnit_Number);
|
||||
arr->Item(3).SetFloatValue(z, eCSSUnit_Number);
|
||||
arr->Item(4).SetFloatValue(theta, eCSSUnit_Radian);
|
||||
break;
|
||||
}
|
||||
case TransformFunction::TScale:
|
||||
{
|
||||
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_scale3d, resultTail);
|
||||
arr->Item(1).SetFloatValue(aFunctions[i].get_Scale().x(), eCSSUnit_Number);
|
||||
arr->Item(2).SetFloatValue(aFunctions[i].get_Scale().y(), eCSSUnit_Number);
|
||||
arr->Item(3).SetFloatValue(aFunctions[i].get_Scale().z(), eCSSUnit_Number);
|
||||
break;
|
||||
}
|
||||
case TransformFunction::TTranslation:
|
||||
{
|
||||
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_translate3d, resultTail);
|
||||
arr->Item(1).SetFloatValue(aFunctions[i].get_Translation().x(), eCSSUnit_Pixel);
|
||||
arr->Item(2).SetFloatValue(aFunctions[i].get_Translation().y(), eCSSUnit_Pixel);
|
||||
arr->Item(3).SetFloatValue(aFunctions[i].get_Translation().z(), eCSSUnit_Pixel);
|
||||
break;
|
||||
}
|
||||
case TransformFunction::TSkewX:
|
||||
{
|
||||
float x = aFunctions[i].get_SkewX().x();
|
||||
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_skewx, resultTail);
|
||||
arr->Item(1).SetFloatValue(x, eCSSUnit_Number);
|
||||
break;
|
||||
}
|
||||
case TransformFunction::TSkewY:
|
||||
{
|
||||
float y = aFunctions[i].get_SkewY().y();
|
||||
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_skewy, resultTail);
|
||||
arr->Item(1).SetFloatValue(y, eCSSUnit_Number);
|
||||
break;
|
||||
}
|
||||
case TransformFunction::TTransformMatrix:
|
||||
{
|
||||
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_matrix3d, resultTail);
|
||||
const gfx3DMatrix& matrix = aFunctions[i].get_TransformMatrix().value();
|
||||
arr->Item(1).SetFloatValue(matrix._11, eCSSUnit_Number);
|
||||
arr->Item(2).SetFloatValue(matrix._12, eCSSUnit_Number);
|
||||
arr->Item(3).SetFloatValue(matrix._13, eCSSUnit_Number);
|
||||
arr->Item(4).SetFloatValue(matrix._14, eCSSUnit_Number);
|
||||
arr->Item(5).SetFloatValue(matrix._21, eCSSUnit_Number);
|
||||
arr->Item(6).SetFloatValue(matrix._22, eCSSUnit_Number);
|
||||
arr->Item(7).SetFloatValue(matrix._23, eCSSUnit_Number);
|
||||
arr->Item(8).SetFloatValue(matrix._24, eCSSUnit_Number);
|
||||
arr->Item(9).SetFloatValue(matrix._31, eCSSUnit_Number);
|
||||
arr->Item(10).SetFloatValue(matrix._32, eCSSUnit_Number);
|
||||
arr->Item(11).SetFloatValue(matrix._33, eCSSUnit_Number);
|
||||
arr->Item(12).SetFloatValue(matrix._34, eCSSUnit_Number);
|
||||
arr->Item(13).SetFloatValue(matrix._41, eCSSUnit_Number);
|
||||
arr->Item(14).SetFloatValue(matrix._42, eCSSUnit_Number);
|
||||
arr->Item(15).SetFloatValue(matrix._43, eCSSUnit_Number);
|
||||
arr->Item(16).SetFloatValue(matrix._44, eCSSUnit_Number);
|
||||
break;
|
||||
}
|
||||
case TransformFunction::TPerspective:
|
||||
{
|
||||
float perspective = aFunctions[i].get_Perspective().value();
|
||||
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_perspective, resultTail);
|
||||
arr->Item(1).SetFloatValue(perspective, eCSSUnit_Pixel);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
NS_ASSERTION(false, "All functions should be implemented?");
|
||||
}
|
||||
}
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
void
|
||||
Layer::SetAnimations(const AnimationArray& aAnimations)
|
||||
{
|
||||
mAnimations = aAnimations;
|
||||
mAnimationData.Clear();
|
||||
for (PRUint32 i = 0; i < mAnimations.Length(); i++) {
|
||||
AnimData data;
|
||||
InfallibleTArray<css::ComputedTimingFunction*>* functions =
|
||||
&data.mFunctions;
|
||||
nsTArray<AnimationSegment> segments = mAnimations.ElementAt(i).segments();
|
||||
for (PRUint32 j = 0; j < segments.Length(); j++) {
|
||||
TimingFunction tf = segments.ElementAt(j).sampleFn();
|
||||
css::ComputedTimingFunction* ctf = new css::ComputedTimingFunction();
|
||||
switch (tf.type()) {
|
||||
case TimingFunction::TCubicBezierFunction: {
|
||||
CubicBezierFunction cbf = tf.get_CubicBezierFunction();
|
||||
ctf->Init(nsTimingFunction(cbf.x1(), cbf.y1(), cbf.x2(), cbf.y2()));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
NS_ASSERTION(tf.type() == TimingFunction::TStepFunction,
|
||||
"Function must be bezier or step");
|
||||
StepFunction sf = tf.get_StepFunction();
|
||||
nsTimingFunction::Type type = sf.type() == 1 ? nsTimingFunction::StepStart
|
||||
: nsTimingFunction::StepEnd;
|
||||
ctf->Init(nsTimingFunction(type, sf.steps()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
functions->AppendElement(ctf);
|
||||
}
|
||||
|
||||
// Precompute the nsStyleAnimation::Values that we need if this is a transform
|
||||
// animation.
|
||||
InfallibleTArray<nsStyleAnimation::Value>* startValues =
|
||||
&data.mStartValues;
|
||||
InfallibleTArray<nsStyleAnimation::Value>* endValues =
|
||||
&data.mEndValues;
|
||||
for (PRUint32 j = 0; j < mAnimations[i].segments().Length(); j++) {
|
||||
const AnimationSegment& segment = mAnimations[i].segments()[j];
|
||||
if (segment.endState().type() == Animatable::TArrayOfTransformFunction) {
|
||||
const InfallibleTArray<TransformFunction>& startFunctions =
|
||||
segment.startState().get_ArrayOfTransformFunction();
|
||||
nsStyleAnimation::Value startValue;
|
||||
nsCSSValueList* startList;
|
||||
if (startFunctions.Length() > 0) {
|
||||
startList = CreateCSSValueList(startFunctions);
|
||||
} else {
|
||||
startList = new nsCSSValueList();
|
||||
startList->mValue.SetNoneValue();
|
||||
}
|
||||
startValue.SetAndAdoptCSSValueListValue(startList, nsStyleAnimation::eUnit_Transform);
|
||||
startValues->AppendElement(startValue);
|
||||
|
||||
const InfallibleTArray<TransformFunction>& endFunctions =
|
||||
segment.endState().get_ArrayOfTransformFunction();
|
||||
nsStyleAnimation::Value endValue;
|
||||
nsCSSValueList* endList;
|
||||
if (endFunctions.Length() > 0) {
|
||||
endList = CreateCSSValueList(endFunctions);
|
||||
} else {
|
||||
endList = new nsCSSValueList();
|
||||
endList->mValue.SetNoneValue();
|
||||
}
|
||||
endValue.SetAndAdoptCSSValueListValue(endList, nsStyleAnimation::eUnit_Transform);
|
||||
endValues->AppendElement(endValue);
|
||||
} else {
|
||||
NS_ASSERTION(segment.endState().type() == Animatable::TOpacity,
|
||||
"Unknown Animatable type");
|
||||
nsStyleAnimation::Value startValue;
|
||||
startValue.SetFloatValue(segment.startState().get_Opacity().value());
|
||||
startValues->AppendElement(startValue);
|
||||
|
||||
nsStyleAnimation::Value endValue;
|
||||
endValue.SetFloatValue(segment.endState().get_Opacity().value());
|
||||
endValues->AppendElement(endValue);
|
||||
}
|
||||
}
|
||||
mAnimationData.AppendElement(data);
|
||||
}
|
||||
|
||||
Mutated();
|
||||
}
|
||||
|
||||
bool
|
||||
Layer::CanUseOpaqueSurface()
|
||||
{
|
||||
@ -304,7 +544,7 @@ Layer::SnapTransform(const gfx3DMatrix& aTransform,
|
||||
return result;
|
||||
}
|
||||
|
||||
nsIntRect
|
||||
nsIntRect
|
||||
Layer::CalculateScissorRect(const nsIntRect& aCurrentScissorRect,
|
||||
const gfxMatrix* aWorldTransform)
|
||||
{
|
||||
@ -361,21 +601,42 @@ Layer::CalculateScissorRect(const nsIntRect& aCurrentScissorRect,
|
||||
return currentClip.Intersect(scissor);
|
||||
}
|
||||
|
||||
const gfx3DMatrix&
|
||||
const gfx3DMatrix
|
||||
Layer::GetTransform()
|
||||
{
|
||||
gfx3DMatrix transform = mTransform;
|
||||
transform.Scale(mXScale, mYScale, 1);
|
||||
return transform;
|
||||
}
|
||||
|
||||
const gfx3DMatrix
|
||||
Layer::GetLocalTransform()
|
||||
{
|
||||
gfx3DMatrix transform;
|
||||
if (ShadowLayer* shadow = AsShadowLayer()) {
|
||||
transform = shadow->GetShadowTransform();
|
||||
} else {
|
||||
transform = mTransform;
|
||||
}
|
||||
transform.Scale(mXScale, mYScale, 1);
|
||||
return transform;
|
||||
}
|
||||
|
||||
const float
|
||||
Layer::GetLocalOpacity()
|
||||
{
|
||||
if (ShadowLayer* shadow = AsShadowLayer())
|
||||
return shadow->GetShadowTransform();
|
||||
return mTransform;
|
||||
return shadow->GetShadowOpacity();
|
||||
return mOpacity;
|
||||
}
|
||||
|
||||
float
|
||||
Layer::GetEffectiveOpacity()
|
||||
{
|
||||
float opacity = GetOpacity();
|
||||
float opacity = GetLocalOpacity();
|
||||
for (ContainerLayer* c = GetParent(); c && !c->UseIntermediateSurface();
|
||||
c = c->GetParent()) {
|
||||
opacity *= c->GetOpacity();
|
||||
opacity *= c->GetLocalOpacity();
|
||||
}
|
||||
return opacity;
|
||||
}
|
||||
@ -384,14 +645,15 @@ void
|
||||
Layer::ComputeEffectiveTransformForMaskLayer(const gfx3DMatrix& aTransformToSurface)
|
||||
{
|
||||
if (mMaskLayer) {
|
||||
mMaskLayer->mEffectiveTransform = aTransformToSurface;
|
||||
|
||||
#ifdef DEBUG
|
||||
gfxMatrix maskTranslation;
|
||||
bool maskIs2D = mMaskLayer->GetTransform().CanDraw2D(&maskTranslation);
|
||||
NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
|
||||
#endif
|
||||
mMaskLayer->mEffectiveTransform.PreMultiply(mMaskLayer->GetTransform());
|
||||
mMaskLayer->mEffectiveTransform = aTransformToSurface;
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
gfxMatrix maskTranslation;
|
||||
bool maskIs2D = mMaskLayer->GetTransform().CanDraw2D(&maskTranslation);
|
||||
NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
|
||||
#endif
|
||||
mMaskLayer->mEffectiveTransform.PreMultiply(mMaskLayer->GetTransform());
|
||||
}
|
||||
}
|
||||
|
||||
@ -790,7 +1052,7 @@ void
|
||||
LayerManager::Dump(FILE* aFile, const char* aPrefix)
|
||||
{
|
||||
FILE* file = FILEOrDefault(aFile);
|
||||
|
||||
|
||||
fprintf(file, "<ul><li><a ");
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
WriteSnapshotLinkToDumpFile(this, file);
|
||||
@ -807,7 +1069,7 @@ LayerManager::Dump(FILE* aFile, const char* aPrefix)
|
||||
fprintf(file, "%s(null)</li></ul>", pfx.get());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
fprintf(file, "<ul>");
|
||||
GetRoot()->Dump(file, pfx.get());
|
||||
fprintf(file, "</ul></li></ul>");
|
||||
@ -941,5 +1203,5 @@ LayerManager::PrintInfo(nsACString& aTo, const char* aPrefix)
|
||||
|
||||
PRLogModuleInfo* LayerManager::sLog;
|
||||
|
||||
} // namespace layers
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "gfxPattern.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsStyleAnimation.h"
|
||||
#include "LayersBackend.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
@ -43,8 +44,14 @@ namespace gl {
|
||||
class GLContext;
|
||||
}
|
||||
|
||||
namespace css {
|
||||
class ComputedTimingFunction;
|
||||
}
|
||||
|
||||
namespace layers {
|
||||
|
||||
class Animation;
|
||||
class CommonLayerAttributes;
|
||||
class Layer;
|
||||
class ThebesLayer;
|
||||
class ContainerLayer;
|
||||
@ -530,6 +537,13 @@ private:
|
||||
};
|
||||
|
||||
class ThebesLayer;
|
||||
typedef InfallibleTArray<Animation> AnimationArray;
|
||||
|
||||
struct AnimData {
|
||||
InfallibleTArray<nsStyleAnimation::Value> mStartValues;
|
||||
InfallibleTArray<nsStyleAnimation::Value> mEndValues;
|
||||
InfallibleTArray<mozilla::css::ComputedTimingFunction*> mFunctions;
|
||||
};
|
||||
|
||||
/**
|
||||
* A Layer represents anything that can be rendered onto a destination
|
||||
@ -551,7 +565,7 @@ public:
|
||||
TYPE_THEBES
|
||||
};
|
||||
|
||||
virtual ~Layer() {}
|
||||
virtual ~Layer();
|
||||
|
||||
/**
|
||||
* Returns the LayerManager this Layer belongs to. Note that the layer
|
||||
@ -702,12 +716,19 @@ public:
|
||||
* XXX Currently only transformations corresponding to 2D affine transforms
|
||||
* are supported.
|
||||
*/
|
||||
void SetTransform(const gfx3DMatrix& aMatrix)
|
||||
void SetBaseTransform(const gfx3DMatrix& aMatrix)
|
||||
{
|
||||
mTransform = aMatrix;
|
||||
Mutated();
|
||||
}
|
||||
|
||||
void SetScale(float aXScale, float aYScale)
|
||||
{
|
||||
mXScale = aXScale;
|
||||
mYScale = aYScale;
|
||||
Mutated();
|
||||
}
|
||||
|
||||
/**
|
||||
* CONSTRUCTION PHASE ONLY
|
||||
* A layer is "fixed position" when it draws content from a content
|
||||
@ -716,6 +737,14 @@ public:
|
||||
*/
|
||||
void SetIsFixedPosition(bool aFixedPosition) { mIsFixedPosition = aFixedPosition; }
|
||||
|
||||
// Call AddAnimation to add an animation to this layer from layout code.
|
||||
void AddAnimation(const Animation& aAnimation);
|
||||
// ClearAnimations clears animations on this layer.
|
||||
void ClearAnimations();
|
||||
// This is only called when the layer tree is updated. Do not call this from
|
||||
// layout code. To add an animation to this layer, use AddAnimation.
|
||||
void SetAnimations(const AnimationArray& aAnimations);
|
||||
|
||||
/**
|
||||
* CONSTRUCTION PHASE ONLY
|
||||
* If a layer is "fixed position", this determines which point on the layer
|
||||
@ -735,11 +764,15 @@ public:
|
||||
Layer* GetPrevSibling() { return mPrevSibling; }
|
||||
virtual Layer* GetFirstChild() { return nsnull; }
|
||||
virtual Layer* GetLastChild() { return nsnull; }
|
||||
const gfx3DMatrix& GetTransform() { return mTransform; }
|
||||
const gfx3DMatrix GetTransform();
|
||||
const gfx3DMatrix& GetBaseTransform() { return mTransform; }
|
||||
float GetXScale() { return mXScale; }
|
||||
float GetYScale() { return mYScale; }
|
||||
bool GetIsFixedPosition() { return mIsFixedPosition; }
|
||||
gfxPoint GetFixedPositionAnchor() { return mAnchor; }
|
||||
Layer* GetMaskLayer() { return mMaskLayer; }
|
||||
|
||||
AnimationArray& GetAnimations() { return mAnimations; }
|
||||
InfallibleTArray<AnimData>& GetAnimationData() { return mAnimationData; }
|
||||
/**
|
||||
* DRAWING PHASE ONLY
|
||||
*
|
||||
@ -940,20 +973,7 @@ public:
|
||||
#endif
|
||||
|
||||
protected:
|
||||
Layer(LayerManager* aManager, void* aImplData) :
|
||||
mManager(aManager),
|
||||
mParent(nsnull),
|
||||
mNextSibling(nsnull),
|
||||
mPrevSibling(nsnull),
|
||||
mImplData(aImplData),
|
||||
mMaskLayer(nsnull),
|
||||
mOpacity(1.0),
|
||||
mContentFlags(0),
|
||||
mUseClipRect(false),
|
||||
mUseTileSourceRect(false),
|
||||
mIsFixedPosition(false),
|
||||
mDebugColorIndex(0)
|
||||
{}
|
||||
Layer(LayerManager* aManager, void* aImplData);
|
||||
|
||||
void Mutated() { mManager->Mutated(this); }
|
||||
|
||||
@ -968,7 +988,13 @@ protected:
|
||||
* Returns the local transform for this layer: either mTransform or,
|
||||
* for shadow layers, GetShadowTransform()
|
||||
*/
|
||||
const gfx3DMatrix& GetLocalTransform();
|
||||
const gfx3DMatrix GetLocalTransform();
|
||||
|
||||
/**
|
||||
* Returns the local opacity for this layer: either mOpacity or,
|
||||
* for shadow layers, GetShadowOpacity()
|
||||
*/
|
||||
const float GetLocalOpacity();
|
||||
|
||||
/**
|
||||
* Computes a tweaked version of aTransform that snaps a point or a rectangle
|
||||
@ -994,7 +1020,11 @@ protected:
|
||||
gfx::UserData mUserData;
|
||||
nsIntRegion mVisibleRegion;
|
||||
gfx3DMatrix mTransform;
|
||||
float mXScale;
|
||||
float mYScale;
|
||||
gfx3DMatrix mEffectiveTransform;
|
||||
AnimationArray mAnimations;
|
||||
InfallibleTArray<AnimData> mAnimationData;
|
||||
float mOpacity;
|
||||
nsIntRect mClipRect;
|
||||
nsIntRect mTileSourceRect;
|
||||
|
@ -31,16 +31,18 @@ EXPORTS = \
|
||||
BasicLayers.h \
|
||||
BasicTiledThebesLayer.h \
|
||||
BasicImplData.h \
|
||||
CompositorParent.h \
|
||||
ImageLayers.h \
|
||||
Layers.h \
|
||||
LayersBackend.h \
|
||||
LayerManagerOGLShaders.h \
|
||||
LayerManagerOGL.h \
|
||||
LayerManagerOGLProgram.h \
|
||||
ReadbackLayer.h \
|
||||
LayerSorter.h \
|
||||
TexturePoolOGL.h \
|
||||
ReadbackLayer.h \
|
||||
ShadowLayersManager.h \
|
||||
SharedTextureImage.h \
|
||||
TexturePoolOGL.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "BasicThebesLayer.h"
|
||||
#include "BasicContainerLayer.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
@ -132,7 +133,8 @@ BasicLayerManager::~BasicLayerManager()
|
||||
|
||||
void
|
||||
BasicLayerManager::SetDefaultTarget(gfxContext* aContext,
|
||||
BufferMode aDoubleBuffering)
|
||||
BufferMode aDoubleBuffering,
|
||||
ScreenRotation aRotation)
|
||||
{
|
||||
NS_ASSERTION(!InTransaction(),
|
||||
"Must set default target outside transaction");
|
||||
@ -922,7 +924,7 @@ BasicLayerManager::CreateReadbackLayer()
|
||||
}
|
||||
|
||||
BasicShadowLayerManager::BasicShadowLayerManager(nsIWidget* aWidget) :
|
||||
BasicLayerManager(aWidget)
|
||||
BasicLayerManager(aWidget), mTargetRotation(ROTATION_0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(BasicShadowLayerManager);
|
||||
}
|
||||
@ -942,6 +944,18 @@ BasicShadowLayerManager::GetMaxTextureSize() const
|
||||
return PR_INT32_MAX;
|
||||
}
|
||||
|
||||
void
|
||||
BasicShadowLayerManager::SetDefaultTarget(gfxContext* aContext,
|
||||
BufferMode aDoubleBuffering,
|
||||
ScreenRotation aRotation)
|
||||
{
|
||||
BasicLayerManager::SetDefaultTarget(aContext, aDoubleBuffering, aRotation);
|
||||
mTargetRotation = aRotation;
|
||||
if (mWidget) {
|
||||
mTargetBounds = mWidget->GetNaturalBounds();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BasicShadowLayerManager::SetRoot(Layer* aLayer)
|
||||
{
|
||||
@ -981,7 +995,7 @@ BasicShadowLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
|
||||
// don't signal a new transaction to ShadowLayerForwarder. Carry on adding
|
||||
// to the previous transaction.
|
||||
if (HasShadowManager()) {
|
||||
ShadowLayerForwarder::BeginTransaction();
|
||||
ShadowLayerForwarder::BeginTransaction(mTargetBounds, mTargetRotation);
|
||||
|
||||
// If we have a non-default target, we need to let our shadow manager draw
|
||||
// to it. This will happen at the end of the transaction.
|
||||
|
@ -10,11 +10,11 @@
|
||||
|
||||
#include "gfxContext.h"
|
||||
#include "gfxCachedTempSurface.h"
|
||||
#include "mozilla/layers/ShadowLayers.h"
|
||||
#include "mozilla/WidgetUtils.h"
|
||||
#include "nsAutoRef.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "mozilla/layers/ShadowLayers.h"
|
||||
|
||||
class nsIWidget;
|
||||
|
||||
namespace mozilla {
|
||||
@ -80,7 +80,8 @@ public:
|
||||
BUFFER_NONE,
|
||||
BUFFER_BUFFERED
|
||||
};
|
||||
void SetDefaultTarget(gfxContext* aContext, BufferMode aDoubleBuffering);
|
||||
virtual void SetDefaultTarget(gfxContext* aContext, BufferMode aDoubleBuffering,
|
||||
ScreenRotation aRotation);
|
||||
gfxContext* GetDefaultTarget() { return mDefaultTarget; }
|
||||
|
||||
nsIWidget* GetRetainerWidget() { return mWidget; }
|
||||
@ -221,6 +222,8 @@ public:
|
||||
|
||||
virtual PRInt32 GetMaxTextureSize() const;
|
||||
|
||||
virtual void SetDefaultTarget(gfxContext* aContext, BufferMode aDoubleBuffering,
|
||||
ScreenRotation aRotation) MOZ_OVERRIDE;
|
||||
virtual void BeginTransactionWithTarget(gfxContext* aTarget);
|
||||
virtual bool EndEmptyTransaction();
|
||||
virtual void EndTransaction(DrawThebesLayerCallback aCallback,
|
||||
@ -261,11 +264,20 @@ private:
|
||||
*/
|
||||
void ForwardTransaction();
|
||||
|
||||
// The bounds of |mTarget| in device pixels.
|
||||
nsIntRect mTargetBounds;
|
||||
|
||||
LayerRefArray mKeepAlive;
|
||||
|
||||
// Sometimes we draw to targets that don't natively support
|
||||
// landscape/portrait orientation. When we need to implement that
|
||||
// ourselves, |mTargetRotation| describes the induced transform we
|
||||
// need to apply when compositing content to our target.
|
||||
ScreenRotation mTargetRotation;
|
||||
|
||||
// Used to repeat the transaction right away (to avoid rebuilding
|
||||
// a display list) to support progressive drawing.
|
||||
bool mRepeatTransaction;
|
||||
|
||||
LayerRefArray mKeepAlive;
|
||||
};
|
||||
|
||||
class BasicShadowableThebesLayer;
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "ReadbackLayerD3D10.h"
|
||||
#include "ImageLayerD3D10.h"
|
||||
#include "mozilla/layers/PLayerChild.h"
|
||||
#include "mozilla/WidgetUtils.h"
|
||||
|
||||
#include "../d3d9/Nv3DVUtils.h"
|
||||
|
||||
@ -448,7 +449,6 @@ LayerManagerD3D10::CreateOptimalSurface(const gfxIntSize &aSize,
|
||||
|
||||
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aSize.width, aSize.height, 1, 1);
|
||||
desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
|
||||
desc.MiscFlags = D3D10_RESOURCE_MISC_GDI_COMPATIBLE;
|
||||
|
||||
HRESULT hr = device()->CreateTexture2D(&desc, NULL, getter_AddRefs(texture));
|
||||
|
||||
@ -729,7 +729,8 @@ LayerManagerD3D10::Render()
|
||||
if (mTarget) {
|
||||
PaintToTarget();
|
||||
} else if (mBackBuffer) {
|
||||
ShadowLayerForwarder::BeginTransaction();
|
||||
ShadowLayerForwarder::BeginTransaction(mWidget->GetNaturalBounds(),
|
||||
ROTATION_0);
|
||||
|
||||
nsIntRect contentRect = nsIntRect(0, 0, rect.width, rect.height);
|
||||
if (!mRootForShadowTree) {
|
||||
|
@ -470,7 +470,6 @@ ThebesLayerD3D10::CreateNewTextures(const gfxIntSize &aSize, SurfaceMode aMode)
|
||||
|
||||
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aSize.width, aSize.height, 1, 1);
|
||||
desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
|
||||
desc.MiscFlags = D3D10_RESOURCE_MISC_GDI_COMPATIBLE;
|
||||
HRESULT hr;
|
||||
|
||||
if (!mTexture) {
|
||||
|
@ -21,6 +21,15 @@
|
||||
#include "nsIWidget.h"
|
||||
#include "RenderTrace.h"
|
||||
#include "ShadowLayersParent.h"
|
||||
#include "BasicLayers.h"
|
||||
#include "LayerManagerOGL.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "RenderTrace.h"
|
||||
#include "nsStyleAnimation.h"
|
||||
#include "nsDisplayList.h"
|
||||
#include "AnimationCommon.h"
|
||||
#include "nsAnimationManager.h"
|
||||
|
||||
using namespace base;
|
||||
using namespace mozilla::ipc;
|
||||
@ -412,16 +421,23 @@ CompositorParent::Composite()
|
||||
return;
|
||||
}
|
||||
|
||||
Layer* aLayer = mLayerManager->GetRoot();
|
||||
AutoResolveRefLayers resolve(aLayer);
|
||||
Layer* layer = mLayerManager->GetRoot();
|
||||
AutoResolveRefLayers resolve(layer);
|
||||
|
||||
bool requestNextFrame = TransformShadowTree(mLastCompose);
|
||||
if (requestNextFrame) {
|
||||
ScheduleComposition();
|
||||
}
|
||||
|
||||
RenderTraceLayers(aLayer, "0000");
|
||||
RenderTraceLayers(layer, "0000");
|
||||
|
||||
if (LAYERS_OPENGL == mLayerManager->GetBackendType() &&
|
||||
!mTargetConfig.naturalBounds().IsEmpty()) {
|
||||
LayerManagerOGL* lm = static_cast<LayerManagerOGL*>(mLayerManager.get());
|
||||
lm->SetWorldTransform(
|
||||
ComputeGLTransformForRotation(mTargetConfig.naturalBounds(),
|
||||
mTargetConfig.rotation()));
|
||||
}
|
||||
mLayerManager->EndEmptyTransaction();
|
||||
|
||||
#ifdef COMPOSITOR_PERFORMANCE_WARNING
|
||||
@ -510,9 +526,10 @@ SetShadowProperties(Layer* aLayer)
|
||||
{
|
||||
// FIXME: Bug 717688 -- Do these updates in ShadowLayersParent::RecvUpdate.
|
||||
ShadowLayer* shadow = aLayer->AsShadowLayer();
|
||||
shadow->SetShadowTransform(aLayer->GetTransform());
|
||||
shadow->SetShadowTransform(aLayer->GetBaseTransform());
|
||||
shadow->SetShadowVisibleRegion(aLayer->GetVisibleRegion());
|
||||
shadow->SetShadowClipRect(aLayer->GetClipRect());
|
||||
shadow->SetShadowOpacity(aLayer->GetOpacity());
|
||||
|
||||
for (Layer* child = aLayer->GetFirstChild();
|
||||
child; child = child->GetNextSibling()) {
|
||||
@ -520,6 +537,114 @@ SetShadowProperties(Layer* aLayer)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// SampleValue should eventually take the CSS property as an argument. This
|
||||
// will be needed if we ever animate two values with the same type but different
|
||||
// interpolation rules.
|
||||
static void
|
||||
SampleValue(float aPortion, Animation& aAnimation, nsStyleAnimation::Value& aStart,
|
||||
nsStyleAnimation::Value& aEnd, Animatable* aValue)
|
||||
{
|
||||
nsStyleAnimation::Value interpolatedValue;
|
||||
NS_ASSERTION(aStart.GetUnit() == aEnd.GetUnit() ||
|
||||
aStart.GetUnit() == nsStyleAnimation::eUnit_None ||
|
||||
aEnd.GetUnit() == nsStyleAnimation::eUnit_None, "Must have same unit");
|
||||
if (aStart.GetUnit() == nsStyleAnimation::eUnit_Transform ||
|
||||
aEnd.GetUnit() == nsStyleAnimation::eUnit_Transform) {
|
||||
nsStyleAnimation::Interpolate(eCSSProperty_transform, aStart, aEnd,
|
||||
aPortion, interpolatedValue);
|
||||
nsCSSValueList* interpolatedList = interpolatedValue.GetCSSValueListValue();
|
||||
|
||||
TransformData& data = aAnimation.data().get_TransformData();
|
||||
gfx3DMatrix transform =
|
||||
nsDisplayTransform::GetResultingTransformMatrix(nsnull, data.origin(), nsDeviceContext::AppUnitsPerCSSPixel(),
|
||||
&data.bounds(), interpolatedList, &data.mozOrigin(),
|
||||
&data.perspectiveOrigin(), &data.perspective());
|
||||
|
||||
InfallibleTArray<TransformFunction>* functions = new InfallibleTArray<TransformFunction>();
|
||||
functions->AppendElement(TransformMatrix(transform));
|
||||
*aValue = *functions;
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ASSERTION(aStart.GetUnit() == nsStyleAnimation::eUnit_Float, "Should be opacity");
|
||||
nsStyleAnimation::Interpolate(eCSSProperty_opacity, aStart, aEnd,
|
||||
aPortion, interpolatedValue);
|
||||
*aValue = interpolatedValue.GetFloatValue();
|
||||
}
|
||||
|
||||
static bool
|
||||
SampleAnimations(Layer* aLayer, TimeStamp aPoint)
|
||||
{
|
||||
AnimationArray& animations = aLayer->GetAnimations();
|
||||
InfallibleTArray<AnimData>& animationData = aLayer->GetAnimationData();
|
||||
|
||||
bool activeAnimations = false;
|
||||
|
||||
for (PRUint32 i = animations.Length(); i-- !=0; ) {
|
||||
Animation& animation = animations[i];
|
||||
AnimData& animData = animationData[i];
|
||||
|
||||
double numIterations = animation.numIterations() != -1 ?
|
||||
animation.numIterations() : NS_IEEEPositiveInfinity();
|
||||
double positionInIteration =
|
||||
ElementAnimations::GetPositionInIteration(animation.startTime(),
|
||||
aPoint,
|
||||
animation.duration(),
|
||||
numIterations,
|
||||
animation.direction());
|
||||
|
||||
if (positionInIteration == -1) {
|
||||
animations.RemoveElementAt(i);
|
||||
animationData.RemoveElementAt(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
NS_ABORT_IF_FALSE(0.0 <= positionInIteration &&
|
||||
positionInIteration <= 1.0,
|
||||
"position should be in [0-1]");
|
||||
|
||||
int segmentIndex = 0;
|
||||
AnimationSegment* segment = animation.segments().Elements();
|
||||
while (segment->endPortion() < positionInIteration) {
|
||||
++segment;
|
||||
++segmentIndex;
|
||||
}
|
||||
|
||||
double positionInSegment = (positionInIteration - segment->startPortion()) /
|
||||
(segment->endPortion() - segment->startPortion());
|
||||
|
||||
double portion = animData.mFunctions[segmentIndex]->GetValue(positionInSegment);
|
||||
|
||||
activeAnimations = true;
|
||||
|
||||
// interpolate the property
|
||||
Animatable interpolatedValue;
|
||||
SampleValue(portion, animation, animData.mStartValues[segmentIndex],
|
||||
animData.mEndValues[segmentIndex], &interpolatedValue);
|
||||
ShadowLayer* shadow = aLayer->AsShadowLayer();
|
||||
switch (interpolatedValue.type()) {
|
||||
case Animatable::TOpacity:
|
||||
shadow->SetShadowOpacity(interpolatedValue.get_Opacity().value());
|
||||
break;
|
||||
case Animatable::TArrayOfTransformFunction: {
|
||||
gfx3DMatrix matrix = interpolatedValue.get_ArrayOfTransformFunction()[0].get_TransformMatrix().value();
|
||||
shadow->SetShadowTransform(matrix);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
NS_WARNING("Unhandled animated property");
|
||||
}
|
||||
}
|
||||
|
||||
for (Layer* child = aLayer->GetFirstChild(); child;
|
||||
child = child->GetNextSibling()) {
|
||||
activeAnimations |= SampleAnimations(child, aPoint);
|
||||
}
|
||||
|
||||
return activeAnimations;
|
||||
}
|
||||
|
||||
bool
|
||||
CompositorParent::ApplyAsyncContentTransformToTree(TimeStamp aCurrentFrame,
|
||||
Layer *aLayer,
|
||||
@ -565,9 +690,13 @@ CompositorParent::TransformShadowTree(TimeStamp aCurrentFrame)
|
||||
ContainerLayer* container = layer->AsContainerLayer();
|
||||
Layer* root = mLayerManager->GetRoot();
|
||||
|
||||
// NB: we must sample animations *before* sampling pan/zoom
|
||||
// transforms.
|
||||
wantNextFrame |= SampleAnimations(layer, mLastCompose);
|
||||
|
||||
const FrameMetrics& metrics = container->GetFrameMetrics();
|
||||
const gfx3DMatrix& rootTransform = root->GetTransform();
|
||||
const gfx3DMatrix& currentTransform = layer->GetTransform();
|
||||
const gfx3DMatrix& currentTransform = layer->GetBaseTransform();
|
||||
|
||||
// FIXME/bug 775437: unify this interface with the ~native-fennec
|
||||
// derived code
|
||||
@ -660,7 +789,6 @@ CompositorParent::TransformShadowTree(TimeStamp aCurrentFrame)
|
||||
shadow->SetShadowTransform(treeTransform * currentTransform);
|
||||
TransformFixedLayers(layer, offset, scaleDiff);
|
||||
}
|
||||
|
||||
return wantNextFrame;
|
||||
}
|
||||
|
||||
@ -694,8 +822,10 @@ CompositorParent::SyncViewportInfo(const nsIntRect& aDisplayPort,
|
||||
|
||||
void
|
||||
CompositorParent::ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
|
||||
const TargetConfig& aTargetConfig,
|
||||
bool isFirstPaint)
|
||||
{
|
||||
mTargetConfig = aTargetConfig;
|
||||
mIsFirstPaint = mIsFirstPaint || isFirstPaint;
|
||||
mLayersUpdated = true;
|
||||
Layer* root = aLayerTree->GetRoot();
|
||||
@ -898,6 +1028,7 @@ public:
|
||||
virtual bool DeallocPLayers(PLayersParent* aLayers) MOZ_OVERRIDE;
|
||||
|
||||
virtual void ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
|
||||
const TargetConfig& aTargetConfig,
|
||||
bool isFirstPaint) MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
@ -997,8 +1128,10 @@ CrossProcessCompositorParent::DeallocPLayers(PLayersParent* aLayers)
|
||||
}
|
||||
|
||||
void
|
||||
CrossProcessCompositorParent::ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
|
||||
bool isFirstPaint)
|
||||
CrossProcessCompositorParent::ShadowLayersUpdated(
|
||||
ShadowLayersParent* aLayerTree,
|
||||
const TargetConfig& aTargetConfig,
|
||||
bool isFirstPaint)
|
||||
{
|
||||
uint64_t id = aLayerTree->GetId();
|
||||
MOZ_ASSERT(id != 0);
|
||||
|
@ -70,6 +70,7 @@ public:
|
||||
virtual bool RecvResume() MOZ_OVERRIDE;
|
||||
|
||||
virtual void ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
|
||||
const TargetConfig& aTargetConfig,
|
||||
bool isFirstPaint) MOZ_OVERRIDE;
|
||||
void Destroy();
|
||||
|
||||
@ -227,6 +228,7 @@ private:
|
||||
|
||||
nsRefPtr<LayerManager> mLayerManager;
|
||||
nsIWidget* mWidget;
|
||||
TargetConfig mTargetConfig;
|
||||
CancelableTask *mCurrentCompositeTask;
|
||||
TimeStamp mLastCompose;
|
||||
#ifdef COMPOSITOR_PERFORMANCE_WARNING
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user