mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-01 22:55:23 +00:00
[JAEGER] Merge from Tracemonkey. This picks up Yarr.
This commit is contained in:
commit
7dad0652f9
@ -895,8 +895,16 @@ nsHTMLTableAccessible::GetCellAt(PRInt32 aRow, PRInt32 aColumn,
|
||||
nsCOMPtr<nsIContent> cellContent(do_QueryInterface(cellElement));
|
||||
nsAccessible *cell =
|
||||
GetAccService()->GetAccessibleInWeakShell(cellContent, mWeakShell);
|
||||
if (cell)
|
||||
CallQueryInterface(cell, aTableCellAccessible);
|
||||
|
||||
if (!cell) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (cell != this) {
|
||||
// XXX bug 576838: crazy tables (like table6 in tables/test_table2.html) may
|
||||
// return itself as a cell what makes Orca hang.
|
||||
NS_ADDREF(*aTableCellAccessible = cell);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -76,6 +76,11 @@ function doTest()
|
||||
accNotCreated = (!isAccessible("t5_cell"));
|
||||
ok(accNotCreated, "wrongly created table cell accessible");
|
||||
|
||||
// test crazy table
|
||||
var table6 = getAccessible("table6", [nsIAccessibleTable]);
|
||||
ok(!table6.getCellAt(0, 0),
|
||||
"We don't expect cell accessible for crazy table 6!");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
@ -138,6 +143,11 @@ addA11yLoadEvent(doTest);
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div style="display:table;" id="table6">
|
||||
<input type="checkbox">
|
||||
<a href="bar">Bad checkbox</a>
|
||||
</div>
|
||||
|
||||
</center>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -4,6 +4,8 @@ skin testpilot skin skin/all/
|
||||
skin testpilot-os skin skin/linux/ os=Linux
|
||||
skin testpilot-os skin skin/mac/ os=Darwin
|
||||
skin testpilot-os skin skin/win/ os=WINNT
|
||||
overlay chrome://browser/content/macBrowserOverlay.xul chrome://testpilot/content/tp-browser.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} appversion<4.0b1pre
|
||||
overlay chrome://browser/content/macBrowserOverlay.xul chrome://testpilot/content/feedback-browser.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} appversion>=4.0b1pre
|
||||
overlay chrome://browser/content/browser.xul chrome://testpilot/content/tp-browser.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} appversion<=3.6.*
|
||||
overlay chrome://browser/content/browser.xul chrome://testpilot/content/feedback-browser.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} appversion>3.7a1pre
|
||||
# For the menubar on Mac
|
||||
|
@ -286,11 +286,9 @@ var TestPilotXulWindow = {
|
||||
let openInTab = (task.taskType == TaskConstants.TYPE_LEGACY);
|
||||
|
||||
this.addDescription(textVbox, task.title, task.summary);
|
||||
if (task.showMoreInfoLink) {
|
||||
this.addXulLink(
|
||||
textVbox, this._stringBundle.getString("testpilot.moreInfo"),
|
||||
task.defaultUrl, openInTab);
|
||||
}
|
||||
this.addXulLink(
|
||||
textVbox, this._stringBundle.getString("testpilot.moreInfo"),
|
||||
task.defaultUrl, openInTab);
|
||||
|
||||
// Create the rightmost status area, depending on status:
|
||||
let statusVbox = document.createElement("vbox");
|
||||
|
@ -7,8 +7,10 @@
|
||||
#feedback-menu-button .toolbarbutton-text {
|
||||
display: -moz-box;
|
||||
margin: 0;
|
||||
color: -moz-dialogtext;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
|
||||
#feedback-menu-button .toolbarbutton-icon {
|
||||
display: none;
|
||||
}
|
||||
|
@ -166,10 +166,6 @@ var TestPilotTask = {
|
||||
return url + this._id;
|
||||
},
|
||||
|
||||
get showMoreInfoLink() {
|
||||
return true;
|
||||
},
|
||||
|
||||
// event handlers:
|
||||
|
||||
onExperimentStartup: function TestPilotTask_onExperimentStartup() {
|
||||
@ -1021,10 +1017,6 @@ TestPilotWebSurvey.prototype = {
|
||||
return this.infoPageUrl;
|
||||
},
|
||||
|
||||
get showMoreInfoLink() {
|
||||
return false;
|
||||
},
|
||||
|
||||
onDetailPageOpened: function TPWS_onDetailPageOpened() {
|
||||
/* Once you view the URL of the survey, we'll assume you've taken it.
|
||||
* There's no reliable way to tell whether you have or not, so let's
|
||||
|
@ -480,9 +480,9 @@ var PlacesCommandHook = {
|
||||
var tabList = [];
|
||||
var seenURIs = {};
|
||||
|
||||
var browsers = gBrowser.browsers;
|
||||
for (var i = 0; i < browsers.length; ++i) {
|
||||
let uri = browsers[i].currentURI;
|
||||
let tabs = gBrowser.visibleTabs;
|
||||
for (let i = 0; i < tabs.length; ++i) {
|
||||
let uri = tabs[i].linkedBrowser.currentURI;
|
||||
|
||||
// skip redundant entries
|
||||
if (uri.spec in seenURIs)
|
||||
|
@ -215,12 +215,13 @@ var ctrlTab = {
|
||||
if (this._tabList)
|
||||
return this._tabList;
|
||||
|
||||
var list = Array.slice(gBrowser.tabs);
|
||||
let list = gBrowser.visibleTabs;
|
||||
|
||||
if (this._closing)
|
||||
this.detachTab(this._closing, list);
|
||||
|
||||
for (let i = 0; i < gBrowser.tabContainer.selectedIndex; i++)
|
||||
// Rotate the list until the selected tab is first
|
||||
while (!list[0].selected)
|
||||
list.push(list.shift());
|
||||
|
||||
if (this.recentlyUsedLimit != 0) {
|
||||
@ -462,11 +463,12 @@ var ctrlTab = {
|
||||
} else if (!event.shiftKey) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
if (gBrowser.tabs.length > 2) {
|
||||
let tabs = gBrowser.visibleTabs;
|
||||
if (tabs.length > 2) {
|
||||
this.open();
|
||||
} else if (gBrowser.tabs.length == 2) {
|
||||
gBrowser.selectedTab = gBrowser.selectedTab.nextSibling ||
|
||||
gBrowser.selectedTab.previousSibling;
|
||||
} else if (tabs.length == 2) {
|
||||
let index = gBrowser.selectedTab == tabs[0] ? 1 : 0;
|
||||
gBrowser.selectedTab = tabs[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -664,7 +666,7 @@ var allTabs = {
|
||||
Array.forEach(this.previews, function (preview) {
|
||||
var tab = preview._tab;
|
||||
var matches = 0;
|
||||
if (filter.length) {
|
||||
if (filter.length && !tab.hidden) {
|
||||
let tabstring = tab.linkedBrowser.currentURI.spec;
|
||||
try {
|
||||
tabstring = decodeURI(tabstring);
|
||||
@ -673,7 +675,7 @@ var allTabs = {
|
||||
for (let i = 0; i < filter.length; i++)
|
||||
matches += tabstring.indexOf(filter[i]) > -1;
|
||||
}
|
||||
if (matches < filter.length) {
|
||||
if (matches < filter.length || tab.hidden) {
|
||||
preview.hidden = true;
|
||||
}
|
||||
else {
|
||||
|
@ -6772,14 +6772,12 @@ var gBookmarkAllTabsHandler = {
|
||||
this._updateCommandState();
|
||||
},
|
||||
|
||||
_updateCommandState: function BATH__updateCommandState(aTabClose) {
|
||||
var numTabs = gBrowser.tabs.length;
|
||||
_updateCommandState: function BATH__updateCommandState() {
|
||||
let remainingTabs = gBrowser.visibleTabs.filter(function(tab) {
|
||||
return gBrowser._removingTabs.indexOf(tab) == -1;
|
||||
});
|
||||
|
||||
// The TabClose event is fired before the tab is removed from the DOM
|
||||
if (aTabClose)
|
||||
numTabs--;
|
||||
|
||||
if (numTabs > 1)
|
||||
if (remainingTabs.length > 1)
|
||||
this._command.removeAttribute("disabled");
|
||||
else
|
||||
this._command.setAttribute("disabled", "true");
|
||||
@ -6791,7 +6789,7 @@ var gBookmarkAllTabsHandler = {
|
||||
|
||||
// nsIDOMEventListener
|
||||
handleEvent: function(aEvent) {
|
||||
this._updateCommandState(aEvent.type == "TabClose");
|
||||
this._updateCommandState();
|
||||
}
|
||||
};
|
||||
|
||||
@ -7799,7 +7797,7 @@ var TabContextMenu = {
|
||||
updateContextMenu: function updateContextMenu(aPopupMenu) {
|
||||
this.contextTab = document.popupNode.localName == "tab" ?
|
||||
document.popupNode : gBrowser.selectedTab;
|
||||
var disabled = gBrowser.tabs.length == 1;
|
||||
let disabled = gBrowser.visibleTabs.length == 1;
|
||||
|
||||
// Enable the "Close Tab" menuitem when the window doesn't close with the last tab.
|
||||
document.getElementById("context_closeTab").disabled =
|
||||
@ -7821,7 +7819,7 @@ var TabContextMenu = {
|
||||
|
||||
// Disable "Close other Tabs" if there is only one unpinned tab and
|
||||
// hide it when the user rightclicked on a pinned tab.
|
||||
var unpinnedTabs = gBrowser.tabs.length - gBrowser._numPinnedTabs;
|
||||
let unpinnedTabs = gBrowser.visibleTabs.length - gBrowser._numPinnedTabs;
|
||||
document.getElementById("context_closeOtherTabs").disabled = unpinnedTabs <= 1;
|
||||
document.getElementById("context_closeOtherTabs").hidden = this.contextTab.pinned;
|
||||
}
|
||||
|
@ -88,6 +88,8 @@
|
||||
<field name="tabs" readonly="true">
|
||||
this.tabContainer.childNodes;
|
||||
</field>
|
||||
<property name="visibleTabs" readonly="true"
|
||||
onget="return Array.filter(this.tabs, function(tab) !tab.hidden);"/>
|
||||
<field name="mURIFixup" readonly="true">
|
||||
Components.classes["@mozilla.org/docshell/urifixup;1"]
|
||||
.getService(Components.interfaces.nsIURIFixup);
|
||||
@ -758,6 +760,7 @@
|
||||
newBrowser.docShell.isActive = true;
|
||||
this.mCurrentBrowser = newBrowser;
|
||||
this.mCurrentTab = this.selectedTab;
|
||||
this.mCurrentTab.hidden = false;
|
||||
|
||||
if (updatePageReport)
|
||||
this.mCurrentBrowser.updatePageReport();
|
||||
@ -1016,7 +1019,8 @@
|
||||
// == 1 false YES
|
||||
// == 1 true NO
|
||||
// > 1 false/true NO
|
||||
var owner = (aURIs.length > 1) || aLoadInBackground ? null : this.selectedTab;
|
||||
var multiple = aURIs.length > 1;
|
||||
var owner = multiple || aLoadInBackground ? null : this.selectedTab;
|
||||
var firstTabAdded = null;
|
||||
|
||||
if (aReplace) {
|
||||
@ -1028,7 +1032,7 @@
|
||||
}
|
||||
}
|
||||
else
|
||||
firstTabAdded = this.addTab(aURIs[0], {ownerTab: owner, skipAnimation: true});
|
||||
firstTabAdded = this.addTab(aURIs[0], {ownerTab: owner, skipAnimation: multiple});
|
||||
|
||||
var tabNum = this.tabContainer.selectedIndex;
|
||||
for (let i = 1; i < aURIs.length; ++i) {
|
||||
@ -1243,7 +1247,7 @@
|
||||
var tabsToClose = this.tabs.length;
|
||||
|
||||
if (!aAll)
|
||||
tabsToClose -= 1 + gBrowser._numPinnedTabs;
|
||||
tabsToClose = this.visibleTabs.length - (1 + this._numPinnedTabs);
|
||||
if (tabsToClose <= 1)
|
||||
return true;
|
||||
|
||||
@ -1294,11 +1298,12 @@
|
||||
return;
|
||||
|
||||
if (this.warnAboutClosingTabs(false)) {
|
||||
let tabs = this.visibleTabs;
|
||||
this.selectedTab = aTab;
|
||||
|
||||
for (let i = this.tabs.length - 1; i >= 0; --i) {
|
||||
if (this.tabs[i] != aTab && !this.tabs[i].pinned)
|
||||
this.removeTab(this.tabs[i]);
|
||||
for (let i = tabs.length - 1; i >= 0; --i) {
|
||||
if (tabs[i] != aTab && !tabs[i].pinned)
|
||||
this.removeTab(tabs[i]);
|
||||
}
|
||||
}
|
||||
]]>
|
||||
@ -1323,10 +1328,19 @@
|
||||
<parameter name="aParams"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
var isLastTab = (this.tabs.length - this._removingTabs.length == 1);
|
||||
if (aParams)
|
||||
var animate = aParams.animate;
|
||||
|
||||
// Handle requests for synchronously removing an already
|
||||
// asynchronously closing tab.
|
||||
if (!animate &&
|
||||
this._removingTabs.indexOf(aTab) > -1) {
|
||||
this._endRemoveTab(aTab);
|
||||
return;
|
||||
}
|
||||
|
||||
var isLastTab = (this.tabs.length - this._removingTabs.length == 1);
|
||||
|
||||
if (!this._beginRemoveTab(aTab, false, null, true))
|
||||
return;
|
||||
|
||||
@ -1564,18 +1578,29 @@
|
||||
return;
|
||||
}
|
||||
|
||||
var tab = aTab;
|
||||
let removing = this._removingTabs;
|
||||
function keepRemaining(tab) {
|
||||
// A tab remains only if it's not being removed nor blurred
|
||||
return removing.indexOf(tab) == -1 && tab != aTab;
|
||||
}
|
||||
|
||||
// Switch to a visible tab unless there aren't any remaining
|
||||
let remainingTabs = this.visibleTabs.filter(keepRemaining);
|
||||
if (remainingTabs.length == 0)
|
||||
remainingTabs = Array.filter(this.tabs, keepRemaining);
|
||||
|
||||
// Try to find a remaining tab that comes after the given tab
|
||||
var tab = aTab;
|
||||
do {
|
||||
tab = tab.nextSibling;
|
||||
} while (tab && this._removingTabs.indexOf(tab) != -1);
|
||||
} while (tab && remainingTabs.indexOf(tab) == -1);
|
||||
|
||||
if (!tab) {
|
||||
tab = aTab;
|
||||
|
||||
do {
|
||||
tab = tab.previousSibling;
|
||||
} while (tab && this._removingTabs.indexOf(tab) != -1);
|
||||
} while (tab && remainingTabs.indexOf(tab) == -1);
|
||||
}
|
||||
|
||||
this.selectedTab = tab;
|
||||
@ -1651,10 +1676,11 @@
|
||||
<method name="reloadAllTabs">
|
||||
<body>
|
||||
<![CDATA[
|
||||
var l = this.mPanelContainer.childNodes.length;
|
||||
let tabs = this.visibleTabs;
|
||||
let l = tabs.length;
|
||||
for (var i = 0; i < l; i++) {
|
||||
try {
|
||||
this.getBrowserAtIndex(i).reload();
|
||||
this.getBrowserForTab(tabs[i]).reload();
|
||||
} catch (e) {
|
||||
// ignore failure to reload so others will be reloaded
|
||||
}
|
||||
@ -1751,19 +1777,30 @@
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="showOnlyTheseTabs">
|
||||
<parameter name="aTabs"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
Array.forEach(this.tabs, function(tab) {
|
||||
tab.hidden = aTabs.indexOf(tab) == -1 && !tab.pinned && !tab.selected;
|
||||
});
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="selectTabAtIndex">
|
||||
<parameter name="aIndex"/>
|
||||
<parameter name="aEvent"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
let tabs = this.visibleTabs;
|
||||
|
||||
// count backwards for aIndex < 0
|
||||
if (aIndex < 0)
|
||||
aIndex += this.tabs.length;
|
||||
aIndex += tabs.length;
|
||||
|
||||
if (aIndex >= 0 &&
|
||||
aIndex < this.tabs.length &&
|
||||
aIndex != this.tabContainer.selectedIndex)
|
||||
this.selectedTab = this.tabs[aIndex];
|
||||
if (aIndex >= 0 && aIndex < tabs.length)
|
||||
this.selectedTab = tabs[aIndex];
|
||||
|
||||
if (aEvent) {
|
||||
aEvent.preventDefault();
|
||||
@ -1805,7 +1842,7 @@
|
||||
<parameter name="aTab"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this.tabs.length == 1)
|
||||
if (this.visibleTabs.length == 1)
|
||||
return null;
|
||||
|
||||
// tell a new window to take the "dropped" tab
|
||||
@ -2390,9 +2427,9 @@
|
||||
</method>
|
||||
<method name="_canScrollToElement">
|
||||
<parameter name="tab"/>
|
||||
<body>
|
||||
return !tab.pinned;
|
||||
</body>
|
||||
<body><![CDATA[
|
||||
return !tab.pinned && !tab.hidden;
|
||||
]]></body>
|
||||
</method>
|
||||
</implementation>
|
||||
|
||||
@ -2404,7 +2441,7 @@
|
||||
var tabs = document.getBindingParent(this);
|
||||
tabs.removeAttribute("overflow");
|
||||
|
||||
tabs.tabbrowser._removingTabs.forEach(tabs.tabbrowser._endRemoveTab,
|
||||
tabs.tabbrowser._removingTabs.forEach(tabs.tabbrowser.removeTab,
|
||||
tabs.tabbrowser);
|
||||
|
||||
tabs._positionPinnedTabs();
|
||||
@ -2569,7 +2606,8 @@
|
||||
if (this.childNodes.length == 1 && this._closeWindowWithLastTab)
|
||||
this.setAttribute("closebuttons", "noclose");
|
||||
else {
|
||||
let tab = this.childNodes.item(this.tabbrowser._numPinnedTabs);
|
||||
// Grab the last tab for size comparison
|
||||
let tab = this.tabbrowser.visibleTabs.pop();
|
||||
if (tab && tab.getBoundingClientRect().width > this.mTabClipWidth)
|
||||
this.setAttribute("closebuttons", "alltabs");
|
||||
else
|
||||
@ -3366,7 +3404,7 @@
|
||||
<![CDATA[
|
||||
// set up the menu popup
|
||||
var tabcontainer = gBrowser.tabContainer;
|
||||
var tabs = tabcontainer.childNodes;
|
||||
let tabs = gBrowser.visibleTabs;
|
||||
|
||||
// Listen for changes in the tab bar.
|
||||
tabcontainer.addEventListener("TabOpen", this, false);
|
||||
|
720
browser/base/content/tabview/iq.js
Normal file
720
browser/base/content/tabview/iq.js
Normal file
@ -0,0 +1,720 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is iq.js.
|
||||
*
|
||||
* The Initial Developer of the Original Code is the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ian Gilman <ian@iangilman.com>
|
||||
* Aza Raskin <aza@mozilla.com>
|
||||
* Michael Yoshitaka Erlewine <mitcho@mitcho.com>
|
||||
*
|
||||
* This file incorporates work from:
|
||||
* jQuery JavaScript Library v1.4.2: http://code.jquery.com/jquery-1.4.2.js
|
||||
* This incorporated work is covered by the following copyright and
|
||||
* permission notice:
|
||||
* Copyright 2010, John Resig
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// **********
|
||||
// Title: iq.js
|
||||
// Various helper functions, in the vein of jQuery.
|
||||
|
||||
// ----------
|
||||
// Function: iQ
|
||||
// Returns an iQClass object which represents an individual element or a group
|
||||
// of elements. It works pretty much like jQuery(), with a few exceptions,
|
||||
// most notably that you can't use strings with complex html,
|
||||
// just simple tags like '<div>'.
|
||||
function iQ(selector, context) {
|
||||
// The iQ object is actually just the init constructor 'enhanced'
|
||||
return new iQClass(selector, context);
|
||||
};
|
||||
|
||||
// A simple way to check for HTML strings or ID strings
|
||||
// (both of which we optimize for)
|
||||
let quickExpr = /^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/;
|
||||
|
||||
// Match a standalone tag
|
||||
let rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/;
|
||||
|
||||
// ##########
|
||||
// Class: iQClass
|
||||
// The actual class of iQ result objects, representing an individual element
|
||||
// or a group of elements.
|
||||
//
|
||||
// ----------
|
||||
// Function: iQClass
|
||||
// You don't call this directly; this is what's called by iQ().
|
||||
let iQClass = function(selector, context) {
|
||||
|
||||
// Handle $(""), $(null), or $(undefined)
|
||||
if (!selector) {
|
||||
return this;
|
||||
}
|
||||
|
||||
// Handle $(DOMElement)
|
||||
if (selector.nodeType) {
|
||||
this.context = selector;
|
||||
this[0] = selector;
|
||||
this.length = 1;
|
||||
return this;
|
||||
}
|
||||
|
||||
// The body element only exists once, optimize finding it
|
||||
if (selector === "body" && !context) {
|
||||
this.context = document;
|
||||
this[0] = document.body;
|
||||
this.selector = "body";
|
||||
this.length = 1;
|
||||
return this;
|
||||
}
|
||||
|
||||
// Handle HTML strings
|
||||
if (typeof selector === "string") {
|
||||
// Are we dealing with HTML string or an ID?
|
||||
|
||||
let match = quickExpr.exec(selector);
|
||||
|
||||
// Verify a match, and that no context was specified for #id
|
||||
if (match && (match[1] || !context)) {
|
||||
|
||||
// HANDLE $(html) -> $(array)
|
||||
if (match[1]) {
|
||||
let doc = (context ? context.ownerDocument || context : document);
|
||||
|
||||
// If a single string is passed in and it's a single tag
|
||||
// just do a createElement and skip the rest
|
||||
let ret = rsingleTag.exec(selector);
|
||||
|
||||
if (ret) {
|
||||
if (Utils.isPlainObject(context)) {
|
||||
Utils.assert(false, 'does not support HTML creation with context');
|
||||
} else {
|
||||
selector = [doc.createElement(ret[1])];
|
||||
}
|
||||
|
||||
} else {
|
||||
Utils.assert(false, 'does not support complex HTML creation');
|
||||
}
|
||||
|
||||
return Utils.merge(this, selector);
|
||||
|
||||
// HANDLE $("#id")
|
||||
} else {
|
||||
let elem = document.getElementById(match[2]);
|
||||
|
||||
if (elem) {
|
||||
this.length = 1;
|
||||
this[0] = elem;
|
||||
}
|
||||
|
||||
this.context = document;
|
||||
this.selector = selector;
|
||||
return this;
|
||||
}
|
||||
|
||||
// HANDLE $("TAG")
|
||||
} else if (!context && /^\w+$/.test(selector)) {
|
||||
this.selector = selector;
|
||||
this.context = document;
|
||||
selector = document.getElementsByTagName(selector);
|
||||
return Utils.merge(this, selector);
|
||||
|
||||
// HANDLE $(expr, $(...))
|
||||
} else if (!context || context.iq) {
|
||||
return (context || iQ(document)).find(selector);
|
||||
|
||||
// HANDLE $(expr, context)
|
||||
// (which is just equivalent to: $(context).find(expr)
|
||||
} else {
|
||||
return iQ(context).find(selector);
|
||||
}
|
||||
|
||||
// HANDLE $(function)
|
||||
// Shortcut for document ready
|
||||
} else if (typeof selector == "function") {
|
||||
Utils.log('iQ does not support ready functions');
|
||||
return null;
|
||||
}
|
||||
|
||||
if (typeof selector.selector !== "undefined") {
|
||||
this.selector = selector.selector;
|
||||
this.context = selector.context;
|
||||
}
|
||||
|
||||
let ret = this || [];
|
||||
if (selector != null) {
|
||||
// The window, strings (and functions) also have 'length'
|
||||
if (selector.length == null || typeof selector == "string" || selector.setInterval) {
|
||||
Array.push(ret, selector);
|
||||
} else {
|
||||
Utils.merge(ret, selector);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
iQClass.prototype = {
|
||||
|
||||
// Start with an empty selector
|
||||
selector: "",
|
||||
|
||||
// The default length of a iQ object is 0
|
||||
length: 0,
|
||||
|
||||
// ----------
|
||||
// Function: each
|
||||
// Execute a callback for every element in the matched set.
|
||||
each: function(callback) {
|
||||
if (typeof callback != "function") {
|
||||
Utils.assert(false, "each's argument must be a function");
|
||||
return null;
|
||||
}
|
||||
for (let i = 0; this[i] != null; i++) {
|
||||
callback(this[i]);
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: addClass
|
||||
// Adds the given class(es) to the receiver.
|
||||
addClass: function(value) {
|
||||
Utils.assertThrow(typeof value == "string" && value,
|
||||
'requires a valid string argument');
|
||||
|
||||
let length = this.length;
|
||||
for (let i = 0; i < length; i++) {
|
||||
let elem = this[i];
|
||||
if (elem.nodeType === 1) {
|
||||
value.split(/\s+/).forEach(function(className) {
|
||||
elem.classList.add(className);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: removeClass
|
||||
// Removes the given class(es) from the receiver.
|
||||
removeClass: function(value) {
|
||||
if (typeof value != "string" || !value) {
|
||||
Utils.assert(false, 'does not support function argument');
|
||||
return null;
|
||||
}
|
||||
|
||||
let length = this.length;
|
||||
for (let i = 0; i < length; i++) {
|
||||
let elem = this[i];
|
||||
if (elem.nodeType === 1 && elem.className) {
|
||||
value.split(/\s+/).forEach(function(className) {
|
||||
elem.classList.remove(className);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: hasClass
|
||||
// Returns true is the receiver has the given css class.
|
||||
hasClass: function(singleClassName) {
|
||||
let length = this.length;
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (this[i].classList.contains(singleClassName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: find
|
||||
// Searches the receiver and its children, returning a new iQ object with
|
||||
// elements that match the given selector.
|
||||
find: function(selector) {
|
||||
let ret = [];
|
||||
let length = 0;
|
||||
|
||||
let l = this.length;
|
||||
for (let i = 0; i < l; i++) {
|
||||
length = ret.length;
|
||||
try {
|
||||
Utils.merge(ret, this[i].querySelectorAll(selector));
|
||||
} catch(e) {
|
||||
Utils.log('iQ.find error (bad selector)', e);
|
||||
}
|
||||
|
||||
if (i > 0) {
|
||||
// Make sure that the results are unique
|
||||
for (let n = length; n < ret.length; n++) {
|
||||
for (let r = 0; r < length; r++) {
|
||||
if (ret[r] === ret[n]) {
|
||||
ret.splice(n--, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return iQ(ret);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: remove
|
||||
// Removes the receiver from the DOM.
|
||||
remove: function() {
|
||||
for (let i = 0; this[i] != null; i++) {
|
||||
let elem = this[i];
|
||||
if (elem.parentNode) {
|
||||
elem.parentNode.removeChild(elem);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: empty
|
||||
// Removes all of the reciever's children and HTML content from the DOM.
|
||||
empty: function() {
|
||||
for (let i = 0; this[i] != null; i++) {
|
||||
let elem = this[i];
|
||||
while (elem.firstChild) {
|
||||
elem.removeChild(elem.firstChild);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: width
|
||||
// Returns the width of the receiver.
|
||||
width: function() {
|
||||
let bounds = this.bounds();
|
||||
return bounds.width;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: height
|
||||
// Returns the height of the receiver.
|
||||
height: function() {
|
||||
let bounds = this.bounds();
|
||||
return bounds.height;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: position
|
||||
// Returns an object with the receiver's position in left and top
|
||||
// properties.
|
||||
position: function() {
|
||||
let bounds = this.bounds();
|
||||
return new Point(bounds.left, bounds.top);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: bounds
|
||||
// Returns a <Rect> with the receiver's bounds.
|
||||
bounds: function() {
|
||||
Utils.assert(this.length == 1, 'does not yet support multi-objects (or null objects)');
|
||||
let rect = this[0].getBoundingClientRect();
|
||||
return new Rect(Math.floor(rect.left), Math.floor(rect.top),
|
||||
Math.floor(rect.width), Math.floor(rect.height));
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: data
|
||||
// Pass in both key and value to attach some data to the receiver;
|
||||
// pass in just key to retrieve it.
|
||||
data: function(key, value) {
|
||||
let data = null;
|
||||
if (typeof value === "undefined") {
|
||||
Utils.assert(this.length == 1, 'does not yet support multi-objects (or null objects)');
|
||||
data = this[0].iQData;
|
||||
if (data)
|
||||
return data[key];
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
for (let i = 0; this[i] != null; i++) {
|
||||
let elem = this[i];
|
||||
data = elem.iQData;
|
||||
|
||||
if (!data)
|
||||
data = elem.iQData = {};
|
||||
|
||||
data[key] = value;
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: html
|
||||
// Given a value, sets the receiver's innerHTML to it; otherwise returns
|
||||
// what's already there.
|
||||
html: function(value) {
|
||||
Utils.assert(this.length == 1, 'does not yet support multi-objects (or null objects)');
|
||||
if (typeof value === "undefined")
|
||||
return this[0].innerHTML;
|
||||
|
||||
this[0].innerHTML = value;
|
||||
return this;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: text
|
||||
// Given a value, sets the receiver's textContent to it; otherwise returns
|
||||
// what's already there.
|
||||
text: function(value) {
|
||||
Utils.assert(this.length == 1, 'does not yet support multi-objects (or null objects)');
|
||||
if (typeof value === "undefined") {
|
||||
return this[0].textContent;
|
||||
}
|
||||
|
||||
return this.empty().append((this[0] && this[0].ownerDocument || document).createTextNode(value));
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: val
|
||||
// Given a value, sets the receiver's value to it; otherwise returns what's already there.
|
||||
val: function(value) {
|
||||
Utils.assert(this.length == 1, 'does not yet support multi-objects (or null objects)');
|
||||
if (typeof value === "undefined") {
|
||||
return this[0].value;
|
||||
}
|
||||
|
||||
this[0].value = value;
|
||||
return this;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: appendTo
|
||||
// Appends the receiver to the result of iQ(selector).
|
||||
appendTo: function(selector) {
|
||||
Utils.assert(this.length == 1, 'does not yet support multi-objects (or null objects)');
|
||||
iQ(selector).append(this);
|
||||
return this;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: append
|
||||
// Appends the result of iQ(selector) to the receiver.
|
||||
append: function(selector) {
|
||||
let object = iQ(selector);
|
||||
Utils.assert(object.length == 1 && this.length == 1,
|
||||
'does not yet support multi-objects (or null objects)');
|
||||
this[0].appendChild(object[0]);
|
||||
return this;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: attr
|
||||
// Sets or gets an attribute on the element(s).
|
||||
attr: function(key, value) {
|
||||
Utils.assert(typeof key === 'string', 'string key');
|
||||
if (typeof value === "undefined") {
|
||||
Utils.assert(this.length == 1, 'retrieval does not support multi-objects (or null objects)');
|
||||
return this[0].getAttribute(key);
|
||||
}
|
||||
|
||||
for (let i = 0; this[i] != null; i++)
|
||||
this[i].setAttribute(key, value);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: css
|
||||
// Sets or gets CSS properties on the receiver. When setting certain numerical properties,
|
||||
// will automatically add "px". A property can be removed by setting it to null.
|
||||
//
|
||||
// Possible call patterns:
|
||||
// a: object, b: undefined - sets with properties from a
|
||||
// a: string, b: undefined - gets property specified by a
|
||||
// a: string, b: string/number - sets property specified by a to b
|
||||
css: function(a, b) {
|
||||
let properties = null;
|
||||
|
||||
if (typeof a === 'string') {
|
||||
let key = a;
|
||||
if (typeof b === "undefined") {
|
||||
Utils.assert(this.length == 1, 'retrieval does not support multi-objects (or null objects)');
|
||||
|
||||
return window.getComputedStyle(this[0], null).getPropertyValue(key);
|
||||
}
|
||||
properties = {};
|
||||
properties[key] = b;
|
||||
} else {
|
||||
properties = a;
|
||||
}
|
||||
|
||||
let pixels = {
|
||||
'left': true,
|
||||
'top': true,
|
||||
'right': true,
|
||||
'bottom': true,
|
||||
'width': true,
|
||||
'height': true
|
||||
};
|
||||
|
||||
for (let i = 0; this[i] != null; i++) {
|
||||
let elem = this[i];
|
||||
for (let key in properties) {
|
||||
let value = properties[key];
|
||||
if (pixels[key] && typeof value != 'string')
|
||||
value += 'px';
|
||||
|
||||
if (value == null) {
|
||||
elem.style.removeProperty(key);
|
||||
} else if (key.indexOf('-') != -1)
|
||||
elem.style.setProperty(key, value, '');
|
||||
else
|
||||
elem.style[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: animate
|
||||
// Uses CSS transitions to animate the element.
|
||||
//
|
||||
// Parameters:
|
||||
// css - an object map of the CSS properties to change
|
||||
// options - an object with various properites (see below)
|
||||
//
|
||||
// Possible "options" properties:
|
||||
// duration - how long to animate, in milliseconds
|
||||
// easing - easing function to use. Possibilities include
|
||||
// "tabviewBounce", "easeInQuad". Default is "ease".
|
||||
// complete - function to call once the animation is done, takes nothing
|
||||
// in, but "this" is set to the element that was animated.
|
||||
animate: function(css, options) {
|
||||
Utils.assert(this.length == 1, 'does not yet support multi-objects (or null objects)');
|
||||
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
let easings = {
|
||||
tabviewBounce: "cubic-bezier(0.0, 0.63, .6, 1.0)",
|
||||
// TODO: change 1.0 above to 1.29 after bug 575672 is fixed
|
||||
|
||||
easeInQuad: 'ease-in', // TODO: make it a real easeInQuad, or decide we don't care
|
||||
fast: 'cubic-bezier(0.7,0,1,1)'
|
||||
};
|
||||
|
||||
let duration = (options.duration || 400);
|
||||
let easing = (easings[options.easing] || 'ease');
|
||||
|
||||
// The latest versions of Firefox do not animate from a non-explicitly
|
||||
// set css properties. So for each element to be animated, go through
|
||||
// and explicitly define 'em.
|
||||
let rupper = /([A-Z])/g;
|
||||
this.each(function(elem) {
|
||||
let cStyle = window.getComputedStyle(elem, null);
|
||||
for (let prop in css) {
|
||||
prop = prop.replace(rupper, "-$1").toLowerCase();
|
||||
iQ(elem).css(prop, cStyle.getPropertyValue(prop));
|
||||
}
|
||||
});
|
||||
|
||||
this.css({
|
||||
'-moz-transition-property': 'all', // TODO: just animate the properties we're changing
|
||||
'-moz-transition-duration': (duration / 1000) + 's',
|
||||
'-moz-transition-timing-function': easing
|
||||
});
|
||||
|
||||
this.css(css);
|
||||
|
||||
let self = this;
|
||||
setTimeout(function() {
|
||||
self.css({
|
||||
'-moz-transition-property': 'none',
|
||||
'-moz-transition-duration': '',
|
||||
'-moz-transition-timing-function': ''
|
||||
});
|
||||
|
||||
if (typeof options.complete == "function")
|
||||
options.complete.apply(self);
|
||||
}, duration);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: fadeOut
|
||||
// Animates the receiver to full transparency. Calls callback on completion.
|
||||
fadeOut: function(callback) {
|
||||
Utils.assert(typeof callback == "function" || typeof callback === "undefined",
|
||||
'does not yet support duration');
|
||||
|
||||
this.animate({
|
||||
opacity: 0
|
||||
}, {
|
||||
duration: 400,
|
||||
complete: function() {
|
||||
iQ(this).css({display: 'none'});
|
||||
if (typeof callback == "function")
|
||||
callback.apply(this);
|
||||
}
|
||||
});
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: fadeIn
|
||||
// Animates the receiver to full opacity.
|
||||
fadeIn: function() {
|
||||
this.css({display: ''});
|
||||
this.animate({
|
||||
opacity: 1
|
||||
}, {
|
||||
duration: 400
|
||||
});
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: hide
|
||||
// Hides the receiver.
|
||||
hide: function() {
|
||||
this.css({display: 'none', opacity: 0});
|
||||
return this;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: show
|
||||
// Shows the receiver.
|
||||
show: function() {
|
||||
this.css({display: '', opacity: 1});
|
||||
return this;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: bind
|
||||
// Binds the given function to the given event type. Also wraps the function
|
||||
// in a try/catch block that does a Utils.log on any errors.
|
||||
bind: function(type, func) {
|
||||
let handler = function(event) func.apply(this, [event]);
|
||||
|
||||
for (let i = 0; this[i] != null; i++) {
|
||||
let elem = this[i];
|
||||
if (!elem.iQEventData)
|
||||
elem.iQEventData = {};
|
||||
|
||||
if (!elem.iQEventData[type])
|
||||
elem.iQEventData[type] = [];
|
||||
|
||||
elem.iQEventData[type].push({
|
||||
original: func,
|
||||
modified: handler
|
||||
});
|
||||
|
||||
elem.addEventListener(type, handler, false);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: one
|
||||
// Binds the given function to the given event type, but only for one call;
|
||||
// automatically unbinds after the event fires once.
|
||||
one: function(type, func) {
|
||||
Utils.assert(typeof func == "function", 'does not support eventData argument');
|
||||
|
||||
let handler = function(e) {
|
||||
iQ(this).unbind(type, handler);
|
||||
return func.apply(this, [e]);
|
||||
};
|
||||
|
||||
return this.bind(type, handler);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: unbind
|
||||
// Unbinds the given function from the given event type.
|
||||
unbind: function(type, func) {
|
||||
Utils.assert(typeof func == "function", 'Must provide a function');
|
||||
|
||||
for (let i = 0; this[i] != null; i++) {
|
||||
let elem = this[i];
|
||||
let handler = func;
|
||||
if (elem.iQEventData && elem.iQEventData[type]) {
|
||||
let count = elem.iQEventData[type].length;
|
||||
for (let a = 0; a < count; a++) {
|
||||
let pair = elem.iQEventData[type][a];
|
||||
if (pair.original == func) {
|
||||
handler = pair.modified;
|
||||
elem.iQEventData[type].splice(a, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
elem.removeEventListener(type, handler, false);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
// ----------
|
||||
// Create various event aliases
|
||||
let events = [
|
||||
'keyup',
|
||||
'keydown',
|
||||
'mouseup',
|
||||
'mousedown',
|
||||
'mouseover',
|
||||
'mouseout',
|
||||
'mousemove',
|
||||
'click',
|
||||
'resize',
|
||||
'change',
|
||||
'blur',
|
||||
'focus'
|
||||
];
|
||||
|
||||
events.forEach(function(event) {
|
||||
iQClass.prototype[event] = function(func) {
|
||||
return this.bind(event, func);
|
||||
};
|
||||
});
|
728
browser/base/content/tabview/modules/utils.jsm
Normal file
728
browser/base/content/tabview/modules/utils.jsm
Normal file
@ -0,0 +1,728 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is utils.js.
|
||||
*
|
||||
* The Initial Developer of the Original Code is the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Aza Raskin <aza@mozilla.com>
|
||||
* Ian Gilman <ian@iangilman.com>
|
||||
* Michael Yoshitaka Erlewine <mitcho@mitcho.com>
|
||||
*
|
||||
* This file incorporates work from:
|
||||
* jQuery JavaScript Library v1.4.2: http://code.jquery.com/jquery-1.4.2.js
|
||||
* This incorporated work is covered by the following copyright and
|
||||
* permission notice:
|
||||
* Copyright 2010, John Resig
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// **********
|
||||
// Title: utils.js
|
||||
|
||||
let EXPORTED_SYMBOLS = ["Point", "Rect", "Range", "Subscribable", "Utils"];
|
||||
|
||||
// #########
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
// ##########
|
||||
// Class: Point
|
||||
// A simple point.
|
||||
//
|
||||
// Constructor: Point
|
||||
// If a is a Point, creates a copy of it. Otherwise, expects a to be x,
|
||||
// and creates a Point with it along with y. If either a or y are omitted,
|
||||
// 0 is used in their place.
|
||||
function Point(a, y) {
|
||||
if (Utils.isPoint(a)) {
|
||||
this.x = a.x;
|
||||
this.y = a.y;
|
||||
} else {
|
||||
this.x = (Utils.isNumber(a) ? a : 0);
|
||||
this.y = (Utils.isNumber(y) ? y : 0);
|
||||
}
|
||||
};
|
||||
|
||||
Point.prototype = {
|
||||
// ----------
|
||||
// Function: distance
|
||||
// Returns the distance from this point to the given <Point>.
|
||||
distance: function(point) {
|
||||
var ax = this.x - point.x;
|
||||
var ay = this.y - point.y;
|
||||
return Math.sqrt((ax * ax) + (ay * ay));
|
||||
}
|
||||
};
|
||||
|
||||
// ##########
|
||||
// Class: Rect
|
||||
// A simple rectangle. Note that in addition to the left and width, it also has
|
||||
// a right property; changing one affects the others appropriately. Same for the
|
||||
// vertical properties.
|
||||
//
|
||||
// Constructor: Rect
|
||||
// If a is a Rect, creates a copy of it. Otherwise, expects a to be left,
|
||||
// and creates a Rect with it along with top, width, and height.
|
||||
function Rect(a, top, width, height) {
|
||||
// Note: perhaps 'a' should really be called 'rectOrLeft'
|
||||
if (Utils.isRect(a)) {
|
||||
this.left = a.left;
|
||||
this.top = a.top;
|
||||
this.width = a.width;
|
||||
this.height = a.height;
|
||||
} else {
|
||||
this.left = a;
|
||||
this.top = top;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
};
|
||||
|
||||
Rect.prototype = {
|
||||
|
||||
get right() this.left + this.width,
|
||||
set right(value) {
|
||||
this.width = value - this.left;
|
||||
},
|
||||
|
||||
get bottom() this.top + this.height,
|
||||
set bottom(value) {
|
||||
this.height = value - this.top;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Variable: xRange
|
||||
// Gives you a new <Range> for the horizontal dimension.
|
||||
get xRange() new Range(this.left, this.right),
|
||||
|
||||
// ----------
|
||||
// Variable: yRange
|
||||
// Gives you a new <Range> for the vertical dimension.
|
||||
get yRange() new Range(this.top, this.bottom),
|
||||
|
||||
// ----------
|
||||
// Function: intersects
|
||||
// Returns true if this rectangle intersects the given <Rect>.
|
||||
intersects: function(rect) {
|
||||
return (rect.right > this.left &&
|
||||
rect.left < this.right &&
|
||||
rect.bottom > this.top &&
|
||||
rect.top < this.bottom);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: intersection
|
||||
// Returns a new <Rect> with the intersection of this rectangle and the give <Rect>,
|
||||
// or null if they don't intersect.
|
||||
intersection: function(rect) {
|
||||
var box = new Rect(Math.max(rect.left, this.left), Math.max(rect.top, this.top), 0, 0);
|
||||
box.right = Math.min(rect.right, this.right);
|
||||
box.bottom = Math.min(rect.bottom, this.bottom);
|
||||
if (box.width > 0 && box.height > 0)
|
||||
return box;
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: contains
|
||||
// Returns a boolean denoting if the <Rect> is contained inside
|
||||
// of the bounding rect.
|
||||
//
|
||||
// Paramaters
|
||||
// - A <Rect>
|
||||
contains: function(rect) {
|
||||
return (rect.left > this.left &&
|
||||
rect.right < this.right &&
|
||||
rect.top > this.top &&
|
||||
rect.bottom < this.bottom);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: center
|
||||
// Returns a new <Point> with the center location of this rectangle.
|
||||
center: function() {
|
||||
return new Point(this.left + (this.width / 2), this.top + (this.height / 2));
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: size
|
||||
// Returns a new <Point> with the dimensions of this rectangle.
|
||||
size: function() {
|
||||
return new Point(this.width, this.height);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: position
|
||||
// Returns a new <Point> with the top left of this rectangle.
|
||||
position: function() {
|
||||
return new Point(this.left, this.top);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: area
|
||||
// Returns the area of this rectangle.
|
||||
area: function() {
|
||||
return this.width * this.height;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: inset
|
||||
// Makes the rect smaller (if the arguments are positive) as if a margin is added all around
|
||||
// the initial rect, with the margin widths (symmetric) being specified by the arguments.
|
||||
//
|
||||
// Paramaters
|
||||
// - A <Point> or two arguments: x and y
|
||||
inset: function(a, b) {
|
||||
if (Utils.isPoint(a)) {
|
||||
b = a.y;
|
||||
a = a.x;
|
||||
}
|
||||
|
||||
this.left += a;
|
||||
this.width -= a * 2;
|
||||
this.top += b;
|
||||
this.height -= b * 2;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: offset
|
||||
// Moves (translates) the rect by the given vector.
|
||||
//
|
||||
// Paramaters
|
||||
// - A <Point> or two arguments: x and y
|
||||
offset: function(a, b) {
|
||||
if (Utils.isPoint(a)) {
|
||||
this.left += a.x;
|
||||
this.top += a.y;
|
||||
} else {
|
||||
this.left += a;
|
||||
this.top += b;
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: equals
|
||||
// Returns true if this rectangle is identical to the given <Rect>.
|
||||
equals: function(rect) {
|
||||
return (rect.left == this.left &&
|
||||
rect.top == this.top &&
|
||||
rect.width == this.width &&
|
||||
rect.height == this.height);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: union
|
||||
// Returns a new <Rect> with the union of this rectangle and the given <Rect>.
|
||||
union: function(a) {
|
||||
var newLeft = Math.min(a.left, this.left);
|
||||
var newTop = Math.min(a.top, this.top);
|
||||
var newWidth = Math.max(a.right, this.right) - newLeft;
|
||||
var newHeight = Math.max(a.bottom, this.bottom) - newTop;
|
||||
var newRect = new Rect(newLeft, newTop, newWidth, newHeight);
|
||||
|
||||
return newRect;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: copy
|
||||
// Copies the values of the given <Rect> into this rectangle.
|
||||
copy: function(a) {
|
||||
this.left = a.left;
|
||||
this.top = a.top;
|
||||
this.width = a.width;
|
||||
this.height = a.height;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: css
|
||||
// Returns an object with the dimensions of this rectangle, suitable for
|
||||
// passing into iQ's css method. You could of course just pass the rectangle
|
||||
// straight in, but this is cleaner, as it removes all the extraneous
|
||||
// properties. If you give a <Rect> to <iQClass.css> without this, it will
|
||||
// ignore the extraneous properties, but result in CSS warnings.
|
||||
css: function() {
|
||||
return {
|
||||
left: this.left,
|
||||
top: this.top,
|
||||
width: this.width,
|
||||
height: this.height
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// ##########
|
||||
// Class: Range
|
||||
// A physical interval, with a min and max.
|
||||
//
|
||||
// Constructor: Range
|
||||
// Creates a Range with the given min and max
|
||||
function Range(min, max) {
|
||||
if (Utils.isRange(min) && !max) { // if the one variable given is a range, copy it.
|
||||
this.min = min.min;
|
||||
this.max = min.max;
|
||||
} else {
|
||||
this.min = min || 0;
|
||||
this.max = max || 0;
|
||||
}
|
||||
};
|
||||
|
||||
Range.prototype = {
|
||||
// Variable: extent
|
||||
// Equivalent to max-min
|
||||
get extent() {
|
||||
return (this.max - this.min);
|
||||
},
|
||||
|
||||
set extent(extent) {
|
||||
this.max = extent - this.min;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: contains
|
||||
// Whether the <Range> contains the given <Range> or value or not.
|
||||
//
|
||||
// Paramaters
|
||||
// - a number or <Range>
|
||||
contains: function(value) {
|
||||
if (Utils.isNumber(value))
|
||||
return value >= this.min && value <= this.max;
|
||||
if (Utils.isRange(value))
|
||||
return value.min >= this.min && value.max <= this.max;
|
||||
return false;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: proportion
|
||||
// Maps the given value to the range [0,1], so that it returns 0 if the value is <= the min,
|
||||
// returns 1 if the value >= the max, and returns an interpolated "proportion" in (min, max).
|
||||
//
|
||||
// Paramaters
|
||||
// - a number
|
||||
// - (bool) smooth? If true, a smooth tanh-based function will be used instead of the linear.
|
||||
proportion: function(value, smooth) {
|
||||
if (value <= this.min)
|
||||
return 0;
|
||||
if (this.max <= value)
|
||||
return 1;
|
||||
|
||||
var proportion = (value - this.min) / this.extent;
|
||||
|
||||
if (smooth) {
|
||||
// The ease function ".5+.5*Math.tanh(4*x-2)" is a pretty
|
||||
// little graph. It goes from near 0 at x=0 to near 1 at x=1
|
||||
// smoothly and beautifully.
|
||||
// http://www.wolframalpha.com/input/?i=.5+%2B+.5+*+tanh%28%284+*+x%29+-+2%29
|
||||
function tanh(x) {
|
||||
var e = Math.exp(x);
|
||||
return (e - 1/e) / (e + 1/e);
|
||||
}
|
||||
return .5 - .5 * tanh(2 - 4 * proportion);
|
||||
}
|
||||
|
||||
return proportion;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: scale
|
||||
// Takes the given value in [0,1] and maps it to the associated value on the Range.
|
||||
//
|
||||
// Paramaters
|
||||
// - a number in [0,1]
|
||||
scale: function(value) {
|
||||
if (value > 1)
|
||||
value = 1;
|
||||
if (value < 0)
|
||||
value = 0;
|
||||
return this.min + this.extent * value;
|
||||
}
|
||||
};
|
||||
|
||||
// ##########
|
||||
// Class: Subscribable
|
||||
// A mix-in for allowing objects to collect subscribers for custom events.
|
||||
function Subscribable() {
|
||||
this.subscribers = null;
|
||||
};
|
||||
|
||||
Subscribable.prototype = {
|
||||
// ----------
|
||||
// Function: addSubscriber
|
||||
// The given callback will be called when the Subscribable fires the given event.
|
||||
// The refObject is used to facilitate removal if necessary.
|
||||
addSubscriber: function(refObject, eventName, callback) {
|
||||
try {
|
||||
Utils.assertThrow(refObject, "refObject");
|
||||
Utils.assertThrow(typeof callback == "function", "callback must be a function");
|
||||
Utils.assertThrow(eventName && typeof eventName == "string",
|
||||
"eventName must be a non-empty string");
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.subscribers)
|
||||
this.subscribers = {};
|
||||
|
||||
if (!this.subscribers[eventName])
|
||||
this.subscribers[eventName] = [];
|
||||
|
||||
var subs = this.subscribers[eventName];
|
||||
var existing = subs.filter(function(element) {
|
||||
return element.refObject == refObject;
|
||||
});
|
||||
|
||||
if (existing.length) {
|
||||
Utils.assert(existing.length == 1, 'should only ever be one');
|
||||
existing[0].callback = callback;
|
||||
} else {
|
||||
subs.push({
|
||||
refObject: refObject,
|
||||
callback: callback
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: removeSubscriber
|
||||
// Removes the callback associated with refObject for the given event.
|
||||
removeSubscriber: function(refObject, eventName) {
|
||||
try {
|
||||
Utils.assertThrow(refObject, "refObject");
|
||||
Utils.assertThrow(eventName && typeof eventName == "string",
|
||||
"eventName must be a non-empty string");
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.subscribers || !this.subscribers[eventName])
|
||||
return;
|
||||
|
||||
this.subscribers[eventName] = this.subscribers[eventName].filter(function(element) {
|
||||
return element.refObject != refObject;
|
||||
});
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: _sendToSubscribers
|
||||
// Internal routine. Used by the Subscribable to fire events.
|
||||
_sendToSubscribers: function(eventName, eventInfo) {
|
||||
try {
|
||||
Utils.assertThrow(eventName && typeof eventName == "string",
|
||||
"eventName must be a non-empty string");
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.subscribers || !this.subscribers[eventName])
|
||||
return;
|
||||
|
||||
var subsCopy = this.subscribers[eventName].concat();
|
||||
subsCopy.forEach(function(object) {
|
||||
try {
|
||||
object.callback(this, eventInfo);
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
};
|
||||
|
||||
// ##########
|
||||
// Class: Utils
|
||||
// Singelton with common utility functions.
|
||||
let Utils = {
|
||||
// ___ Logging
|
||||
|
||||
// ----------
|
||||
// Function: log
|
||||
// Prints the given arguments to the JavaScript error console as a message.
|
||||
// Pass as many arguments as you want, it'll print them all.
|
||||
log: function() {
|
||||
var text = this.expandArgumentsForLog(arguments);
|
||||
Services.console.logStringMessage(text);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: error
|
||||
// Prints the given arguments to the JavaScript error console as an error.
|
||||
// Pass as many arguments as you want, it'll print them all.
|
||||
error: function() {
|
||||
var text = this.expandArgumentsForLog(arguments);
|
||||
Cu.reportError("tabview error: " + text);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: trace
|
||||
// Prints the given arguments to the JavaScript error console as a message,
|
||||
// along with a full stack trace.
|
||||
// Pass as many arguments as you want, it'll print them all.
|
||||
trace: function() {
|
||||
var text = this.expandArgumentsForLog(arguments);
|
||||
// cut off the first two lines of the stack trace, because they're just this function.
|
||||
let stack = Error().stack.replace(/^.*?\n.*?\n/, "");
|
||||
// if the caller was assert, cut out the line for the assert function as well.
|
||||
if (this.trace.caller.name == 'Utils_assert')
|
||||
stack = stack.replace(/^.*?\n/, "");
|
||||
this.log('trace: ' + text + '\n' + stack);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: assert
|
||||
// Prints a stack trace along with label (as a console message) if condition is false.
|
||||
assert: function Utils_assert(condition, label) {
|
||||
if (!condition) {
|
||||
let text;
|
||||
if (typeof label != 'string')
|
||||
text = 'badly formed assert';
|
||||
else
|
||||
text = "tabview assert: " + label;
|
||||
|
||||
this.trace(text);
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: assertThrow
|
||||
// Throws label as an exception if condition is false.
|
||||
assertThrow: function(condition, label) {
|
||||
if (!condition) {
|
||||
let text;
|
||||
if (typeof label != 'string')
|
||||
text = 'badly formed assert';
|
||||
else
|
||||
text = "tabview assert: " + label;
|
||||
|
||||
// cut off the first two lines of the stack trace, because they're just this function.
|
||||
text += Error().stack.replace(/^.*?\n.*?\n/, "");
|
||||
|
||||
throw text;
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: expandObject
|
||||
// Prints the given object to a string, including all of its properties.
|
||||
expandObject: function(obj) {
|
||||
var s = obj + ' = {';
|
||||
for (let prop in obj) {
|
||||
let value;
|
||||
try {
|
||||
value = obj[prop];
|
||||
} catch(e) {
|
||||
value = '[!!error retrieving property]';
|
||||
}
|
||||
|
||||
s += prop + ': ';
|
||||
if (typeof value == 'string')
|
||||
s += '\'' + value + '\'';
|
||||
else if (typeof value == 'function')
|
||||
s += 'function';
|
||||
else
|
||||
s += value;
|
||||
|
||||
s += ', ';
|
||||
}
|
||||
return s + '}';
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: expandArgumentsForLog
|
||||
// Expands all of the given args (an array) into a single string.
|
||||
expandArgumentsForLog: function(args) {
|
||||
var that = this;
|
||||
return Array.map(args, function(arg) {
|
||||
return typeof arg == 'object' ? that.expandObject(arg) : arg;
|
||||
}).join('; ');
|
||||
},
|
||||
|
||||
// ___ Misc
|
||||
|
||||
// ----------
|
||||
// Function: isRightClick
|
||||
// Given a DOM mouse event, returns true if it was for the right mouse button.
|
||||
isRightClick: function(event) {
|
||||
return event.button == 2;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: isDOMElement
|
||||
// Returns true if the given object is a DOM element.
|
||||
isDOMElement: function(object) {
|
||||
return object instanceof Ci.nsIDOMElement;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: isNumber
|
||||
// Returns true if the argument is a valid number.
|
||||
isNumber: function(n) {
|
||||
return typeof n == 'number' && !isNaN(n);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: isRect
|
||||
// Returns true if the given object (r) looks like a <Rect>.
|
||||
isRect: function(r) {
|
||||
return (r &&
|
||||
this.isNumber(r.left) &&
|
||||
this.isNumber(r.top) &&
|
||||
this.isNumber(r.width) &&
|
||||
this.isNumber(r.height));
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: isRange
|
||||
// Returns true if the given object (r) looks like a <Range>.
|
||||
isRange: function(r) {
|
||||
return (r &&
|
||||
this.isNumber(r.min) &&
|
||||
this.isNumber(r.max));
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: isPoint
|
||||
// Returns true if the given object (p) looks like a <Point>.
|
||||
isPoint: function(p) {
|
||||
return (p && this.isNumber(p.x) && this.isNumber(p.y));
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: isPlainObject
|
||||
// Check to see if an object is a plain object (created using "{}" or "new Object").
|
||||
isPlainObject: function(obj) {
|
||||
// Must be an Object.
|
||||
// Make sure that DOM nodes and window objects don't pass through, as well
|
||||
if (!obj || Object.prototype.toString.call(obj) !== "[object Object]" ||
|
||||
obj.nodeType || obj.setInterval) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Not own constructor property must be Object
|
||||
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
|
||||
if (obj.constructor &&
|
||||
!hasOwnProperty.call(obj, "constructor") &&
|
||||
!hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Own properties are enumerated firstly, so to speed up,
|
||||
// if last one is own, then all properties are own.
|
||||
|
||||
var key;
|
||||
for (key in obj) {}
|
||||
|
||||
return key === undefined || hasOwnProperty.call(obj, key);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: isEmptyObject
|
||||
// Returns true if the given object has no members.
|
||||
isEmptyObject: function(obj) {
|
||||
for (let name in obj)
|
||||
return false;
|
||||
return true;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: copy
|
||||
// Returns a copy of the argument. Note that this is a shallow copy; if the argument
|
||||
// has properties that are themselves objects, those properties will be copied by reference.
|
||||
copy: function(value) {
|
||||
if (value && typeof value == 'object') {
|
||||
if (Array.isArray(value))
|
||||
return this.extend([], value);
|
||||
return this.extend({}, value);
|
||||
}
|
||||
return value;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: merge
|
||||
// Merge two array-like objects into the first and return it.
|
||||
merge: function(first, second) {
|
||||
Array.forEach(second, function(el) Array.push(first, el));
|
||||
return first;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: extend
|
||||
// Pass several objects in and it will combine them all into the first object and return it.
|
||||
extend: function() {
|
||||
|
||||
// copy reference to target object
|
||||
let target = arguments[0] || {};
|
||||
// Deep copy is not supported
|
||||
if (typeof target === "boolean") {
|
||||
this.assert(false, "The first argument of extend cannot be a boolean." +
|
||||
"Deep copy is not supported.");
|
||||
return target;
|
||||
}
|
||||
|
||||
// Back when this was in iQ + iQ.fn, so you could extend iQ objects with it.
|
||||
// This is no longer supported.
|
||||
let length = arguments.length;
|
||||
if (length === 1) {
|
||||
this.assert(false, "Extending the iQ prototype using extend is not supported.");
|
||||
return target;
|
||||
}
|
||||
|
||||
// Handle case when target is a string or something
|
||||
if (typeof target != "object" && typeof target != "function") {
|
||||
target = {};
|
||||
}
|
||||
|
||||
for (let i = 1; i < length; i++) {
|
||||
// Only deal with non-null/undefined values
|
||||
let options = arguments[i];
|
||||
if (options != null) {
|
||||
// Extend the base object
|
||||
for (let name in options) {
|
||||
let copy = options[name];
|
||||
|
||||
// Prevent never-ending loop
|
||||
if (target === copy)
|
||||
continue;
|
||||
|
||||
if (copy !== undefined)
|
||||
target[name] = copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the modified object
|
||||
return target;
|
||||
}
|
||||
};
|
@ -68,7 +68,6 @@ _TEST_FILES = \
|
||||
gZipOfflineChild.html^headers^ \
|
||||
gZipOfflineChild.cacheManifest \
|
||||
gZipOfflineChild.cacheManifest^headers^ \
|
||||
test_bug452451.html \
|
||||
$(NULL)
|
||||
|
||||
ifeq (,$(filter gtk2,$(MOZ_WIDGET_TOOLKIT)))
|
||||
@ -167,6 +166,7 @@ _BROWSER_FILES = \
|
||||
browser_selectTabAtIndex.js \
|
||||
browser_tabfocus.js \
|
||||
browser_tabs_owner.js \
|
||||
browser_visibleTabs.js \
|
||||
discovery.html \
|
||||
moz.png \
|
||||
test_bug435035.html \
|
||||
|
@ -5,6 +5,11 @@ function test() {
|
||||
gBrowser.removeTab(tab);
|
||||
is(tab.parentNode, null, "tab removed immediately");
|
||||
|
||||
tab = gBrowser.addTab("about:blank", { skipAnimation: true });
|
||||
gBrowser.removeTab(tab, { animate: true });
|
||||
gBrowser.removeTab(tab);
|
||||
is(tab.parentNode, null, "tab removed immediately when calling removeTab again after the animation was kicked off");
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
Services.prefs.setBoolPref("browser.tabs.animate", true);
|
||||
|
126
browser/base/content/test/browser_visibleTabs.js
Normal file
126
browser/base/content/test/browser_visibleTabs.js
Normal file
@ -0,0 +1,126 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is tabbrowser visibleTabs test.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Edward Lee <edilee@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function test() {
|
||||
// There should be one tab when we start the test
|
||||
let [origTab] = gBrowser.visibleTabs;
|
||||
|
||||
// Add a tab that will get pinned
|
||||
let pinned = gBrowser.addTab();
|
||||
gBrowser.pinTab(pinned);
|
||||
|
||||
let testTab = gBrowser.addTab();
|
||||
|
||||
let visible = gBrowser.visibleTabs;
|
||||
is(visible.length, 3, "3 tabs should be open");
|
||||
is(visible[0], pinned, "the pinned tab is first");
|
||||
is(visible[1], origTab, "original tab is next");
|
||||
is(visible[2], testTab, "last created tab is last");
|
||||
|
||||
// Only show the test tab (but also get pinned and selected)
|
||||
is(gBrowser.selectedTab, origTab, "sanity check that we're on the original tab");
|
||||
gBrowser.showOnlyTheseTabs([testTab]);
|
||||
is(gBrowser.visibleTabs.length, 3, "all 3 tabs are still visible");
|
||||
|
||||
// Select the test tab and only show that (and pinned)
|
||||
gBrowser.selectedTab = testTab;
|
||||
gBrowser.showOnlyTheseTabs([testTab]);
|
||||
|
||||
visible = gBrowser.visibleTabs;
|
||||
is(visible.length, 2, "2 tabs should be visible including the pinned");
|
||||
is(visible[0], pinned, "first is pinned");
|
||||
is(visible[1], testTab, "next is the test tab");
|
||||
is(gBrowser.tabs.length, 3, "3 tabs should still be open");
|
||||
|
||||
gBrowser.selectTabAtIndex(0);
|
||||
is(gBrowser.selectedTab, pinned, "first tab is pinned");
|
||||
gBrowser.selectTabAtIndex(1);
|
||||
is(gBrowser.selectedTab, testTab, "second tab is the test tab");
|
||||
gBrowser.selectTabAtIndex(2);
|
||||
is(gBrowser.selectedTab, testTab, "no third tab, so no change");
|
||||
gBrowser.selectTabAtIndex(0);
|
||||
is(gBrowser.selectedTab, pinned, "switch back to the pinned");
|
||||
gBrowser.selectTabAtIndex(2);
|
||||
is(gBrowser.selectedTab, pinned, "no third tab, so no change");
|
||||
gBrowser.selectTabAtIndex(-1);
|
||||
is(gBrowser.selectedTab, testTab, "last tab is the test tab");
|
||||
|
||||
gBrowser.tabContainer.advanceSelectedTab(1, true);
|
||||
is(gBrowser.selectedTab, pinned, "wrapped around the end to pinned");
|
||||
gBrowser.tabContainer.advanceSelectedTab(1, true);
|
||||
is(gBrowser.selectedTab, testTab, "next to test tab");
|
||||
gBrowser.tabContainer.advanceSelectedTab(1, true);
|
||||
is(gBrowser.selectedTab, pinned, "next to pinned again");
|
||||
|
||||
gBrowser.tabContainer.advanceSelectedTab(-1, true);
|
||||
is(gBrowser.selectedTab, testTab, "going backwards to last tab");
|
||||
gBrowser.tabContainer.advanceSelectedTab(-1, true);
|
||||
is(gBrowser.selectedTab, pinned, "next to pinned");
|
||||
gBrowser.tabContainer.advanceSelectedTab(-1, true);
|
||||
is(gBrowser.selectedTab, testTab, "next to test tab again");
|
||||
|
||||
// Try showing all tabs
|
||||
gBrowser.showOnlyTheseTabs(Array.slice(gBrowser.tabs));
|
||||
is(gBrowser.visibleTabs.length, 3, "all 3 tabs are visible again");
|
||||
|
||||
// Select the pinned tab and show the testTab to make sure selection updates
|
||||
gBrowser.selectedTab = pinned;
|
||||
gBrowser.showOnlyTheseTabs([testTab]);
|
||||
is(gBrowser.tabs[1], origTab, "make sure origTab is in the middle");
|
||||
is(origTab.hidden, true, "make sure it's hidden");
|
||||
gBrowser.removeTab(pinned);
|
||||
is(gBrowser.selectedTab, testTab, "making sure origTab was skipped");
|
||||
is(gBrowser.visibleTabs.length, 1, "only testTab is there");
|
||||
|
||||
// Only show one of the non-pinned tabs (but testTab is selected)
|
||||
gBrowser.showOnlyTheseTabs([origTab]);
|
||||
is(gBrowser.visibleTabs.length, 2, "got 2 tabs");
|
||||
|
||||
// Now really only show one of the tabs
|
||||
gBrowser.showOnlyTheseTabs([testTab]);
|
||||
visible = gBrowser.visibleTabs;
|
||||
is(visible.length, 1, "only the original tab is visible");
|
||||
is(visible[0], testTab, "it's the original tab");
|
||||
is(gBrowser.tabs.length, 2, "still have 2 open tabs");
|
||||
|
||||
// Close the last visible tab and make sure we still get a visible tab
|
||||
gBrowser.removeTab(testTab);
|
||||
is(gBrowser.visibleTabs.length, 1, "only orig is left and visible");
|
||||
is(gBrowser.tabs.length, 1, "sanity check that it matches");
|
||||
is(gBrowser.selectedTab, origTab, "got the orig tab");
|
||||
is(origTab.hidden, false, "and it's not hidden -- visible!");
|
||||
}
|
@ -52,6 +52,11 @@ const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
return NetUtil;
|
||||
});
|
||||
|
||||
const PREF_EM_NEW_ADDONS_LIST = "extensions.newAddons";
|
||||
const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser";
|
||||
const PREF_PLUGINS_UPDATEURL = "plugins.update.url";
|
||||
@ -840,16 +845,18 @@ BrowserGlue.prototype = {
|
||||
var dirService = Cc["@mozilla.org/file/directory_service;1"].
|
||||
getService(Ci.nsIProperties);
|
||||
|
||||
var bookmarksFile = null;
|
||||
var bookmarksURI = null;
|
||||
if (restoreDefaultBookmarks) {
|
||||
// User wants to restore bookmarks.html file from default profile folder
|
||||
bookmarksFile = dirService.get("profDef", Ci.nsILocalFile);
|
||||
bookmarksFile.append("bookmarks.html");
|
||||
bookmarksURI = NetUtil.newURI("resource:///defaults/profile/bookmarks.html");
|
||||
}
|
||||
else {
|
||||
var bookmarksFile = dirService.get("BMarks", Ci.nsILocalFile);
|
||||
if (bookmarksFile.exists())
|
||||
bookmarksURI = NetUtil.newURI(bookmarksFile);
|
||||
}
|
||||
else
|
||||
bookmarksFile = dirService.get("BMarks", Ci.nsILocalFile);
|
||||
|
||||
if (bookmarksFile.exists()) {
|
||||
if (bookmarksURI) {
|
||||
// Add an import observer. It will ensure that smart bookmarks are
|
||||
// created once the operation is complete.
|
||||
Services.obs.addObserver(this, "bookmarks-restore-success", false);
|
||||
@ -859,7 +866,7 @@ BrowserGlue.prototype = {
|
||||
try {
|
||||
var importer = Cc["@mozilla.org/browser/places/import-export-service;1"].
|
||||
getService(Ci.nsIPlacesImportExportService);
|
||||
importer.importHTMLFromFile(bookmarksFile, true /* overwrite existing */);
|
||||
importer.importHTMLFromURI(bookmarksURI, true /* overwrite existing */);
|
||||
} catch (err) {
|
||||
// Report the error, but ignore it.
|
||||
Cu.reportError("Bookmarks.html file could be corrupt. " + err);
|
||||
|
@ -50,7 +50,7 @@ const RELOAD_ACTION_NOTHING = 0;
|
||||
const RELOAD_ACTION_INSERT = 1;
|
||||
// Removing items from the view, select the first item after the last selected
|
||||
const RELOAD_ACTION_REMOVE = 2;
|
||||
// Moving items within a view, don't treat the dropped items as additional
|
||||
// Moving items within a view, don't treat the dropped items as additional
|
||||
// rows.
|
||||
const RELOAD_ACTION_MOVE = 3;
|
||||
|
||||
@ -67,7 +67,7 @@ const REMOVE_PAGES_MAX_SINGLEREMOVES = 10;
|
||||
|
||||
/**
|
||||
* Represents an insertion point within a container where we can insert
|
||||
* items.
|
||||
* items.
|
||||
* @param aItemId
|
||||
* The identifier of the parent container
|
||||
* @param aIndex
|
||||
@ -139,7 +139,7 @@ PlacesController.prototype = {
|
||||
return true;
|
||||
}
|
||||
|
||||
// All other Places Commands are prefixed with "placesCmd_" ... this
|
||||
// All other Places Commands are prefixed with "placesCmd_" ... this
|
||||
// filters out other commands that we do _not_ support (see 329587).
|
||||
const CMD_PREFIX = "placesCmd_";
|
||||
return (aCommand.substr(0, CMD_PREFIX.length) == CMD_PREFIX);
|
||||
@ -178,7 +178,7 @@ PlacesController.prototype = {
|
||||
if (this._view.selType != "single") {
|
||||
let rootNode = this._view.result.root;
|
||||
if (rootNode.containerOpen && rootNode.childCount > 0)
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case "placesCmd_open":
|
||||
@ -308,9 +308,9 @@ PlacesController.prototype = {
|
||||
|
||||
onEvent: function PC_onEvent(eventName) { },
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Determine whether or not the selection can be removed, either by the
|
||||
* Determine whether or not the selection can be removed, either by the
|
||||
* delete or cut operations based on whether or not any of its contents
|
||||
* are non-removable. We don't need to worry about recursion here since it
|
||||
* is a policy decision that a removable item not be placed inside a non-
|
||||
@ -373,14 +373,14 @@ PlacesController.prototype = {
|
||||
var root = this._view.result.root;
|
||||
for (var i = 0; i < nodes.length; ++i) {
|
||||
if (nodes[i] == root)
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Looks at the data on the clipboard to see if it is paste-able.
|
||||
* Looks at the data on the clipboard to see if it is paste-able.
|
||||
* Paste-able data is:
|
||||
* - in a format that the view can receive
|
||||
* @returns true if: - clipboard data is of a TYPE_X_MOZ_PLACE_* flavor,
|
||||
@ -427,7 +427,7 @@ PlacesController.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
/**
|
||||
* Gathers information about the selected nodes according to the following
|
||||
* rules:
|
||||
* "link" node is a URI
|
||||
@ -442,7 +442,7 @@ PlacesController.prototype = {
|
||||
*
|
||||
* @returns an array of objects corresponding the selected nodes. Each
|
||||
* object has each of the properties above set if its corresponding
|
||||
* node matches the rule. In addition, the annotations names for each
|
||||
* node matches the rule. In addition, the annotations names for each
|
||||
* node are set on its corresponding object as properties.
|
||||
* Notes:
|
||||
* 1) This can be slow, so don't call it anywhere performance critical!
|
||||
@ -456,7 +456,7 @@ PlacesController.prototype = {
|
||||
if (nodes.length == 0)
|
||||
nodes.push(root); // See the second note above
|
||||
|
||||
for (var i=0; i < nodes.length; i++) {
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
var nodeData = {};
|
||||
var node = nodes[i];
|
||||
var nodeType = node.type;
|
||||
@ -514,16 +514,16 @@ PlacesController.prototype = {
|
||||
|
||||
// annotations
|
||||
if (uri) {
|
||||
var names = PlacesUtils.annotations.getPageAnnotationNames(uri);
|
||||
for (var j = 0; j < names.length; ++j)
|
||||
let names = PlacesUtils.annotations.getPageAnnotationNames(uri);
|
||||
for (let j = 0; j < names.length; ++j)
|
||||
nodeData[names[j]] = true;
|
||||
}
|
||||
|
||||
// For items also include the item-specific annotations
|
||||
if (node.itemId != -1) {
|
||||
names = PlacesUtils.annotations
|
||||
.getItemAnnotationNames(node.itemId);
|
||||
for (j = 0; j < names.length; ++j)
|
||||
let names = PlacesUtils.annotations
|
||||
.getItemAnnotationNames(node.itemId);
|
||||
for (let j = 0; j < names.length; ++j)
|
||||
nodeData[names[j]] = true;
|
||||
}
|
||||
metadata.push(nodeData);
|
||||
@ -532,14 +532,14 @@ PlacesController.prototype = {
|
||||
return metadata;
|
||||
},
|
||||
|
||||
/**
|
||||
/**
|
||||
* Determines if a context-menu item should be shown
|
||||
* @param aMenuItem
|
||||
* the context menu item
|
||||
* the context menu item
|
||||
* @param aMetaData
|
||||
* meta data about the selection
|
||||
* @returns true if the conditions (see buildContextMenu) are satisfied
|
||||
* and the item can be displayed, false otherwise.
|
||||
* and the item can be displayed, false otherwise.
|
||||
*/
|
||||
_shouldShowMenuItem: function PC__shouldShowMenuItem(aMenuItem, aMetaData) {
|
||||
var selectiontype = aMenuItem.getAttribute("selectiontype");
|
||||
@ -551,8 +551,8 @@ PlacesController.prototype = {
|
||||
var forceHideAttr = aMenuItem.getAttribute("forcehideselection");
|
||||
if (forceHideAttr) {
|
||||
var forceHideRules = forceHideAttr.split("|");
|
||||
for (var i = 0; i < aMetaData.length; ++i) {
|
||||
for (var j=0; j < forceHideRules.length; ++j) {
|
||||
for (let i = 0; i < aMetaData.length; ++i) {
|
||||
for (let j = 0; j < forceHideRules.length; ++j) {
|
||||
if (forceHideRules[j] in aMetaData[i])
|
||||
return false;
|
||||
}
|
||||
@ -682,7 +682,7 @@ PlacesController.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Select all links in the current view.
|
||||
* Select all links in the current view.
|
||||
*/
|
||||
selectAll: function PC_selectAll() {
|
||||
this._view.selectAll();
|
||||
@ -691,7 +691,7 @@ PlacesController.prototype = {
|
||||
/**
|
||||
* Opens the bookmark properties for the selected URI Node.
|
||||
*/
|
||||
showBookmarkPropertiesForSelection:
|
||||
showBookmarkPropertiesForSelection:
|
||||
function PC_showBookmarkPropertiesForSelection() {
|
||||
var node = this._view.selectedNode;
|
||||
if (!node)
|
||||
@ -717,7 +717,7 @@ PlacesController.prototype = {
|
||||
* receive a string instead of an nsIURI object.
|
||||
*/
|
||||
_assertURINotString: function PC__assertURINotString(value) {
|
||||
NS_ASSERT((typeof(value) == "object") && !(value instanceof String),
|
||||
NS_ASSERT((typeof(value) == "object") && !(value instanceof String),
|
||||
"This method should be passed a URI as a nsIURI object, not as a string.");
|
||||
},
|
||||
|
||||
@ -759,16 +759,15 @@ PlacesController.prototype = {
|
||||
|
||||
var messageKey = "tabs.openWarningMultipleBranded";
|
||||
var openKey = "tabs.openButtonMultiple";
|
||||
var strings = document.getElementById("placeBundle");
|
||||
const BRANDING_BUNDLE_URI = "chrome://branding/locale/brand.properties";
|
||||
var brandShortName = Cc["@mozilla.org/intl/stringbundle;1"].
|
||||
getService(Ci.nsIStringBundleService).
|
||||
createBundle(BRANDING_BUNDLE_URI).
|
||||
GetStringFromName("brandShortName");
|
||||
|
||||
|
||||
var buttonPressed = promptService.confirmEx(window,
|
||||
PlacesUIUtils.getString("tabs.openWarningTitle"),
|
||||
PlacesUIUtils.getFormattedString(messageKey,
|
||||
PlacesUIUtils.getFormattedString(messageKey,
|
||||
[numTabsToOpen, brandShortName]),
|
||||
(promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0)
|
||||
+ (promptService.BUTTON_TITLE_CANCEL * promptService.BUTTON_POS_1),
|
||||
@ -788,7 +787,7 @@ PlacesController.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Opens the links in the selected folder, or the selected links in new tabs.
|
||||
* Opens the links in the selected folder, or the selected links in new tabs.
|
||||
*/
|
||||
openSelectionInTabs: function PC_openLinksInTabs(aEvent) {
|
||||
var node = this._view.selectedNode;
|
||||
@ -828,7 +827,7 @@ PlacesController.prototype = {
|
||||
|
||||
/**
|
||||
* Create a new Bookmark folder somewhere. Prompts the user for the name
|
||||
* of the folder.
|
||||
* of the folder.
|
||||
*/
|
||||
newFolder: function PC_newFolder() {
|
||||
var ip = this._view.insertionPoint;
|
||||
@ -880,17 +879,17 @@ PlacesController.prototype = {
|
||||
|
||||
/**
|
||||
* Walk the list of folders we're removing in this delete operation, and
|
||||
* see if the selected node specified is already implicitly being removed
|
||||
* because it is a child of that folder.
|
||||
* see if the selected node specified is already implicitly being removed
|
||||
* because it is a child of that folder.
|
||||
* @param node
|
||||
* Node to check for containment.
|
||||
* Node to check for containment.
|
||||
* @param pastFolders
|
||||
* List of folders the calling function has already traversed
|
||||
* @returns true if the node should be skipped, false otherwise.
|
||||
* @returns true if the node should be skipped, false otherwise.
|
||||
*/
|
||||
_shouldSkipNode: function PC_shouldSkipNode(node, pastFolders) {
|
||||
/**
|
||||
* Determines if a node is contained by another node within a resultset.
|
||||
* Determines if a node is contained by another node within a resultset.
|
||||
* @param node
|
||||
* The node to check for containment for
|
||||
* @param parent
|
||||
@ -906,7 +905,7 @@ PlacesController.prototype = {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
for (var j = 0; j < pastFolders.length; ++j) {
|
||||
if (isContainedBy(node, pastFolders[j]))
|
||||
return true;
|
||||
@ -915,10 +914,10 @@ PlacesController.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a set of transactions for the removal of a range of items.
|
||||
* Creates a set of transactions for the removal of a range of items.
|
||||
* A range is an array of adjacent nodes in a view.
|
||||
* @param [in] range
|
||||
* An array of nodes to remove. Should all be adjacent.
|
||||
* An array of nodes to remove. Should all be adjacent.
|
||||
* @param [out] transactions
|
||||
* An array of transactions.
|
||||
* @param [optional] removedFolders
|
||||
@ -1090,7 +1089,7 @@ PlacesController.prototype = {
|
||||
|
||||
var root = this._view.result.root;
|
||||
|
||||
if (PlacesUtils.nodeIsFolder(root))
|
||||
if (PlacesUtils.nodeIsFolder(root))
|
||||
this._removeRowsFromBookmarks(aTxnName);
|
||||
else if (PlacesUtils.nodeIsQuery(root)) {
|
||||
var queryType = PlacesUtils.asQuery(root).queryOptions.queryType;
|
||||
@ -1136,7 +1135,7 @@ PlacesController.prototype = {
|
||||
addData(PlacesUtils.TYPE_HTML, index, overrideURI);
|
||||
}
|
||||
|
||||
// This order is _important_! It controls how this and other
|
||||
// This order is _important_! It controls how this and other
|
||||
// applications select data to be inserted based on type.
|
||||
addData(PlacesUtils.TYPE_X_MOZ_PLACE, i);
|
||||
|
||||
@ -1166,8 +1165,8 @@ PlacesController.prototype = {
|
||||
try {
|
||||
let nodes = this._view.selectedNodes;
|
||||
|
||||
let xferable = Cc["@mozilla.org/widget/transferable;1"].
|
||||
createInstance(Ci.nsITransferable);
|
||||
let xferable = Cc["@mozilla.org/widget/transferable;1"].
|
||||
createInstance(Ci.nsITransferable);
|
||||
let foundFolder = false, foundLink = false;
|
||||
let copiedFolders = [];
|
||||
let placeString, mozURLString, htmlString, unicodeString;
|
||||
@ -1179,11 +1178,11 @@ PlacesController.prototype = {
|
||||
continue;
|
||||
if (PlacesUtils.nodeIsFolder(node))
|
||||
copiedFolders.push(node);
|
||||
|
||||
|
||||
function generateChunk(type, overrideURI) {
|
||||
let suffix = i < (nodes.length - 1) ? PlacesUtils.endl : "";
|
||||
let uri = overrideURI;
|
||||
|
||||
|
||||
if (PlacesUtils.nodeIsLivemarkContainer(node))
|
||||
uri = PlacesUtils.livemarks.getFeedURI(node.itemId).spec
|
||||
|
||||
@ -1194,8 +1193,8 @@ PlacesController.prototype = {
|
||||
htmlString += (PlacesUtils.wrapNode(node, PlacesUtils.TYPE_HTML,
|
||||
uri) + suffix);
|
||||
|
||||
var placeSuffix = i < (nodes.length - 1) ? "," : "";
|
||||
var resolveShortcuts = !PlacesControllerDragHelper.canMoveNode(node);
|
||||
let placeSuffix = i < (nodes.length - 1) ? "," : "";
|
||||
let resolveShortcuts = !PlacesControllerDragHelper.canMoveNode(node);
|
||||
return PlacesUtils.wrapNode(node, type, overrideURI, resolveShortcuts) + placeSuffix;
|
||||
}
|
||||
|
||||
@ -1207,7 +1206,7 @@ PlacesController.prototype = {
|
||||
xferable.addDataFlavor(type);
|
||||
xferable.setTransferData(type, PlacesUIUtils._wrapString(data), data.length * 2);
|
||||
}
|
||||
// This order is _important_! It controls how this and other applications
|
||||
// This order is _important_! It controls how this and other applications
|
||||
// select data to be inserted based on type.
|
||||
if (placeString)
|
||||
addData(PlacesUtils.TYPE_X_MOZ_PLACE, placeString);
|
||||
@ -1241,11 +1240,11 @@ PlacesController.prototype = {
|
||||
*/
|
||||
paste: function PC_paste() {
|
||||
// Strategy:
|
||||
//
|
||||
// There can be data of various types (folder, separator, link) on the
|
||||
//
|
||||
// There can be data of various types (folder, separator, link) on the
|
||||
// clipboard. We need to get all of that data and build edit transactions
|
||||
// for them. This means asking the clipboard once for each type and
|
||||
// aggregating the results.
|
||||
// for them. This means asking the clipboard once for each type and
|
||||
// aggregating the results.
|
||||
|
||||
/**
|
||||
* Constructs a transferable that can receive data of specific types.
|
||||
@ -1255,10 +1254,9 @@ PlacesController.prototype = {
|
||||
* @returns The transferable.
|
||||
*/
|
||||
function makeXferable(types) {
|
||||
var xferable =
|
||||
Cc["@mozilla.org/widget/transferable;1"].
|
||||
createInstance(Ci.nsITransferable);
|
||||
for (var i = 0; i < types.length; ++i)
|
||||
var xferable = Cc["@mozilla.org/widget/transferable;1"].
|
||||
createInstance(Ci.nsITransferable);
|
||||
for (var i = 0; i < types.length; ++i)
|
||||
xferable.addDataFlavor(types[i]);
|
||||
return xferable;
|
||||
}
|
||||
@ -1291,10 +1289,10 @@ PlacesController.prototype = {
|
||||
if (ip.isTag) {
|
||||
var uri = PlacesUtils._uri(items[i].uri);
|
||||
txn = PlacesUIUtils.ptm.tagURI(uri, [ip.itemId]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// adjusted to make sure that items are given the correct index
|
||||
// transactions insert differently if index == -1
|
||||
// transactions insert differently if index == -1
|
||||
// transaction will enqueue the item.
|
||||
if (ip.index > -1)
|
||||
index = ip.index + i;
|
||||
@ -1307,18 +1305,18 @@ PlacesController.prototype = {
|
||||
}
|
||||
catch (e) {
|
||||
// getAnyTransferData will throw if there is no data of the specified
|
||||
// type on the clipboard.
|
||||
// type on the clipboard.
|
||||
// unwrapNodes will throw if the data that is present is malformed in
|
||||
// some way.
|
||||
// some way.
|
||||
// In either case, don't fail horribly, just return no data.
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
// Get transactions to paste any folders, separators or links that might
|
||||
// be on the clipboard, aggregate them and execute them.
|
||||
// be on the clipboard, aggregate them and execute them.
|
||||
var transactions = getTransactions([PlacesUtils.TYPE_X_MOZ_PLACE,
|
||||
PlacesUtils.TYPE_X_MOZ_URL,
|
||||
PlacesUtils.TYPE_X_MOZ_URL,
|
||||
PlacesUtils.TYPE_UNICODE]);
|
||||
var txn = PlacesUIUtils.ptm.aggregateTransactions("Paste", transactions);
|
||||
PlacesUIUtils.ptm.doTransaction(txn);
|
||||
@ -1336,8 +1334,8 @@ PlacesController.prototype = {
|
||||
/**
|
||||
* Handles drag and drop operations for views. Note that this is view agnostic!
|
||||
* You should not use PlacesController._view within these methods, since
|
||||
* the view that the item(s) have been dropped on was not necessarily active.
|
||||
* Drop functions are passed the view that is being dropped on.
|
||||
* the view that the item(s) have been dropped on was not necessarily active.
|
||||
* Drop functions are passed the view that is being dropped on.
|
||||
*/
|
||||
let PlacesControllerDragHelper = {
|
||||
/**
|
||||
@ -1416,7 +1414,8 @@ let PlacesControllerDragHelper = {
|
||||
let dragged;
|
||||
try {
|
||||
dragged = PlacesUtils.unwrapNodes(data, flavor)[0];
|
||||
} catch (e) {
|
||||
}
|
||||
catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1442,10 +1441,10 @@ let PlacesControllerDragHelper = {
|
||||
return true;
|
||||
},
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Determines if a node can be moved.
|
||||
*
|
||||
*
|
||||
* @param aNode
|
||||
* A nsINavHistoryResultNode node.
|
||||
* @returns True if the node can be moved, false otherwise.
|
||||
@ -1477,7 +1476,7 @@ let PlacesControllerDragHelper = {
|
||||
|
||||
/**
|
||||
* Determines if a container node can be moved.
|
||||
*
|
||||
*
|
||||
* @param aId
|
||||
* A bookmark folder id.
|
||||
* @param [optional] aParentId
|
||||
|
@ -132,6 +132,6 @@ var SidebarUtils = {
|
||||
},
|
||||
|
||||
clearURLFromStatusBar: function SU_clearURLFromStatusBar() {
|
||||
window.top.XULBrowserWindow.setOverLink("", null);
|
||||
window.top.XULBrowserWindow.setOverLink("", null);
|
||||
}
|
||||
};
|
||||
|
@ -780,4 +780,3 @@
|
||||
</binding>
|
||||
|
||||
</bindings>
|
||||
|
||||
|
@ -37,11 +37,21 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function PlacesTreeView(aFlatList, aOnOpenFlatContainer) {
|
||||
this._tree = null;
|
||||
this._result = null;
|
||||
this._selection = null;
|
||||
this._rootNode = null;
|
||||
this._rows = [];
|
||||
this._flatList = aFlatList;
|
||||
this._openContainerCallback = aOnOpenFlatContainer;
|
||||
}
|
||||
|
||||
PlacesTreeView.prototype = {
|
||||
_makeAtom: function PTV__makeAtom(aString) {
|
||||
return Cc["@mozilla.org/atom-service;1"].
|
||||
getService(Ci.nsIAtomService).
|
||||
getAtom(aString);
|
||||
return Cc["@mozilla.org/atom-service;1"].
|
||||
getService(Ci.nsIAtomService).
|
||||
getAtom(aString);
|
||||
},
|
||||
|
||||
_atoms: [],
|
||||
@ -122,8 +132,7 @@ PlacesTreeView.prototype = {
|
||||
if (!(aContainer instanceof Ci.nsINavHistoryQueryResultNode))
|
||||
return aContainer._plainContainer = false;
|
||||
|
||||
let resultType = aContainer.queryOptions.resultType;
|
||||
switch (resultType) {
|
||||
switch (aContainer.queryOptions.resultType) {
|
||||
case Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_QUERY:
|
||||
case Ci.nsINavHistoryQueryOptions.RESULTS_AS_SITE_QUERY:
|
||||
case Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_SITE_QUERY:
|
||||
@ -602,8 +611,7 @@ PlacesTreeView.prototype = {
|
||||
return;
|
||||
|
||||
// Bail out for hidden separators.
|
||||
if (PlacesUtils.nodeIsSeparator(aNode) &&
|
||||
this._result.sortingMode != Ci.nsINavHistoryQueryOptions.SORT_BY_NONE)
|
||||
if (PlacesUtils.nodeIsSeparator(aNode) && this.isSorted())
|
||||
return;
|
||||
|
||||
let parentRow;
|
||||
@ -632,7 +640,7 @@ PlacesTreeView.prototype = {
|
||||
// children themselves that would be in the way.
|
||||
let cc = aParentNode.childCount;
|
||||
let separatorsAreHidden = PlacesUtils.nodeIsSeparator(aNode) &&
|
||||
this._result.sortingMode != Ci.nsINavHistoryQueryOptions.SORT_BY_NONE;
|
||||
this.isSorted();
|
||||
for (let i = aNewIndex + 1; i < cc; i++) {
|
||||
let node = aParentNode.getChild(i);
|
||||
if (!separatorsAreHidden || PlacesUtils.nodeIsSeparator(node)) {
|
||||
@ -679,8 +687,7 @@ PlacesTreeView.prototype = {
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
// Bail out for hidden separators.
|
||||
if (PlacesUtils.nodeIsSeparator(aNode) &&
|
||||
this._result.sortingMode != Ci.nsINavHistoryQueryOptions.SORT_BY_NONE)
|
||||
if (PlacesUtils.nodeIsSeparator(aNode) && this.isSorted())
|
||||
return;
|
||||
|
||||
let parentRow = aParentNode == this._rootNode ?
|
||||
@ -728,8 +735,7 @@ PlacesTreeView.prototype = {
|
||||
return;
|
||||
|
||||
// Bail out for hidden separators.
|
||||
if (PlacesUtils.nodeIsSeparator(aNode) &&
|
||||
this._result.sortingMode != Ci.nsINavHistoryQueryOptions.SORT_BY_NONE)
|
||||
if (PlacesUtils.nodeIsSeparator(aNode) && this.isSorted())
|
||||
return;
|
||||
|
||||
let oldRow = this._getRowForNode(aNode, true);
|
||||
@ -1204,7 +1210,7 @@ PlacesTreeView.prototype = {
|
||||
else {
|
||||
// Use the last-selected node's container.
|
||||
container = lastSelected.parent;
|
||||
|
||||
|
||||
// During its Drag & Drop operation, the tree code closes-and-opens
|
||||
// containers very often (part of the XUL "spring-loaded folders"
|
||||
// implementation). And in certain cases, we may reach a closed
|
||||
@ -1309,8 +1315,7 @@ PlacesTreeView.prototype = {
|
||||
|
||||
getCellText: function PTV_getCellText(aRow, aColumn) {
|
||||
let node = this._getNodeForRow(aRow);
|
||||
let columnType = this._getColumnType(aColumn);
|
||||
switch (columnType) {
|
||||
switch (this._getColumnType(aColumn)) {
|
||||
case this.COLUMN_TYPE_TITLE:
|
||||
// normally, this is just the title, but we don't want empty items in
|
||||
// the tree view so return a special string if the title is empty.
|
||||
@ -1428,8 +1433,7 @@ PlacesTreeView.prototype = {
|
||||
let newSort;
|
||||
let newSortingAnnotation = "";
|
||||
const NHQO = Ci.nsINavHistoryQueryOptions;
|
||||
let columnType = this._getColumnType(aColumn);
|
||||
switch (columnType) {
|
||||
switch (this._getColumnType(aColumn)) {
|
||||
case this.COLUMN_TYPE_TITLE:
|
||||
if (oldSort == NHQO.SORT_BY_TITLE_ASCENDING)
|
||||
newSort = NHQO.SORT_BY_TITLE_DESCENDING;
|
||||
@ -1576,13 +1580,3 @@ PlacesTreeView.prototype = {
|
||||
performActionOnRow: function(aAction, aRow) { },
|
||||
performActionOnCell: function(aAction, aRow, aColumn) { }
|
||||
};
|
||||
|
||||
function PlacesTreeView(aFlatList, aOnOpenFlatContainer) {
|
||||
this._tree = null;
|
||||
this._result = null;
|
||||
this._selection = null;
|
||||
this._rootNode = null;
|
||||
this._rows = [];
|
||||
this._flatList = aFlatList;
|
||||
this._openContainerCallback = aOnOpenFlatContainer;
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ var PlacesUIUtils = {
|
||||
* @returns A URI object for the spec.
|
||||
*/
|
||||
createFixedURI: function PUIU_createFixedURI(aSpec) {
|
||||
return URIFixup.createFixupURI(aSpec, 0);
|
||||
return URIFixup.createFixupURI(aSpec, Ci.nsIURIFixup.FIXUP_FLAG_NONE);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -128,7 +128,7 @@ var PlacesUIUtils = {
|
||||
*/
|
||||
_getBookmarkItemCopyTransaction:
|
||||
function PUIU__getBookmarkItemCopyTransaction(aData, aContainer, aIndex,
|
||||
aExcludeAnnotations) {
|
||||
aExcludeAnnotations) {
|
||||
var itemURL = PlacesUtils._uri(aData.uri);
|
||||
var itemTitle = aData.title;
|
||||
var keyword = aData.keyword || null;
|
||||
@ -278,7 +278,7 @@ var PlacesUIUtils = {
|
||||
* the move/insert.
|
||||
*/
|
||||
makeTransaction: function PUIU_makeTransaction(data, type, container,
|
||||
index, copy) {
|
||||
index, copy) {
|
||||
switch (data.type) {
|
||||
case PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER:
|
||||
if (copy)
|
||||
@ -289,7 +289,7 @@ var PlacesUIUtils = {
|
||||
case PlacesUtils.TYPE_X_MOZ_PLACE:
|
||||
if (data.id == -1) // Not bookmarked.
|
||||
return this._getURIItemCopyTransaction(data, container, index);
|
||||
|
||||
|
||||
if (copy)
|
||||
return this._getBookmarkItemCopyTransaction(data, container, index);
|
||||
// Otherwise move the item.
|
||||
@ -361,14 +361,14 @@ var PlacesUIUtils = {
|
||||
* bookmarks root folder.
|
||||
*/
|
||||
showAddBookmarkUI: function PUIU_showAddBookmarkUI(aURI,
|
||||
aTitle,
|
||||
aDescription,
|
||||
aDefaultInsertionPoint,
|
||||
aShowPicker,
|
||||
aLoadInSidebar,
|
||||
aKeyword,
|
||||
aPostData,
|
||||
aCharSet) {
|
||||
aTitle,
|
||||
aDescription,
|
||||
aDefaultInsertionPoint,
|
||||
aShowPicker,
|
||||
aLoadInSidebar,
|
||||
aKeyword,
|
||||
aPostData,
|
||||
aCharSet) {
|
||||
var info = {
|
||||
action: "add",
|
||||
type: "bookmark"
|
||||
@ -417,9 +417,9 @@ var PlacesUIUtils = {
|
||||
*/
|
||||
showMinimalAddBookmarkUI:
|
||||
function PUIU_showMinimalAddBookmarkUI(aURI, aTitle, aDescription,
|
||||
aDefaultInsertionPoint, aShowPicker,
|
||||
aLoadInSidebar, aKeyword, aPostData,
|
||||
aCharSet) {
|
||||
aDefaultInsertionPoint, aShowPicker,
|
||||
aLoadInSidebar, aKeyword, aPostData,
|
||||
aCharSet) {
|
||||
var info = {
|
||||
action: "add",
|
||||
type: "bookmark",
|
||||
@ -485,11 +485,11 @@ var PlacesUIUtils = {
|
||||
* bookmarks root folder.
|
||||
*/
|
||||
showAddLivemarkUI: function PUIU_showAddLivemarkURI(aFeedURI,
|
||||
aSiteURI,
|
||||
aTitle,
|
||||
aDescription,
|
||||
aDefaultInsertionPoint,
|
||||
aShowPicker) {
|
||||
aSiteURI,
|
||||
aTitle,
|
||||
aDescription,
|
||||
aDefaultInsertionPoint,
|
||||
aShowPicker) {
|
||||
var info = {
|
||||
action: "add",
|
||||
type: "livemark"
|
||||
@ -525,8 +525,8 @@ var PlacesUIUtils = {
|
||||
*/
|
||||
showMinimalAddLivemarkUI:
|
||||
function PUIU_showMinimalAddLivemarkURI(aFeedURI, aSiteURI, aTitle,
|
||||
aDescription, aDefaultInsertionPoint,
|
||||
aShowPicker) {
|
||||
aDescription, aDefaultInsertionPoint,
|
||||
aShowPicker) {
|
||||
var info = {
|
||||
action: "add",
|
||||
type: "livemark",
|
||||
@ -706,7 +706,7 @@ var PlacesUIUtils = {
|
||||
/**
|
||||
* By calling this before visiting an URL, the visit will be associated to a
|
||||
* TRANSITION_BOOKMARK transition.
|
||||
* This is used when visiting pages from the bookmarks menu,
|
||||
* This is used when visiting pages from the bookmarks menu,
|
||||
* personal toolbar, and bookmarks from within the places organizer.
|
||||
* If this is not called visits will be marked as TRANSITION_LINK.
|
||||
*/
|
||||
@ -730,6 +730,8 @@ var PlacesUIUtils = {
|
||||
* bookmarked (see bug 224521).
|
||||
* @param aURINode
|
||||
* a URI node
|
||||
* @param aWindow
|
||||
* a window on which a potential error alert is shown on.
|
||||
* @return true if it's safe to open the node in the browser, false otherwise.
|
||||
*
|
||||
*/
|
||||
@ -890,7 +892,7 @@ var PlacesUIUtils = {
|
||||
openNodeWithEvent: function PUIU_openNodeWithEvent(aNode, aEvent) {
|
||||
this.openNodeIn(aNode, this._getCurrentActiveWin().whereToOpenLink(aEvent));
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Loads the node's URL in the appropriate tab or window or as a
|
||||
* web panel.
|
||||
@ -927,12 +929,12 @@ var PlacesUIUtils = {
|
||||
* Used to avoid nsIURI overhead in frequently called UI functions.
|
||||
*
|
||||
* @param aUrlString the url to guess the scheme from.
|
||||
*
|
||||
*
|
||||
* @return guessed scheme for this url string.
|
||||
*
|
||||
* @note this is not supposed be perfect, so use it only for UI purposes.
|
||||
*/
|
||||
guessUrlSchemeForUI: function PUU_guessUrlSchemeForUI(aUrlString) {
|
||||
guessUrlSchemeForUI: function PUIU_guessUrlSchemeForUI(aUrlString) {
|
||||
return aUrlString.substr(0, aUrlString.indexOf(":"));
|
||||
},
|
||||
|
||||
@ -961,7 +963,7 @@ var PlacesUIUtils = {
|
||||
return title || this.getString("noTitle");
|
||||
},
|
||||
|
||||
get leftPaneQueries() {
|
||||
get leftPaneQueries() {
|
||||
// build the map
|
||||
this.leftPaneFolderId;
|
||||
return this.leftPaneQueries;
|
||||
@ -1239,7 +1241,7 @@ var PlacesUIUtils = {
|
||||
queryName = name;
|
||||
}
|
||||
}
|
||||
return queryName;
|
||||
return queryName;
|
||||
}
|
||||
};
|
||||
|
||||
@ -1380,7 +1382,7 @@ XPCOMUtils.defineLazyGetter(PlacesUIUtils, "ptm", function() {
|
||||
|
||||
/**
|
||||
* Transaction for editing a the description of a bookmark or a folder.
|
||||
*
|
||||
*
|
||||
* @param aItemId
|
||||
* id of the item to edit.
|
||||
* @param aDescription
|
||||
|
@ -1212,6 +1212,7 @@ SessionStoreService.prototype = {
|
||||
|
||||
if (aTab.pinned)
|
||||
tabData.pinned = true;
|
||||
tabData.hidden = aTab.hidden;
|
||||
|
||||
var disallow = [];
|
||||
for (var i = 0; i < CAPABILITIES.length; i++)
|
||||
@ -1947,6 +1948,7 @@ SessionStoreService.prototype = {
|
||||
tabbrowser.pinTab(tabs[t]);
|
||||
else
|
||||
tabbrowser.unpinTab(tabs[t]);
|
||||
tabs[t].hidden = winData.tabs[t].hidden;
|
||||
}
|
||||
|
||||
// when overwriting tabs, remove all superflous ones
|
||||
@ -2031,6 +2033,7 @@ SessionStoreService.prototype = {
|
||||
tabbrowser.pinTab(tab);
|
||||
else
|
||||
tabbrowser.unpinTab(tab);
|
||||
tab.hidden = tabData.hidden;
|
||||
|
||||
tabData._tabStillLoading = true;
|
||||
if (!tabData.entries || tabData.entries.length == 0) {
|
||||
|
@ -115,6 +115,7 @@ _BROWSER_TEST_FILES = \
|
||||
browser_524745.js \
|
||||
browser_528776.js \
|
||||
browser_579879.js \
|
||||
browser_586147.js \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_BROWSER_TEST_FILES)
|
||||
|
@ -0,0 +1,84 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is sessionstore test code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Edward Lee <edilee@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function observeOneRestore(callback) {
|
||||
let topic = "sessionstore-browser-state-restored";
|
||||
Services.obs.addObserver(function() {
|
||||
Services.obs.removeObserver(arguments.callee, topic, false);
|
||||
callback();
|
||||
}, topic, false);
|
||||
};
|
||||
|
||||
function test() {
|
||||
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
|
||||
waitForExplicitFinish();
|
||||
|
||||
// There should be one tab when we start the test
|
||||
let [origTab] = gBrowser.visibleTabs;
|
||||
let hiddenTab = gBrowser.addTab();
|
||||
|
||||
is(gBrowser.visibleTabs.length, 2, "should have 2 tabs before hiding");
|
||||
gBrowser.showOnlyTheseTabs([origTab]);
|
||||
is(gBrowser.visibleTabs.length, 1, "only 1 after hiding");
|
||||
ok(hiddenTab.hidden, "sanity check that it's hidden");
|
||||
|
||||
let extraTab = gBrowser.addTab();
|
||||
let state = ss.getBrowserState();
|
||||
let stateObj = JSON.parse(state);
|
||||
let tabs = stateObj.windows[0].tabs;
|
||||
is(tabs.length, 3, "just checking that browser state is correct");
|
||||
ok(!tabs[0].hidden, "first tab is visible");
|
||||
ok(tabs[1].hidden, "second is hidden");
|
||||
ok(!tabs[2].hidden, "third is visible");
|
||||
|
||||
// Make the third tab hidden and then restore the modified state object
|
||||
tabs[2].hidden = true;
|
||||
|
||||
observeOneRestore(function() {
|
||||
let testWindow = Services.wm.getEnumerator("navigator:browser").getNext();
|
||||
is(testWindow.gBrowser.visibleTabs.length, 1, "only restored 1 visible tab");
|
||||
let tabs = testWindow.gBrowser.tabs;
|
||||
ok(!tabs[0].hidden, "first is still visible");
|
||||
ok(tabs[1].hidden, "second tab is still hidden");
|
||||
ok(tabs[2].hidden, "third tab is now hidden");
|
||||
|
||||
// Restore the original state and clean up now that we're done
|
||||
gBrowser.removeTab(hiddenTab);
|
||||
gBrowser.removeTab(extraTab);
|
||||
finish();
|
||||
});
|
||||
ss.setBrowserState(JSON.stringify(stateObj));
|
||||
}
|
@ -11,9 +11,9 @@
|
||||
@DLL_PREFIX@zlib@DLL_SUFFIX@
|
||||
LICENSE
|
||||
browserconfig.properties
|
||||
chrome.manifest
|
||||
chrome/US.jar
|
||||
chrome/app-chrome.manifest
|
||||
chrome/browser.manifest
|
||||
chrome/chrome.rdf
|
||||
chrome/chromelist.txt
|
||||
chrome/classic.jar
|
||||
@ -21,14 +21,18 @@ chrome/classic.manifest
|
||||
chrome/comm.jar
|
||||
chrome/comm.manifest
|
||||
chrome/en-win.jar
|
||||
chrome/en-US.manifest
|
||||
chrome/help.jar
|
||||
chrome/installed-chrome.txt
|
||||
chrome/m3ffxtbr.jar
|
||||
chrome/m3ffxtbr.manifest
|
||||
chrome/overlayinfo/
|
||||
chrome/pippki.manifest
|
||||
chrome/reporter.jar
|
||||
chrome/reporter.manifest
|
||||
chrome/toolkit.manifest
|
||||
component.reg
|
||||
components/browser.manifest
|
||||
components/components.list
|
||||
components/@DLL_PREFIX@browserdirprovider@DLL_SUFFIX@
|
||||
components/@DLL_PREFIX@brwsrdir@DLL_SUFFIX@
|
||||
|
@ -878,7 +878,7 @@ toolbar[iconsize="small"] #fullscreen-button {
|
||||
-moz-border-start: 1px solid ThreeDShadow;
|
||||
}
|
||||
|
||||
#identity-box:focus {
|
||||
#identity-box:-moz-focusring {
|
||||
outline: 1px dotted -moz-DialogText;
|
||||
}
|
||||
|
||||
|
@ -699,7 +699,7 @@ toolbar[iconsize="small"][mode="icons"] #forward-button:-moz-locale-dir(rtl) {
|
||||
}
|
||||
|
||||
|
||||
#identity-box:focus:not(:active):not([open="true"]) {
|
||||
#identity-box:-moz-focusring {
|
||||
-moz-box-shadow: 0 0 3px 1px -moz-mac-focusring inset,
|
||||
0 0 3px 2px -moz-mac-focusring;
|
||||
}
|
||||
|
@ -60,11 +60,8 @@
|
||||
|
||||
#navigator-toolbox {
|
||||
-moz-appearance: none;
|
||||
border-top: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#navigator-toolbox[tabsontop="true"] {
|
||||
border-top: none;
|
||||
border-bottom: 1px solid ThreeDShadow;
|
||||
}
|
||||
|
||||
@ -81,7 +78,11 @@
|
||||
}
|
||||
|
||||
#nav-bar:not(:-moz-lwtheme),
|
||||
#navigator-toolbox[tabsontop="true"] > #nav-bar {
|
||||
#nav-bar[collapsed="true"] + toolbar:not(:-moz-lwtheme),
|
||||
#nav-bar[collapsed="true"] + #customToolbars + #PersonalToolbar:not(:-moz-lwtheme),
|
||||
#navigator-toolbox[tabsontop="true"] > #nav-bar,
|
||||
#navigator-toolbox[tabsontop="true"]:not([customizing]) > #nav-bar[collapsed="true"] + toolbar,
|
||||
#navigator-toolbox[tabsontop="true"]:not([customizing]) > #nav-bar[collapsed="true"] + #customToolbars + #PersonalToolbar {
|
||||
background-image: -moz-linear-gradient(@toolbarHighlight@, rgba(255,255,255,0));
|
||||
}
|
||||
|
||||
@ -844,13 +845,13 @@ toolbar:not([iconsize="small"])[mode="icons"] #forward-button:not([disabled="tru
|
||||
background-color: hsl(92,45%,52%);
|
||||
}
|
||||
|
||||
#identity-box:focus {
|
||||
#identity-box:-moz-focusring {
|
||||
outline: 1px dotted -moz-DialogText;
|
||||
outline-offset: -3px;
|
||||
}
|
||||
|
||||
#identity-box.verifiedDomain:focus ,
|
||||
#identity-box.verifiedIdentity:focus {
|
||||
#identity-box.verifiedDomain:-moz-focusring,
|
||||
#identity-box.verifiedIdentity:-moz-focusring {
|
||||
outline-color: white;
|
||||
}
|
||||
|
||||
@ -1115,10 +1116,6 @@ richlistitem[type="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-i
|
||||
-moz-box-shadow: 0 -1px ThreeDShadow inset;
|
||||
}
|
||||
|
||||
#TabsToolbar[tabsontop="false"] {
|
||||
border-bottom: 1px solid ThreeDShadow !important;
|
||||
}
|
||||
|
||||
.tabbrowser-tabs:-moz-system-metric(touch-enabled) {
|
||||
min-height: .73cm;
|
||||
}
|
||||
|
@ -51,5 +51,9 @@ _TEST_FILES = test_bug423375.html \
|
||||
test_bug470804.html \
|
||||
$(NULL)
|
||||
|
||||
test_bug292789.html : % : %.in
|
||||
$(PYTHON) $(topsrcdir)/config/Preprocessor.py \
|
||||
$(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $< > $@
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
|
||||
|
@ -38,7 +38,11 @@ function testScriptSrc(aCallback) {
|
||||
** moved the resource
|
||||
**/
|
||||
var resjs = document.createElement("script");
|
||||
#ifdef MOZ_CHROME_FILE_FORMAT_JAR
|
||||
resjs.src = "jar:resource://gre/chrome/toolkit.jar!/content/mozapps/xpinstall/xpinstallConfirm.js";
|
||||
#else
|
||||
resjs.src = "resource://gre/chrome/toolkit/content/mozapps/xpinstall/xpinstallConfirm.js";
|
||||
#endif
|
||||
resjs.onload = scriptOnload;
|
||||
document.getElementById("content").appendChild(resjs);
|
||||
|
||||
@ -55,7 +59,11 @@ function testScriptSrc(aCallback) {
|
||||
/** <img src=""> tests **/
|
||||
var img_global = "chrome://global/skin/icons/Error.png";
|
||||
var img_mozapps = "chrome://mozapps/skin/passwordmgr/key.png";
|
||||
#ifdef MOZ_CHROME_FILE_FORMAT_JAR
|
||||
var res_mozapps = "jar:resource://gre/chrome/toolkit.jar!/skin/classic/mozapps/passwordmgr/key.png";
|
||||
#else
|
||||
var res_mozapps = "resource://gre/chrome/toolkit/skin/classic/mozapps/passwordmgr/key.png";
|
||||
#endif
|
||||
|
||||
var imgTests = [[img_global, "success"],
|
||||
[img_mozapps, "fail"],
|
@ -1036,4 +1036,7 @@ event.h
|
||||
#ifdef MOZ_ENABLE_LIBPROXY
|
||||
proxy.h
|
||||
#endif
|
||||
#if MOZ_PLATFORM_MAEMO==6
|
||||
contentaction/contentaction.h
|
||||
#endif
|
||||
|
||||
|
@ -437,7 +437,7 @@ public:
|
||||
nsIViewManager* aViewManager,
|
||||
nsStyleSet* aStyleSet,
|
||||
nsIPresShell** aInstancePtrResult) = 0;
|
||||
void DeleteShell() { mPresShell = nsnull; }
|
||||
virtual void DeleteShell() = 0;
|
||||
|
||||
nsIPresShell* GetShell() const
|
||||
{
|
||||
|
@ -249,7 +249,7 @@ nsAttrValue::SetTo(const nsAttrValue& aOther)
|
||||
case eAtomArray:
|
||||
{
|
||||
if (!EnsureEmptyAtomArray() ||
|
||||
!GetAtomArrayValue()->AppendObjects(*otherCont->mAtomArray)) {
|
||||
!GetAtomArrayValue()->AppendElements(*otherCont->mAtomArray)) {
|
||||
Reset();
|
||||
return;
|
||||
}
|
||||
@ -503,7 +503,7 @@ nsAttrValue::GetEnumString(nsAString& aResult, PRBool aRealTag) const
|
||||
NS_NOTREACHED("couldn't find value in EnumTable");
|
||||
}
|
||||
|
||||
PRInt32
|
||||
PRUint32
|
||||
nsAttrValue::GetAtomCount() const
|
||||
{
|
||||
ValueType type = Type();
|
||||
@ -513,7 +513,7 @@ nsAttrValue::GetAtomCount() const
|
||||
}
|
||||
|
||||
if (type == eAtomArray) {
|
||||
return GetAtomArrayValue()->Count();
|
||||
return GetAtomArrayValue()->Length();
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -531,7 +531,7 @@ nsAttrValue::AtomAt(PRInt32 aIndex) const
|
||||
|
||||
NS_ASSERTION(Type() == eAtomArray, "GetAtomCount must be confused");
|
||||
|
||||
return GetAtomArrayValue()->ObjectAt(aIndex);
|
||||
return GetAtomArrayValue()->ElementAt(aIndex);
|
||||
}
|
||||
|
||||
PRUint32
|
||||
@ -592,9 +592,11 @@ nsAttrValue::HashValue() const
|
||||
case eAtomArray:
|
||||
{
|
||||
PRUint32 retval = 0;
|
||||
PRInt32 i, count = cont->mAtomArray->Count();
|
||||
for (i = 0; i < count; ++i) {
|
||||
retval ^= NS_PTR_TO_INT32(cont->mAtomArray->ObjectAt(i));
|
||||
PRUint32 count = cont->mAtomArray->Length();
|
||||
for (nsCOMPtr<nsIAtom> *cur = cont->mAtomArray->Elements(),
|
||||
*end = cur + count;
|
||||
cur != end; ++cur) {
|
||||
retval ^= NS_PTR_TO_INT32(cur->get());
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
@ -690,18 +692,10 @@ nsAttrValue::Equals(const nsAttrValue& aOther) const
|
||||
// For classlists we could be insensitive to order, however
|
||||
// classlists are never mapped attributes so they are never compared.
|
||||
|
||||
PRInt32 count = thisCont->mAtomArray->Count();
|
||||
if (count != otherCont->mAtomArray->Count()) {
|
||||
if (!(*thisCont->mAtomArray == *otherCont->mAtomArray)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRInt32 i;
|
||||
for (i = 0; i < count; ++i) {
|
||||
if (thisCont->mAtomArray->ObjectAt(i) !=
|
||||
otherCont->mAtomArray->ObjectAt(i)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
needsStringComparison = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
@ -827,19 +821,21 @@ nsAttrValue::Contains(nsIAtom* aValue, nsCaseTreatment aCaseSensitive) const
|
||||
default:
|
||||
{
|
||||
if (Type() == eAtomArray) {
|
||||
nsCOMArray<nsIAtom>* array = GetAtomArrayValue();
|
||||
AtomArray* array = GetAtomArrayValue();
|
||||
if (aCaseSensitive == eCaseMatters) {
|
||||
return array->IndexOf(aValue) >= 0;
|
||||
return array->IndexOf(aValue) != AtomArray::NoIndex;
|
||||
}
|
||||
|
||||
nsDependentAtomString val1(aValue);
|
||||
|
||||
for (PRInt32 i = 0, count = array->Count(); i < count; ++i) {
|
||||
for (nsCOMPtr<nsIAtom> *cur = array->Elements(),
|
||||
*end = cur + array->Length();
|
||||
cur != end; ++cur) {
|
||||
// For performance reasons, don't do a full on unicode case
|
||||
// insensitive string comparison. This is only used for quirks mode
|
||||
// anyway.
|
||||
if (nsContentUtils::EqualsIgnoreASCIICase(val1,
|
||||
nsDependentAtomString(array->ObjectAt(i)))) {
|
||||
nsDependentAtomString(*cur))) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
@ -913,9 +909,9 @@ nsAttrValue::ParseAtomArray(const nsAString& aValue)
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMArray<nsIAtom>* array = GetAtomArrayValue();
|
||||
AtomArray* array = GetAtomArrayValue();
|
||||
|
||||
if (!array->AppendObject(classAtom)) {
|
||||
if (!array->AppendElement(classAtom)) {
|
||||
Reset();
|
||||
return;
|
||||
}
|
||||
@ -930,7 +926,7 @@ nsAttrValue::ParseAtomArray(const nsAString& aValue)
|
||||
|
||||
classAtom = do_GetAtom(Substring(start, iter));
|
||||
|
||||
if (!array->AppendObject(classAtom)) {
|
||||
if (!array->AppendElement(classAtom)) {
|
||||
Reset();
|
||||
return;
|
||||
}
|
||||
@ -1362,7 +1358,7 @@ nsAttrValue::EnsureEmptyAtomArray()
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsCOMArray<nsIAtom>* array = new nsCOMArray<nsIAtom>;
|
||||
AtomArray* array = new AtomArray;
|
||||
if (!array) {
|
||||
Reset();
|
||||
return PR_FALSE;
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "nsColor.h"
|
||||
#include "nsCaseTreatment.h"
|
||||
#include "nsMargin.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
typedef PRUptrdiff PtrBits;
|
||||
class nsAString;
|
||||
@ -57,7 +58,7 @@ class nsIAtom;
|
||||
class nsICSSStyleRule;
|
||||
class nsISVGValue;
|
||||
class nsIDocument;
|
||||
template<class E> class nsCOMArray;
|
||||
template<class E> class nsTArray;
|
||||
template<class E> class nsTPtrArray;
|
||||
|
||||
#define NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM 12
|
||||
@ -92,6 +93,8 @@ public:
|
||||
|
||||
class nsAttrValue {
|
||||
public:
|
||||
typedef nsTArray< nsCOMPtr<nsIAtom> > AtomArray;
|
||||
|
||||
nsAttrValue();
|
||||
nsAttrValue(const nsAttrValue& aOther);
|
||||
explicit nsAttrValue(const nsAString& aValue);
|
||||
@ -151,7 +154,7 @@ public:
|
||||
PRBool GetColorValue(nscolor& aColor) const;
|
||||
inline PRInt16 GetEnumValue() const;
|
||||
inline float GetPercentValue() const;
|
||||
inline nsCOMArray<nsIAtom>* GetAtomArrayValue() const;
|
||||
inline AtomArray* GetAtomArrayValue() const;
|
||||
inline nsICSSStyleRule* GetCSSStyleRuleValue() const;
|
||||
#ifdef MOZ_SVG
|
||||
inline nsISVGValue* GetSVGValue() const;
|
||||
@ -170,7 +173,7 @@ public:
|
||||
// Methods to get access to atoms we may have
|
||||
// Returns the number of atoms we have; 0 if we have none. It's OK
|
||||
// to call this without checking the type first; it handles that.
|
||||
PRInt32 GetAtomCount() const;
|
||||
PRUint32 GetAtomCount() const;
|
||||
// Returns the atom at aIndex (0-based). Do not call this with
|
||||
// aIndex >= GetAtomCount().
|
||||
nsIAtom* AtomAt(PRInt32 aIndex) const;
|
||||
@ -333,7 +336,7 @@ private:
|
||||
PRUint32 mEnumValue;
|
||||
PRInt32 mPercent;
|
||||
nsICSSStyleRule* mCSSStyleRule;
|
||||
nsCOMArray<nsIAtom>* mAtomArray;
|
||||
AtomArray* mAtomArray;
|
||||
#ifdef MOZ_SVG
|
||||
nsISVGValue* mSVGValue;
|
||||
#endif
|
||||
@ -426,7 +429,7 @@ nsAttrValue::GetPercentValue() const
|
||||
/ 100.0f;
|
||||
}
|
||||
|
||||
inline nsCOMArray<nsIAtom>*
|
||||
inline nsAttrValue::AtomArray*
|
||||
nsAttrValue::GetAtomArrayValue() const
|
||||
{
|
||||
NS_PRECONDITION(Type() == eAtomArray, "wrong type");
|
||||
|
@ -6004,7 +6004,7 @@ nsContentUtils::ReparentClonedObjectToScope(JSContext* cx,
|
||||
}
|
||||
|
||||
struct ClassMatchingInfo {
|
||||
nsCOMArray<nsIAtom> mClasses;
|
||||
nsAttrValue::AtomArray mClasses;
|
||||
nsCaseTreatment mCaseTreatment;
|
||||
};
|
||||
|
||||
@ -6020,14 +6020,14 @@ MatchClassNames(nsIContent* aContent, PRInt32 aNamespaceID, nsIAtom* aAtom,
|
||||
|
||||
// need to match *all* of the classes
|
||||
ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData);
|
||||
PRInt32 length = info->mClasses.Count();
|
||||
PRUint32 length = info->mClasses.Length();
|
||||
if (!length) {
|
||||
// If we actually had no classes, don't match.
|
||||
return PR_FALSE;
|
||||
}
|
||||
PRInt32 i;
|
||||
PRUint32 i;
|
||||
for (i = 0; i < length; ++i) {
|
||||
if (!classAttr->Contains(info->mClasses.ObjectAt(i),
|
||||
if (!classAttr->Contains(info->mClasses[i],
|
||||
info->mCaseTreatment)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
@ -6054,9 +6054,9 @@ AllocClassMatchingInfo(nsINode* aRootNode,
|
||||
NS_ENSURE_TRUE(info, nsnull);
|
||||
|
||||
if (attrValue.Type() == nsAttrValue::eAtomArray) {
|
||||
info->mClasses.AppendObjects(*(attrValue.GetAtomArrayValue()));
|
||||
info->mClasses.SwapElements(*(attrValue.GetAtomArrayValue()));
|
||||
} else if (attrValue.Type() == nsAttrValue::eAtom) {
|
||||
info->mClasses.AppendObject(attrValue.GetAtomValue());
|
||||
info->mClasses.AppendElement(attrValue.GetAtomValue());
|
||||
}
|
||||
|
||||
info->mCaseTreatment =
|
||||
|
@ -783,6 +783,36 @@ nsExternalResourceMap::Traverse(nsCycleCollectionTraversalCallback* aCallback) c
|
||||
mMap.EnumerateRead(ExternalResourceTraverser, aCallback);
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
ExternalResourceHider(nsIURI* aKey,
|
||||
nsExternalResourceMap::ExternalResource* aData,
|
||||
void* aClosure)
|
||||
{
|
||||
aData->mViewer->Hide();
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
nsExternalResourceMap::HideViewers()
|
||||
{
|
||||
mMap.EnumerateRead(ExternalResourceHider, nsnull);
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
ExternalResourceShower(nsIURI* aKey,
|
||||
nsExternalResourceMap::ExternalResource* aData,
|
||||
void* aClosure)
|
||||
{
|
||||
aData->mViewer->Show();
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
nsExternalResourceMap::ShowViewers()
|
||||
{
|
||||
mMap.EnumerateRead(ExternalResourceShower, nsnull);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsExternalResourceMap::AddExternalResource(nsIURI* aURI,
|
||||
nsIDocumentViewer* aViewer,
|
||||
@ -811,6 +841,9 @@ nsExternalResourceMap::AddExternalResource(nsIURI* aURI,
|
||||
} else {
|
||||
doc->SetDisplayDocument(aDisplayDocument);
|
||||
|
||||
// Make sure that hiding our viewer will tear down its presentation.
|
||||
aViewer->SetSticky(PR_FALSE);
|
||||
|
||||
rv = aViewer->Init(nsnull, nsIntRect(0, 0, 0, 0));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = aViewer->Open(nsnull, nsnull);
|
||||
@ -3039,11 +3072,20 @@ nsDocument::doCreateShell(nsPresContext* aContext,
|
||||
// Note: we don't hold a ref to the shell (it holds a ref to us)
|
||||
mPresShell = shell;
|
||||
|
||||
mExternalResourceMap.ShowViewers();
|
||||
|
||||
shell.swap(*aInstancePtrResult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::DeleteShell()
|
||||
{
|
||||
mExternalResourceMap.HideViewers();
|
||||
mPresShell = nsnull;
|
||||
}
|
||||
|
||||
static void
|
||||
SubDocClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
|
||||
{
|
||||
@ -7815,4 +7857,3 @@ nsIDocument::CreateStaticClone(nsISupports* aCloneContainer)
|
||||
mCreatingStaticClone = PR_FALSE;
|
||||
return clonedDoc.forget();
|
||||
}
|
||||
|
||||
|
@ -375,6 +375,12 @@ public:
|
||||
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
||||
};
|
||||
|
||||
// Hide all our viewers
|
||||
void HideViewers();
|
||||
|
||||
// Show all our viewers
|
||||
void ShowViewers();
|
||||
|
||||
protected:
|
||||
class PendingLoad : public ExternalResourceLoad,
|
||||
public nsIStreamListener
|
||||
@ -588,6 +594,7 @@ public:
|
||||
nsIViewManager* aViewManager,
|
||||
nsStyleSet* aStyleSet,
|
||||
nsIPresShell** aInstancePtrResult);
|
||||
virtual void DeleteShell();
|
||||
|
||||
virtual nsresult SetSubDocumentFor(nsIContent *aContent,
|
||||
nsIDocument* aSubDoc);
|
||||
|
@ -106,6 +106,11 @@ nsHTMLDNSPrefetch::Initialize()
|
||||
rv = CallGetService(kDNSServiceCID, &sDNSService);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
#ifdef MOZ_IPC
|
||||
if (mozilla::net::IsNeckoChild())
|
||||
mozilla::net::NeckoChild::InitNeckoChild();
|
||||
#endif
|
||||
|
||||
sInitialized = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1100,6 +1100,10 @@ nsHTMLParanoidFragmentSink::CloseContainer(const nsHTMLTag aTag)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (mIgnoreNextCloseHead && aTag == eHTMLTag_head) {
|
||||
mIgnoreNextCloseHead = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
if (mSkip) {
|
||||
mSkip = PR_FALSE;
|
||||
return rv;
|
||||
@ -1229,7 +1233,10 @@ nsHTMLParanoidFragmentSink::AddLeaf(const nsIParserNode& aNode)
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (mSkip) {
|
||||
// We need to explicitly skip adding leaf nodes in the paranoid sink,
|
||||
// otherwise things like the textnode under <title> get appended to
|
||||
// the fragment itself, and won't be popped off in CloseContainer.
|
||||
if (mSkip || mIgnoreNextCloseHead) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -53,6 +53,8 @@
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsChromeRegistryChrome.h"
|
||||
#include "nsExternalHelperAppService.h"
|
||||
#include "nsCExternalHandlerService.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
#include "AndroidBridge.h"
|
||||
@ -470,6 +472,17 @@ ContentParent::RecvSetURITitle(const IPC::URI& uri,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvLoadURIExternal(const IPC::URI& uri)
|
||||
{
|
||||
nsCOMPtr<nsIExternalProtocolService> extProtService(do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID));
|
||||
if (!extProtService)
|
||||
return true;
|
||||
nsCOMPtr<nsIURI> ourURI(uri);
|
||||
extProtService->LoadURI(ourURI, nsnull);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* void onDispatchedEvent (in nsIThreadInternal thread); */
|
||||
NS_IMETHODIMP
|
||||
ContentParent::OnDispatchedEvent(nsIThreadInternal *thread)
|
||||
|
@ -162,6 +162,8 @@ private:
|
||||
;
|
||||
|
||||
|
||||
virtual bool RecvLoadURIExternal(const IPC::URI& uri);
|
||||
|
||||
mozilla::Monitor mMonitor;
|
||||
|
||||
GeckoChildProcessHost* mSubprocess;
|
||||
|
@ -82,6 +82,7 @@ LOCAL_INCLUDES += \
|
||||
-I$(srcdir)/../../toolkit/components/places/src \
|
||||
-I$(srcdir)/../src/geolocation \
|
||||
-I$(topsrcdir)/chrome/src \
|
||||
-I$(topsrcdir)/uriloader/exthandler \
|
||||
$(NULL)
|
||||
|
||||
CXXFLAGS += $(TK_CFLAGS)
|
||||
|
@ -81,6 +81,8 @@ parent:
|
||||
async VisitURI(URI uri, URI referrer, PRUint32 flags);
|
||||
async SetURITitle(URI uri, nsString title);
|
||||
|
||||
async LoadURIExternal(URI uri);
|
||||
|
||||
// PrefService messages
|
||||
sync GetPrefType(nsCString prefName) returns (PRInt32 retValue, nsresult rv);
|
||||
sync GetBoolPref(nsCString prefName) returns (PRBool retValue, nsresult rv);
|
||||
|
@ -52,6 +52,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=520182
|
||||
<div id="jj" contenteditable="true"></div>
|
||||
<iframe id="kk" src="about:blank"></iframe>
|
||||
<div id="ll" contenteditable="true"></div>
|
||||
<iframe id="mm" src="about:blank"></iframe>
|
||||
<div id="nn" contenteditable="true"></div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
@ -73,6 +75,7 @@ const invalidStyle3Payload = "foo<style>@import 'xxx.css';</style>baz";
|
||||
const invalidStyle4Payload = "foo<span style=\"@import 'xxx.css';\">bar</span>baz";
|
||||
const invalidStyle5Payload = "foo<span style=\"@font-face{font-family:xxx;src:'xxx.ttf';}\">bar</span>baz";
|
||||
const invalidStyle6Payload = "foo<span style=\"@namespace xxx url(http://example.com/);\">bar</span>baz";
|
||||
const invalidStyle7Payload = "<html><head><title>xxx</title></head><body>foo</body></html>";
|
||||
const nestedStylePayload = "foo<style>#bar1{-moz-binding:url('data:text/xml,<?xml version="1.0"><binding xmlns="http://www.mozilla.org/xbl" id="binding-1"/>');<style></style>#bar2{-moz-binding:url('data:text/xml,<?xml version="1.0"><binding xmlns="http://www.mozilla.org/xbl" id="binding-2"/>');</style>baz";
|
||||
const validImgSrc1Payload = "foo<img src=\"data:image/png,bar\">baz";
|
||||
const validImgSrc2Payload = "foo<img src=\"javascript:void('bar');\">baz";
|
||||
@ -333,6 +336,27 @@ var tests = [
|
||||
payload: invalidStyle6Payload,
|
||||
rootElement: function() document.getElementById("ll"),
|
||||
checkResult: function(html) isnot(html.indexOf("bar"), -1, "Should have retained the src attribute for the image")
|
||||
},
|
||||
{
|
||||
id: "mm",
|
||||
isIFrame: true,
|
||||
insertHTML: true,
|
||||
payload: invalidStyle7Payload,
|
||||
rootElement: function() document.getElementById("mm").contentDocument.documentElement,
|
||||
checkResult: function(html) {
|
||||
is(html.indexOf("xxx"), -1, "Should not have retained the title text");
|
||||
isnot(html.indexOf("foo"), -1, "Should have retained the body text");
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "nn",
|
||||
insertHTML: true,
|
||||
payload: invalidStyle7Payload,
|
||||
rootElement: function() document.getElementById("nn"),
|
||||
checkResult: function(html) {
|
||||
is(html.indexOf("xxx"), -1, "Should not have retained the title text");
|
||||
isnot(html.indexOf("foo"), -1, "Should have retained the body text");
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
@ -357,28 +381,37 @@ function runTest(test) {
|
||||
} else
|
||||
elem.focus();
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
if ("insertHTML" in test) {
|
||||
if ("isIFrame" in test) {
|
||||
elem.contentDocument.execCommand("inserthtml", false, test.payload);
|
||||
} else {
|
||||
getSelection().collapse(elem, 0);
|
||||
document.execCommand("inserthtml", false, test.payload);
|
||||
}
|
||||
} else {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
|
||||
.getService(Components.interfaces.nsIClipboard);
|
||||
var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
|
||||
.getService(Components.interfaces.nsIClipboard);
|
||||
|
||||
var trans = Components.classes["@mozilla.org/widget/transferable;1"]
|
||||
.createInstance(Components.interfaces.nsITransferable);
|
||||
var data = Components.classes["@mozilla.org/supports-string;1"]
|
||||
.createInstance(Components.interfaces.nsISupportsString);
|
||||
data.data = test.payload;
|
||||
trans.addDataFlavor("text/html");
|
||||
trans.setTransferData("text/html", data, data.data.length * 2);
|
||||
clipboard.setData(trans, null, Components.interfaces.nsIClipboard.kGlobalClipboard);
|
||||
var trans = Components.classes["@mozilla.org/widget/transferable;1"]
|
||||
.createInstance(Components.interfaces.nsITransferable);
|
||||
var data = Components.classes["@mozilla.org/supports-string;1"]
|
||||
.createInstance(Components.interfaces.nsISupportsString);
|
||||
data.data = test.payload;
|
||||
trans.addDataFlavor("text/html");
|
||||
trans.setTransferData("text/html", data, data.data.length * 2);
|
||||
clipboard.setData(trans, null, Components.interfaces.nsIClipboard.kGlobalClipboard);
|
||||
|
||||
var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIWebNavigation)
|
||||
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
|
||||
.rootTreeItem
|
||||
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindow);
|
||||
var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIWebNavigation)
|
||||
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
|
||||
.rootTreeItem
|
||||
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindow);
|
||||
|
||||
mainWindow.goDoCommand("cmd_paste");
|
||||
mainWindow.goDoCommand("cmd_paste");
|
||||
}
|
||||
|
||||
if ("checkResult" in test) {
|
||||
if ("isIFrame" in test) {
|
||||
|
@ -14,7 +14,8 @@
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
|
||||
<application android:label="@MOZ_APP_DISPLAYNAME@"
|
||||
android:icon="@drawable/icon">
|
||||
android:icon="@drawable/icon"
|
||||
android:debuggable="true">
|
||||
<activity android:name="App"
|
||||
android:label="@MOZ_APP_DISPLAYNAME@"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|mcc|mnc"
|
||||
|
@ -157,7 +157,7 @@ class GeckoAppShell
|
||||
sGeckoRunning = true;
|
||||
|
||||
// First argument is the .apk path
|
||||
String combinedArgs = apkPath;
|
||||
String combinedArgs = apkPath + " -omnijar " + apkPath;
|
||||
if (args != null)
|
||||
combinedArgs += " " + args;
|
||||
if (url != null)
|
||||
|
@ -91,6 +91,7 @@
|
||||
|
||||
// PSM2 includes
|
||||
#include "nsISecureBrowserUI.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
using namespace mozilla::layers;
|
||||
|
||||
@ -790,6 +791,7 @@ NS_IMETHODIMP nsWebBrowser::SetProperty(PRUint32 aId, PRUint32 aValue)
|
||||
NS_ENSURE_TRUE((aValue == PR_TRUE || aValue == PR_FALSE), NS_ERROR_INVALID_ARG);
|
||||
mDocShell->SetAllowDNSPrefetch(!!aValue);
|
||||
}
|
||||
break;
|
||||
case nsIWebBrowserSetup::SETUP_USE_GLOBAL_HISTORY:
|
||||
{
|
||||
NS_ENSURE_STATE(mDocShell);
|
||||
@ -1230,10 +1232,15 @@ NS_IMETHODIMP nsWebBrowser::Create()
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
mDocShellAsNav->SetSessionHistory(mInitInfo->sessionHistory);
|
||||
|
||||
// Hook up global history. Do not fail if we can't - just warn.
|
||||
rv = EnableGlobalHistory(mShouldEnableHistory);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "EnableGlobalHistory() failed");
|
||||
|
||||
#ifdef MOZ_IPC
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Default)
|
||||
#endif
|
||||
{
|
||||
// Hook up global history. Do not fail if we can't - just warn.
|
||||
rv = EnableGlobalHistory(mShouldEnableHistory);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "EnableGlobalHistory() failed");
|
||||
}
|
||||
|
||||
NS_ENSURE_SUCCESS(mDocShellAsWin->Create(), NS_ERROR_FAILURE);
|
||||
|
||||
|
546
gfx/cairo/cairo/src/cairo-d2d-private-fx.h
Normal file
546
gfx/cairo/cairo/src/cairo-d2d-private-fx.h
Normal file
@ -0,0 +1,546 @@
|
||||
#if 0
|
||||
//
|
||||
// FX Version: fx_4_0
|
||||
// Child effect (requires effect pool): false
|
||||
//
|
||||
// 1 local buffer(s)
|
||||
//
|
||||
cbuffer cb0
|
||||
{
|
||||
float4 QuadDesc; // Offset: 0, size: 16
|
||||
float4 TexCoords; // Offset: 16, size: 16
|
||||
}
|
||||
|
||||
//
|
||||
// 2 local object(s)
|
||||
//
|
||||
Texture2D tex;
|
||||
SamplerState sSampler
|
||||
{
|
||||
Texture = tex;
|
||||
AddressU = uint(CLAMP /* 3 */);
|
||||
AddressV = uint(CLAMP /* 3 */);
|
||||
};
|
||||
|
||||
//
|
||||
// 1 technique(s)
|
||||
//
|
||||
technique10 SampleTexture
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
VertexShader = asm {
|
||||
//
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022
|
||||
//
|
||||
//
|
||||
// Buffer Definitions:
|
||||
//
|
||||
// cbuffer cb0
|
||||
// {
|
||||
//
|
||||
// float4 QuadDesc; // Offset: 0 Size: 16
|
||||
// float4 TexCoords; // Offset: 16 Size: 16
|
||||
//
|
||||
// }
|
||||
//
|
||||
//
|
||||
// Resource Bindings:
|
||||
//
|
||||
// Name Type Format Dim Slot Elements
|
||||
// ------------------------------ ---------- ------- ----------- ---- --------
|
||||
// cb0 cbuffer NA NA 0 1
|
||||
//
|
||||
//
|
||||
//
|
||||
// Input signature:
|
||||
//
|
||||
// Name Index Mask Register SysValue Format Used
|
||||
// -------------------- ----- ------ -------- -------- ------ ------
|
||||
// POSITION 0 xyz 0 NONE float xy
|
||||
//
|
||||
//
|
||||
// Output signature:
|
||||
//
|
||||
// Name Index Mask Register SysValue Format Used
|
||||
// -------------------- ----- ------ -------- -------- ------ ------
|
||||
// SV_Position 0 xyzw 0 POS float xyzw
|
||||
// TEXCOORD 0 xy 1 NONE float xy
|
||||
//
|
||||
//
|
||||
// Constant buffer to DX9 shader constant mappings:
|
||||
//
|
||||
// Target Reg Buffer Start Reg # of Regs Data Conversion
|
||||
// ---------- ------- --------- --------- ----------------------
|
||||
// c1 cb0 0 2 ( FLT, FLT, FLT, FLT)
|
||||
//
|
||||
//
|
||||
// Runtime generated constant mappings:
|
||||
//
|
||||
// Target Reg Constant Description
|
||||
// ---------- --------------------------------------------------
|
||||
// c0 Vertex Shader position offset
|
||||
//
|
||||
//
|
||||
// Level9 shader bytecode:
|
||||
//
|
||||
vs_2_x
|
||||
def c3, 0, 1, 0, 0
|
||||
dcl_texcoord v0
|
||||
mad oT0.xy, v0, c2.zwzw, c2
|
||||
mad r0.x, v0.x, c1.z, c1.x
|
||||
mad r0.y, v0.y, c1.w, c1.y
|
||||
add oPos.xy, r0, c0
|
||||
mov oPos.zw, c3.xyxy
|
||||
|
||||
// approximately 5 instruction slots used
|
||||
vs_4_0
|
||||
dcl_constantbuffer cb0[2], immediateIndexed
|
||||
dcl_input v0.xy
|
||||
dcl_output_siv o0.xyzw, position
|
||||
dcl_output o1.xy
|
||||
mad o0.xy, v0.xyxx, cb0[0].zwzz, cb0[0].xyxx
|
||||
mov o0.zw, l(0,0,0,1.000000)
|
||||
mad o1.xy, v0.xyxx, cb0[1].zwzz, cb0[1].xyxx
|
||||
ret
|
||||
// Approximately 4 instruction slots used
|
||||
|
||||
};
|
||||
GeometryShader = NULL;
|
||||
PixelShader = asm {
|
||||
//
|
||||
// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022
|
||||
//
|
||||
//
|
||||
// Resource Bindings:
|
||||
//
|
||||
// Name Type Format Dim Slot Elements
|
||||
// ------------------------------ ---------- ------- ----------- ---- --------
|
||||
// sSampler sampler NA NA 0 1
|
||||
// tex texture float4 2d 0 1
|
||||
//
|
||||
//
|
||||
//
|
||||
// Input signature:
|
||||
//
|
||||
// Name Index Mask Register SysValue Format Used
|
||||
// -------------------- ----- ------ -------- -------- ------ ------
|
||||
// SV_Position 0 xyzw 0 POS float
|
||||
// TEXCOORD 0 xy 1 NONE float xy
|
||||
//
|
||||
//
|
||||
// Output signature:
|
||||
//
|
||||
// Name Index Mask Register SysValue Format Used
|
||||
// -------------------- ----- ------ -------- -------- ------ ------
|
||||
// SV_Target 0 xyzw 0 TARGET float xyzw
|
||||
//
|
||||
//
|
||||
// Sampler/Resource to DX9 shader sampler mappings:
|
||||
//
|
||||
// Target Sampler Source Sampler Source Resource
|
||||
// -------------- --------------- ----------------
|
||||
// s0 s0 t0
|
||||
//
|
||||
//
|
||||
// Level9 shader bytecode:
|
||||
//
|
||||
ps_2_x
|
||||
dcl t0.xy
|
||||
dcl_2d s0
|
||||
texld r0, t0, s0
|
||||
mov oC0, r0
|
||||
|
||||
// approximately 2 instruction slots used (1 texture, 1 arithmetic)
|
||||
ps_4_0
|
||||
dcl_sampler s0, mode_default
|
||||
dcl_resource_texture2d (float,float,float,float) t0
|
||||
dcl_input_ps linear v1.xy
|
||||
dcl_output o0.xyzw
|
||||
sample o0.xyzw, v1.xyxx, t0.xyzw, s0
|
||||
ret
|
||||
// Approximately 2 instruction slots used
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
const BYTE g_main[] =
|
||||
{
|
||||
68, 88, 66, 67, 235, 24,
|
||||
238, 6, 37, 230, 191, 228,
|
||||
58, 61, 41, 219, 70, 130,
|
||||
61, 51, 1, 0, 0, 0,
|
||||
187, 8, 0, 0, 1, 0,
|
||||
0, 0, 36, 0, 0, 0,
|
||||
70, 88, 49, 48, 143, 8,
|
||||
0, 0, 1, 16, 255, 254,
|
||||
1, 0, 0, 0, 2, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 79, 7,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 2, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
0, 0, 0, 0, 99, 98,
|
||||
48, 0, 102, 108, 111, 97,
|
||||
116, 52, 0, 8, 0, 0,
|
||||
0, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 16, 0, 0,
|
||||
0, 16, 0, 0, 0, 16,
|
||||
0, 0, 0, 10, 33, 0,
|
||||
0, 81, 117, 97, 100, 68,
|
||||
101, 115, 99, 0, 84, 101,
|
||||
120, 67, 111, 111, 114, 100,
|
||||
115, 0, 84, 101, 120, 116,
|
||||
117, 114, 101, 50, 68, 0,
|
||||
62, 0, 0, 0, 2, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
12, 0, 0, 0, 116, 101,
|
||||
120, 0, 83, 97, 109, 112,
|
||||
108, 101, 114, 83, 116, 97,
|
||||
116, 101, 0, 104, 0, 0,
|
||||
0, 2, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 21, 0, 0,
|
||||
0, 115, 83, 97, 109, 112,
|
||||
108, 101, 114, 0, 1, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
3, 0, 0, 0, 1, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
3, 0, 0, 0, 83, 97,
|
||||
109, 112, 108, 101, 84, 101,
|
||||
120, 116, 117, 114, 101, 0,
|
||||
80, 48, 0, 172, 3, 0,
|
||||
0, 68, 88, 66, 67, 247,
|
||||
105, 31, 113, 120, 95, 58,
|
||||
12, 207, 141, 45, 76, 175,
|
||||
59, 223, 25, 1, 0, 0,
|
||||
0, 172, 3, 0, 0, 6,
|
||||
0, 0, 0, 56, 0, 0,
|
||||
0, 248, 0, 0, 0, 188,
|
||||
1, 0, 0, 56, 2, 0,
|
||||
0, 32, 3, 0, 0, 84,
|
||||
3, 0, 0, 65, 111, 110,
|
||||
57, 184, 0, 0, 0, 184,
|
||||
0, 0, 0, 0, 2, 254,
|
||||
255, 132, 0, 0, 0, 52,
|
||||
0, 0, 0, 1, 0, 36,
|
||||
0, 0, 0, 48, 0, 0,
|
||||
0, 48, 0, 0, 0, 36,
|
||||
0, 1, 0, 48, 0, 0,
|
||||
0, 0, 0, 2, 0, 1,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 1, 2, 254,
|
||||
255, 81, 0, 0, 5, 3,
|
||||
0, 15, 160, 0, 0, 0,
|
||||
0, 0, 0, 128, 63, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 31, 0, 0, 2, 5,
|
||||
0, 0, 128, 0, 0, 15,
|
||||
144, 4, 0, 0, 4, 0,
|
||||
0, 3, 224, 0, 0, 228,
|
||||
144, 2, 0, 238, 160, 2,
|
||||
0, 228, 160, 4, 0, 0,
|
||||
4, 0, 0, 1, 128, 0,
|
||||
0, 0, 144, 1, 0, 170,
|
||||
160, 1, 0, 0, 160, 4,
|
||||
0, 0, 4, 0, 0, 2,
|
||||
128, 0, 0, 85, 144, 1,
|
||||
0, 255, 160, 1, 0, 85,
|
||||
160, 2, 0, 0, 3, 0,
|
||||
0, 3, 192, 0, 0, 228,
|
||||
128, 0, 0, 228, 160, 1,
|
||||
0, 0, 2, 0, 0, 12,
|
||||
192, 3, 0, 68, 160, 255,
|
||||
255, 0, 0, 83, 72, 68,
|
||||
82, 188, 0, 0, 0, 64,
|
||||
0, 1, 0, 47, 0, 0,
|
||||
0, 89, 0, 0, 4, 70,
|
||||
142, 32, 0, 0, 0, 0,
|
||||
0, 2, 0, 0, 0, 95,
|
||||
0, 0, 3, 50, 16, 16,
|
||||
0, 0, 0, 0, 0, 103,
|
||||
0, 0, 4, 242, 32, 16,
|
||||
0, 0, 0, 0, 0, 1,
|
||||
0, 0, 0, 101, 0, 0,
|
||||
3, 50, 32, 16, 0, 1,
|
||||
0, 0, 0, 50, 0, 0,
|
||||
11, 50, 32, 16, 0, 0,
|
||||
0, 0, 0, 70, 16, 16,
|
||||
0, 0, 0, 0, 0, 230,
|
||||
138, 32, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 70,
|
||||
128, 32, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 54,
|
||||
0, 0, 8, 194, 32, 16,
|
||||
0, 0, 0, 0, 0, 2,
|
||||
64, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 128,
|
||||
63, 50, 0, 0, 11, 50,
|
||||
32, 16, 0, 1, 0, 0,
|
||||
0, 70, 16, 16, 0, 0,
|
||||
0, 0, 0, 230, 138, 32,
|
||||
0, 0, 0, 0, 0, 1,
|
||||
0, 0, 0, 70, 128, 32,
|
||||
0, 0, 0, 0, 0, 1,
|
||||
0, 0, 0, 62, 0, 0,
|
||||
1, 83, 84, 65, 84, 116,
|
||||
0, 0, 0, 4, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 3, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 82,
|
||||
68, 69, 70, 224, 0, 0,
|
||||
0, 1, 0, 0, 0, 64,
|
||||
0, 0, 0, 1, 0, 0,
|
||||
0, 28, 0, 0, 0, 0,
|
||||
4, 254, 255, 0, 129, 0,
|
||||
0, 174, 0, 0, 0, 60,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 99, 98, 48, 0, 60,
|
||||
0, 0, 0, 2, 0, 0,
|
||||
0, 88, 0, 0, 0, 32,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 136,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 16, 0, 0, 0, 2,
|
||||
0, 0, 0, 148, 0, 0,
|
||||
0, 0, 0, 0, 0, 164,
|
||||
0, 0, 0, 16, 0, 0,
|
||||
0, 16, 0, 0, 0, 2,
|
||||
0, 0, 0, 148, 0, 0,
|
||||
0, 0, 0, 0, 0, 81,
|
||||
117, 97, 100, 68, 101, 115,
|
||||
99, 0, 171, 171, 171, 1,
|
||||
0, 3, 0, 1, 0, 4,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 84, 101, 120,
|
||||
67, 111, 111, 114, 100, 115,
|
||||
0, 77, 105, 99, 114, 111,
|
||||
115, 111, 102, 116, 32, 40,
|
||||
82, 41, 32, 72, 76, 83,
|
||||
76, 32, 83, 104, 97, 100,
|
||||
101, 114, 32, 67, 111, 109,
|
||||
112, 105, 108, 101, 114, 32,
|
||||
57, 46, 50, 55, 46, 57,
|
||||
53, 50, 46, 51, 48, 50,
|
||||
50, 0, 171, 73, 83, 71,
|
||||
78, 44, 0, 0, 0, 1,
|
||||
0, 0, 0, 8, 0, 0,
|
||||
0, 32, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 3, 0, 0, 0, 0,
|
||||
0, 0, 0, 7, 3, 0,
|
||||
0, 80, 79, 83, 73, 84,
|
||||
73, 79, 78, 0, 171, 171,
|
||||
171, 79, 83, 71, 78, 80,
|
||||
0, 0, 0, 2, 0, 0,
|
||||
0, 8, 0, 0, 0, 56,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 1, 0, 0, 0, 3,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 15, 0, 0, 0, 68,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 3,
|
||||
0, 0, 0, 1, 0, 0,
|
||||
0, 3, 12, 0, 0, 83,
|
||||
86, 95, 80, 111, 115, 105,
|
||||
116, 105, 111, 110, 0, 84,
|
||||
69, 88, 67, 79, 79, 82,
|
||||
68, 0, 171, 171, 171, 195,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 1, 0, 0, 0, 2,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 188, 2, 0, 0, 68,
|
||||
88, 66, 67, 90, 17, 243,
|
||||
62, 104, 14, 0, 40, 49,
|
||||
70, 150, 92, 77, 1, 115,
|
||||
141, 1, 0, 0, 0, 188,
|
||||
2, 0, 0, 6, 0, 0,
|
||||
0, 56, 0, 0, 0, 164,
|
||||
0, 0, 0, 16, 1, 0,
|
||||
0, 140, 1, 0, 0, 48,
|
||||
2, 0, 0, 136, 2, 0,
|
||||
0, 65, 111, 110, 57, 100,
|
||||
0, 0, 0, 100, 0, 0,
|
||||
0, 0, 2, 255, 255, 60,
|
||||
0, 0, 0, 40, 0, 0,
|
||||
0, 0, 0, 40, 0, 0,
|
||||
0, 40, 0, 0, 0, 40,
|
||||
0, 1, 0, 36, 0, 0,
|
||||
0, 40, 0, 0, 0, 0,
|
||||
0, 1, 2, 255, 255, 31,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
128, 0, 0, 3, 176, 31,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
144, 0, 8, 15, 160, 66,
|
||||
0, 0, 3, 0, 0, 15,
|
||||
128, 0, 0, 228, 176, 0,
|
||||
8, 228, 160, 1, 0, 0,
|
||||
2, 0, 8, 15, 128, 0,
|
||||
0, 228, 128, 255, 255, 0,
|
||||
0, 83, 72, 68, 82, 100,
|
||||
0, 0, 0, 64, 0, 0,
|
||||
0, 25, 0, 0, 0, 90,
|
||||
0, 0, 3, 0, 96, 16,
|
||||
0, 0, 0, 0, 0, 88,
|
||||
24, 0, 4, 0, 112, 16,
|
||||
0, 0, 0, 0, 0, 85,
|
||||
85, 0, 0, 98, 16, 0,
|
||||
3, 50, 16, 16, 0, 1,
|
||||
0, 0, 0, 101, 0, 0,
|
||||
3, 242, 32, 16, 0, 0,
|
||||
0, 0, 0, 69, 0, 0,
|
||||
9, 242, 32, 16, 0, 0,
|
||||
0, 0, 0, 70, 16, 16,
|
||||
0, 1, 0, 0, 0, 70,
|
||||
126, 16, 0, 0, 0, 0,
|
||||
0, 0, 96, 16, 0, 0,
|
||||
0, 0, 0, 62, 0, 0,
|
||||
1, 83, 84, 65, 84, 116,
|
||||
0, 0, 0, 2, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 2, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 82,
|
||||
68, 69, 70, 156, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 2, 0, 0,
|
||||
0, 28, 0, 0, 0, 0,
|
||||
4, 255, 255, 0, 129, 0,
|
||||
0, 105, 0, 0, 0, 92,
|
||||
0, 0, 0, 3, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 101, 0, 0, 0, 2,
|
||||
0, 0, 0, 5, 0, 0,
|
||||
0, 4, 0, 0, 0, 255,
|
||||
255, 255, 255, 0, 0, 0,
|
||||
0, 1, 0, 0, 0, 12,
|
||||
0, 0, 0, 115, 83, 97,
|
||||
109, 112, 108, 101, 114, 0,
|
||||
116, 101, 120, 0, 77, 105,
|
||||
99, 114, 111, 115, 111, 102,
|
||||
116, 32, 40, 82, 41, 32,
|
||||
72, 76, 83, 76, 32, 83,
|
||||
104, 97, 100, 101, 114, 32,
|
||||
67, 111, 109, 112, 105, 108,
|
||||
101, 114, 32, 57, 46, 50,
|
||||
55, 46, 57, 53, 50, 46,
|
||||
51, 48, 50, 50, 0, 171,
|
||||
171, 73, 83, 71, 78, 80,
|
||||
0, 0, 0, 2, 0, 0,
|
||||
0, 8, 0, 0, 0, 56,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 1, 0, 0, 0, 3,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 15, 0, 0, 0, 68,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 3,
|
||||
0, 0, 0, 1, 0, 0,
|
||||
0, 3, 3, 0, 0, 83,
|
||||
86, 95, 80, 111, 115, 105,
|
||||
116, 105, 111, 110, 0, 84,
|
||||
69, 88, 67, 79, 79, 82,
|
||||
68, 0, 171, 171, 171, 79,
|
||||
83, 71, 78, 44, 0, 0,
|
||||
0, 1, 0, 0, 0, 8,
|
||||
0, 0, 0, 32, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 3, 0, 0,
|
||||
0, 0, 0, 0, 0, 15,
|
||||
0, 0, 0, 83, 86, 95,
|
||||
84, 97, 114, 103, 101, 116,
|
||||
0, 171, 171, 135, 4, 0,
|
||||
0, 0, 0, 0, 0, 4,
|
||||
0, 0, 0, 32, 0, 0,
|
||||
0, 0, 0, 0, 0, 2,
|
||||
0, 0, 0, 255, 255, 255,
|
||||
255, 0, 0, 0, 0, 43,
|
||||
0, 0, 0, 15, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 52, 0, 0,
|
||||
0, 15, 0, 0, 0, 0,
|
||||
0, 0, 0, 16, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 100, 0, 0, 0, 72,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 255, 255, 255, 255, 0,
|
||||
0, 0, 0, 145, 0, 0,
|
||||
0, 117, 0, 0, 0, 0,
|
||||
0, 0, 0, 255, 255, 255,
|
||||
255, 3, 0, 0, 0, 55,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 2, 0, 0, 0, 100,
|
||||
0, 0, 0, 46, 0, 0,
|
||||
0, 0, 0, 0, 0, 1,
|
||||
0, 0, 0, 154, 0, 0,
|
||||
0, 47, 0, 0, 0, 0,
|
||||
0, 0, 0, 1, 0, 0,
|
||||
0, 166, 0, 0, 0, 0,
|
||||
0, 0, 0, 178, 0, 0,
|
||||
0, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 192, 0, 0,
|
||||
0, 3, 0, 0, 0, 0,
|
||||
0, 0, 0, 6, 0, 0,
|
||||
0, 0, 0, 0, 0, 7,
|
||||
0, 0, 0, 115, 4, 0,
|
||||
0, 8, 0, 0, 0, 0,
|
||||
0, 0, 0, 1, 0, 0,
|
||||
0, 123, 4, 0, 0, 7,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 7, 0, 0, 0, 71,
|
||||
7, 0, 0
|
||||
};
|
57
gfx/cairo/cairo/src/cairo-d2d-private.fx
Normal file
57
gfx/cairo/cairo/src/cairo-d2d-private.fx
Normal file
@ -0,0 +1,57 @@
|
||||
// We store vertex coordinates and the quad shape in a constant buffer, this is
|
||||
// easy to update and allows us to use a single call to set the x, y, w, h of
|
||||
// the quad.
|
||||
// The QuadDesc and TexCoords both work as follows:
|
||||
// The x component is the quad left point, the y component is the top point
|
||||
// the z component is the width, and the w component is the height. The quad
|
||||
// are specified in viewport coordinates, i.e. { -1.0f, 1.0f, 2.0f, -2.0f }
|
||||
// would cover the entire viewport (which runs from <-1.0f, 1.0f> left to right
|
||||
// and <-1.0f, 1.0f> -bottom- to top. The TexCoords desc is specified in texture
|
||||
// space <0, 1.0f> left to right and top to bottom. The input vertices of the
|
||||
// shader stage always form a rectangle from {0, 0} - {1, 1}
|
||||
cbuffer cb0
|
||||
{
|
||||
float4 QuadDesc;
|
||||
float4 TexCoords;
|
||||
}
|
||||
|
||||
struct VS_OUTPUT
|
||||
{
|
||||
float4 Position : SV_Position;
|
||||
float2 TexCoord : TEXCOORD0;
|
||||
};
|
||||
|
||||
Texture2D tex;
|
||||
|
||||
sampler sSampler = sampler_state {
|
||||
Texture = tex;
|
||||
AddressU = Clamp;
|
||||
AddressV = Clamp;
|
||||
};
|
||||
|
||||
VS_OUTPUT SampleTextureVS(float3 pos : POSITION)
|
||||
{
|
||||
VS_OUTPUT Output;
|
||||
Output.Position.w = 1.0f;
|
||||
Output.Position.x = pos.x * QuadDesc.z + QuadDesc.x;
|
||||
Output.Position.y = pos.y * QuadDesc.w + QuadDesc.y;
|
||||
Output.Position.z = 0;
|
||||
Output.TexCoord.x = pos.x * TexCoords.z + TexCoords.x;
|
||||
Output.TexCoord.y = pos.y * TexCoords.w + TexCoords.y;
|
||||
return Output;
|
||||
}
|
||||
|
||||
float4 SampleTexturePS( VS_OUTPUT In) : SV_Target
|
||||
{
|
||||
return tex.Sample(sSampler, In.TexCoord);
|
||||
};
|
||||
|
||||
technique10 SampleTexture
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetVertexShader(CompileShader(vs_4_0_level_9_3, SampleTextureVS()));
|
||||
SetGeometryShader(NULL);
|
||||
SetPixelShader(CompileShader(ps_4_0_level_9_3, SampleTexturePS()));
|
||||
}
|
||||
}
|
@ -49,10 +49,28 @@ extern "C" {
|
||||
}
|
||||
|
||||
#include "cairo-win32-refptr.h"
|
||||
#include "cairo-d2d-private-fx.h"
|
||||
#include "cairo-win32.h"
|
||||
|
||||
/* describes the type of the currently applied clip so that we can pop it */
|
||||
struct d2d_clip;
|
||||
|
||||
#define MAX_OPERATORS CAIRO_OPERATOR_HSL_LUMINOSITY + 1
|
||||
|
||||
struct _cairo_d2d_device
|
||||
{
|
||||
cairo_device_t base;
|
||||
|
||||
HMODULE mD3D10_1;
|
||||
RefPtr<ID3D10Device1> mD3D10Device;
|
||||
RefPtr<ID3D10Effect> mSampleEffect;
|
||||
RefPtr<ID3D10InputLayout> mInputLayout;
|
||||
RefPtr<ID3D10Buffer> mQuadBuffer;
|
||||
RefPtr<ID3D10RasterizerState> mRasterizerState;
|
||||
RefPtr<ID3D10BlendState> mBlendStates[MAX_OPERATORS];
|
||||
};
|
||||
typedef struct _cairo_d2d_device cairo_d2d_device_t;
|
||||
|
||||
struct _cairo_d2d_surface {
|
||||
_cairo_d2d_surface() : d2d_clip(NULL), clipping(false), isDrawing(false),
|
||||
textRenderingInit(true)
|
||||
@ -61,6 +79,10 @@ struct _cairo_d2d_surface {
|
||||
}
|
||||
|
||||
cairo_surface_t base;
|
||||
/* Device used by this surface
|
||||
* NOTE: In upstream cairo this is in the surface base class */
|
||||
cairo_d2d_device_t *device;
|
||||
|
||||
/** Render target of the texture we render to */
|
||||
RefPtr<ID2D1RenderTarget> rt;
|
||||
/** Surface containing our backstore */
|
||||
@ -103,6 +125,10 @@ struct _cairo_d2d_surface {
|
||||
/** Indicates if text rendering is initialized */
|
||||
bool textRenderingInit;
|
||||
|
||||
RefPtr<ID3D10RenderTargetView> buffer_rt_view;
|
||||
RefPtr<ID3D10ShaderResourceView> buffer_sr_view;
|
||||
|
||||
|
||||
//cairo_surface_clipper_t clipper;
|
||||
};
|
||||
typedef struct _cairo_d2d_surface cairo_d2d_surface_t;
|
||||
@ -124,104 +150,14 @@ typedef HRESULT (WINAPI*D3D10CreateDevice1Func)(
|
||||
ID3D10Device1 **ppDevice
|
||||
);
|
||||
|
||||
class D2DSurfFactory
|
||||
{
|
||||
public:
|
||||
static ID2D1Factory *Instance()
|
||||
{
|
||||
if (!mFactoryInstance) {
|
||||
D2D1CreateFactoryFunc createD2DFactory = (D2D1CreateFactoryFunc)
|
||||
GetProcAddress(LoadLibraryW(L"d2d1.dll"), "D2D1CreateFactory");
|
||||
if (createD2DFactory) {
|
||||
D2D1_FACTORY_OPTIONS options;
|
||||
#ifdef DEBUG
|
||||
options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
|
||||
#else
|
||||
options.debugLevel = D2D1_DEBUG_LEVEL_NONE;
|
||||
#endif
|
||||
createD2DFactory(
|
||||
D2D1_FACTORY_TYPE_SINGLE_THREADED,
|
||||
__uuidof(ID2D1Factory),
|
||||
&options,
|
||||
(void**)&mFactoryInstance);
|
||||
}
|
||||
}
|
||||
return mFactoryInstance;
|
||||
}
|
||||
private:
|
||||
static ID2D1Factory *mFactoryInstance;
|
||||
};
|
||||
|
||||
/**
|
||||
* On usage of D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS:
|
||||
* documentation on D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
|
||||
* can be misleading. In fact, that flag gives no such indication. I pointed this
|
||||
* out to Bas in my email. However, Microsoft is in fact using this flag to
|
||||
* indicate "light weight" DX applications. By light weight they are essentially
|
||||
* referring to applications that are not games. The idea is that when you create
|
||||
* a DX game, the driver assumes that you will pretty much have a single instance
|
||||
* and therefore it doesn't try to hold back when it comes to GPU resource
|
||||
* allocation as long as it can crank out performance. In other words, the
|
||||
* priority in regular DX applications is to make that one application run as fast
|
||||
* as you can. For "light weight" applications, including D2D applications, the
|
||||
* priorities are a bit different. Now you are no longer going to have a single
|
||||
* (or very few) instances. You can have a lot of them (say, for example, a
|
||||
* separate DX context/device per browser tab). In such cases, the GPU resource
|
||||
* allocation scheme changes.
|
||||
*/
|
||||
class D3D10Factory
|
||||
{
|
||||
public:
|
||||
static ID3D10Device1 *Device()
|
||||
{
|
||||
if (!mDeviceInstance) {
|
||||
D3D10CreateDevice1Func createD3DDevice = (D3D10CreateDevice1Func)
|
||||
GetProcAddress(LoadLibraryA("d3d10_1.dll"), "D3D10CreateDevice1");
|
||||
if (createD3DDevice) {
|
||||
HRESULT hr = createD3DDevice(
|
||||
NULL,
|
||||
D3D10_DRIVER_TYPE_HARDWARE,
|
||||
NULL,
|
||||
D3D10_CREATE_DEVICE_BGRA_SUPPORT |
|
||||
D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
|
||||
D3D10_FEATURE_LEVEL_10_1,
|
||||
D3D10_1_SDK_VERSION,
|
||||
&mDeviceInstance);
|
||||
if (FAILED(hr)) {
|
||||
HRESULT hr = createD3DDevice(
|
||||
NULL,
|
||||
D3D10_DRIVER_TYPE_HARDWARE,
|
||||
NULL,
|
||||
D3D10_CREATE_DEVICE_BGRA_SUPPORT |
|
||||
D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
|
||||
D3D10_FEATURE_LEVEL_10_0,
|
||||
D3D10_1_SDK_VERSION,
|
||||
&mDeviceInstance);
|
||||
if (FAILED(hr)) {
|
||||
/* TODO: D3D10Level9 might be slower than GDI */
|
||||
HRESULT hr = createD3DDevice(
|
||||
NULL,
|
||||
D3D10_DRIVER_TYPE_HARDWARE,
|
||||
NULL,
|
||||
D3D10_CREATE_DEVICE_BGRA_SUPPORT |
|
||||
D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
|
||||
D3D10_FEATURE_LEVEL_9_3,
|
||||
D3D10_1_SDK_VERSION,
|
||||
&mDeviceInstance);
|
||||
|
||||
}
|
||||
}
|
||||
if (SUCCEEDED(hr)) {
|
||||
mDeviceInstance->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_LINESTRIP);
|
||||
}
|
||||
}
|
||||
}
|
||||
return mDeviceInstance;
|
||||
}
|
||||
private:
|
||||
static ID3D10Device1 *mDeviceInstance;
|
||||
};
|
||||
|
||||
typedef HRESULT (WINAPI*D3D10CreateEffectFromMemoryFunc)(
|
||||
void *pData,
|
||||
SIZE_T DataLength,
|
||||
UINT FXFlags,
|
||||
ID3D10Device *pDevice,
|
||||
ID3D10EffectPool *pEffectPool,
|
||||
ID3D10Effect **ppEffect
|
||||
);
|
||||
|
||||
RefPtr<ID2D1Brush>
|
||||
_cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
|
||||
@ -229,8 +165,15 @@ _cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
|
||||
bool unique = false);
|
||||
void
|
||||
_cairo_d2d_begin_draw_state(cairo_d2d_surface_t *d2dsurf);
|
||||
|
||||
cairo_status_t
|
||||
_cairo_d2d_set_clip(cairo_d2d_surface_t *d2dsurf, cairo_clip_t *clip);
|
||||
|
||||
cairo_int_status_t _cairo_d2d_blend_temp_surface(cairo_d2d_surface_t *surf, cairo_operator_t op, ID2D1RenderTarget *rt, cairo_clip_t *clip, const cairo_rectangle_int_t *bounds = NULL);
|
||||
|
||||
RefPtr<ID2D1RenderTarget> _cairo_d2d_get_temp_rt(cairo_d2d_surface_t *surf, cairo_clip_t *clip);
|
||||
|
||||
cairo_operator_t _cairo_d2d_simplify_operator(cairo_operator_t op, const cairo_pattern_t *source);
|
||||
|
||||
#endif /* CAIRO_HAS_D2D_SURFACE */
|
||||
#endif /* CAIRO_D2D_PRIVATE_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1262,32 +1262,52 @@ _cairo_dwrite_show_glyphs_on_d2d_surface(void *surface,
|
||||
if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_DWRITE)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
op = _cairo_d2d_simplify_operator(op, source);
|
||||
|
||||
/* We can only handle operator SOURCE or OVER with the destination
|
||||
* having no alpha */
|
||||
if (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_OVER)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
/* We cannot handle operator SOURCE or CLEAR */
|
||||
if (op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_CLEAR) {
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
_cairo_d2d_begin_draw_state (dst);
|
||||
_cairo_d2d_set_clip (dst, clip);
|
||||
RefPtr<ID2D1RenderTarget> target_rt = dst->rt;
|
||||
cairo_rectangle_int_t fontArea;
|
||||
#ifndef ALWAYS_MANUAL_COMPOSITE
|
||||
if (op != CAIRO_OPERATOR_OVER) {
|
||||
#endif
|
||||
target_rt = _cairo_d2d_get_temp_rt(dst, clip);
|
||||
|
||||
if (!target_rt) {
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
#ifndef ALWAYS_MANUAL_COMPOSITE
|
||||
} else {
|
||||
_cairo_d2d_begin_draw_state(dst);
|
||||
status = (cairo_int_status_t)_cairo_d2d_set_clip (dst, clip);
|
||||
|
||||
if (unlikely(status))
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
D2D1_TEXT_ANTIALIAS_MODE cleartype = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
|
||||
D2D1_TEXT_ANTIALIAS_MODE highest_quality = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
|
||||
|
||||
if (dst->base.content != CAIRO_CONTENT_COLOR) {
|
||||
cleartype = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
|
||||
// If we're rendering to a temporary surface we cannot do sub-pixel AA.
|
||||
if (dst->base.content != CAIRO_CONTENT_COLOR || dst->rt.get() != target_rt.get()) {
|
||||
highest_quality = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
|
||||
}
|
||||
|
||||
switch (scaled_font->options.antialias) {
|
||||
case CAIRO_ANTIALIAS_DEFAULT:
|
||||
dst->rt->SetTextAntialiasMode(cleartype);
|
||||
target_rt->SetTextAntialiasMode(highest_quality);
|
||||
break;
|
||||
case CAIRO_ANTIALIAS_NONE:
|
||||
dst->rt->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
|
||||
target_rt->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
|
||||
break;
|
||||
case CAIRO_ANTIALIAS_GRAY:
|
||||
dst->rt->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
|
||||
target_rt->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
|
||||
break;
|
||||
case CAIRO_ANTIALIAS_SUBPIXEL:
|
||||
dst->rt->SetTextAntialiasMode(cleartype);
|
||||
target_rt->SetTextAntialiasMode(highest_quality);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1349,7 +1369,29 @@ _cairo_dwrite_show_glyphs_on_d2d_surface(void *surface,
|
||||
D2D1::Matrix3x2F mat = _cairo_d2d_matrix_from_matrix(&dwritesf->mat);
|
||||
|
||||
if (transform) {
|
||||
dst->rt->SetTransform(mat);
|
||||
target_rt->SetTransform(mat);
|
||||
}
|
||||
|
||||
if (dst->rt.get() != target_rt.get()) {
|
||||
RefPtr<IDWriteGlyphRunAnalysis> analysis;
|
||||
DWRITE_MATRIX dwmat = _cairo_dwrite_matrix_from_matrix(&dwritesf->mat);
|
||||
DWriteFactory::Instance()->CreateGlyphRunAnalysis(&run,
|
||||
1.0f,
|
||||
transform ? &dwmat : 0,
|
||||
DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC,
|
||||
DWRITE_MEASURING_MODE_NATURAL,
|
||||
0,
|
||||
0,
|
||||
&analysis);
|
||||
|
||||
RECT bounds;
|
||||
analysis->GetAlphaTextureBounds(scaled_font->options.antialias == CAIRO_ANTIALIAS_NONE ?
|
||||
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,
|
||||
@ -1374,15 +1416,19 @@ _cairo_dwrite_show_glyphs_on_d2d_surface(void *surface,
|
||||
brush->SetTransform(&mat_brush);
|
||||
}
|
||||
|
||||
dst->rt->DrawGlyphRun(D2D1::Point2F(0, 0), &run, brush);
|
||||
target_rt->DrawGlyphRun(D2D1::Point2F(0, 0), &run, brush);
|
||||
|
||||
if (transform) {
|
||||
dst->rt->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
target_rt->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
}
|
||||
|
||||
delete [] indices;
|
||||
delete [] offsets;
|
||||
delete [] advances;
|
||||
|
||||
if (target_rt.get() != dst->rt.get()) {
|
||||
return _cairo_d2d_blend_temp_surface(dst, op, target_rt, clip, &fontArea);
|
||||
}
|
||||
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -94,6 +94,26 @@ _cairo_boxes_get_extents (const cairo_box_t *boxes,
|
||||
}
|
||||
}
|
||||
|
||||
/* This function will return 'true' if the containing_rectangle contains the
|
||||
* contained_rectangle, and false otherwise.
|
||||
*/
|
||||
cairo_bool_t
|
||||
_cairo_rectangle_contains (const cairo_rectangle_int_t *containing_rectangle,
|
||||
const cairo_rectangle_int_t *contained_rectangle)
|
||||
{
|
||||
if (containing_rectangle->x > contained_rectangle->x ||
|
||||
containing_rectangle->y > contained_rectangle->y)
|
||||
return FALSE;
|
||||
|
||||
if (containing_rectangle->x + containing_rectangle->width <
|
||||
contained_rectangle->x + contained_rectangle->width ||
|
||||
containing_rectangle->y + containing_rectangle->height <
|
||||
contained_rectangle->y + contained_rectangle->height)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* XXX We currently have a confusing mix of boxes and rectangles as
|
||||
* exemplified by this function. A #cairo_box_t is a rectangular area
|
||||
* represented by the coordinates of the upper left and lower right
|
||||
|
@ -107,6 +107,11 @@ public:
|
||||
return mPtr;
|
||||
}
|
||||
|
||||
T* operator->() const
|
||||
{
|
||||
return mPtr;
|
||||
}
|
||||
|
||||
operator bool()
|
||||
{
|
||||
return (mPtr ? true : false);
|
||||
|
@ -126,30 +126,88 @@ cairo_dwrite_font_face_create_for_dwrite_fontface(void *dwrite_font, void *dwrit
|
||||
#endif /* CAIRO_HAS_DWRITE_FONT */
|
||||
|
||||
#if CAIRO_HAS_D2D_SURFACE
|
||||
|
||||
struct _cairo_device
|
||||
{
|
||||
int type;
|
||||
int refcount;
|
||||
};
|
||||
typedef struct _cairo_device cairo_device_t;
|
||||
|
||||
/**
|
||||
* Create a D2D device
|
||||
*
|
||||
* \return New D2D device, NULL if creation failed.
|
||||
*/
|
||||
cairo_device_t *
|
||||
cairo_d2d_create_device();
|
||||
|
||||
/**
|
||||
* Releases a D2D device.
|
||||
*
|
||||
* \return References left to the device
|
||||
*/
|
||||
int
|
||||
cairo_release_device(cairo_device_t *device);
|
||||
|
||||
/**
|
||||
* Addrefs a D2D device.
|
||||
*
|
||||
* \return References to the device
|
||||
*/
|
||||
int
|
||||
cairo_addref_device(cairo_device_t *device);
|
||||
|
||||
/**
|
||||
* Flushes a D3D device. In most cases the surface backend will do this
|
||||
* internally, but when using a surfaces created from a shared handle this
|
||||
* should be executed manually when a different device is going to be accessing
|
||||
* the same surface data. This will also block until the device is finished
|
||||
* processing all work.
|
||||
*/
|
||||
void
|
||||
cairo_d2d_finish_device(cairo_device_t *device);
|
||||
|
||||
/**
|
||||
* Create a D2D surface for an HWND
|
||||
*
|
||||
* \param device Device used to create the surface
|
||||
* \param wnd Handle for the window
|
||||
* \param content Content of the window, should be COLOR_ALPHA for transparent windows
|
||||
* \return New cairo surface
|
||||
*/
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_d2d_surface_create_for_hwnd(HWND wnd, cairo_content_t content);
|
||||
cairo_d2d_surface_create_for_hwnd(cairo_device_t *device, HWND wnd, cairo_content_t content);
|
||||
|
||||
/**
|
||||
* Create a D2D surface of a certain size.
|
||||
*
|
||||
* \param device Device used to create the surface
|
||||
* \param format Cairo format of the surface
|
||||
* \param width Width of the surface
|
||||
* \param height Height of the surface
|
||||
* \return New cairo surface
|
||||
*/
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_d2d_surface_create(cairo_format_t format,
|
||||
cairo_d2d_surface_create(cairo_device_t *device,
|
||||
cairo_format_t format,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
/**
|
||||
* Create a D3D surface from a Texture SharedHandle, this is obtained from a
|
||||
* CreateTexture call on a D3D9 device. This has to be an A8R8G8B8 format
|
||||
* or an A8 format, the treatment of the alpha channel can be indicated using
|
||||
* the content parameter.
|
||||
*
|
||||
* \param device Device used to create the surface
|
||||
* \param handle Shared handle to the texture we want to wrap
|
||||
* \param content Content of the texture, COLOR_ALPHA for ARGB
|
||||
* \return New cairo surface
|
||||
*/
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_d2d_surface_create_for_handle(cairo_device_t *device, HANDLE handle, cairo_content_t content);
|
||||
|
||||
/**
|
||||
* Present the backbuffer for a surface create for an HWND. This needs
|
||||
* to be called when the owner of the original window surface wants to
|
||||
@ -172,15 +230,6 @@ void cairo_d2d_present_backbuffer(cairo_surface_t *surface);
|
||||
*/
|
||||
void cairo_d2d_scroll(cairo_surface_t *surface, int x, int y, cairo_rectangle_t *clip);
|
||||
|
||||
/**
|
||||
* Verify if D2D surfaces are actually supported. This will confirm the needed
|
||||
* hardware is available.
|
||||
*
|
||||
* \return True if the support is available. If false surface creation will
|
||||
* return error surfaces.
|
||||
*/
|
||||
cairo_bool_t cairo_d2d_has_support();
|
||||
|
||||
/**
|
||||
* Get a DC for the current render target. When selecting the retention option this
|
||||
* call can be relatively slow, since it may require reading back contents from the
|
||||
|
@ -271,6 +271,10 @@ cairo_private void
|
||||
_cairo_box_from_rectangle (cairo_box_t *box,
|
||||
const cairo_rectangle_int_t *rectangle);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_rectangle_contains (const cairo_rectangle_int_t *containing_rectangle,
|
||||
const cairo_rectangle_int_t *contained_rectangle);
|
||||
|
||||
cairo_private void
|
||||
_cairo_box_round_to_rectangle (const cairo_box_t *box,
|
||||
cairo_rectangle_int_t *rectangle);
|
||||
|
@ -84,7 +84,10 @@ CPPSRCS = \
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
|
||||
ifdef MOZ_ENABLE_D3D9_LAYER
|
||||
EXPORTS += LayerManagerD3D9.h
|
||||
EXPORTS += \
|
||||
LayerManagerD3D9.h \
|
||||
DeviceManagerD3D9.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS += \
|
||||
LayerManagerD3D9.cpp \
|
||||
@ -93,6 +96,7 @@ CPPSRCS += \
|
||||
ImageLayerD3D9.cpp \
|
||||
ColorLayerD3D9.cpp \
|
||||
CanvasLayerD3D9.cpp \
|
||||
DeviceManagerD3D9.cpp \
|
||||
$(NULL)
|
||||
endif
|
||||
endif
|
||||
|
@ -70,9 +70,17 @@ CanvasLayerD3D9::Initialize(const Data& aData)
|
||||
|
||||
mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
|
||||
|
||||
device()->CreateTexture(mBounds.width, mBounds.height, 1, 0,
|
||||
D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
|
||||
getter_AddRefs(mTexture), NULL);
|
||||
if (mD3DManager->deviceManager()->HasDynamicTextures()) {
|
||||
device()->CreateTexture(mBounds.width, mBounds.height, 1, D3DUSAGE_DYNAMIC,
|
||||
D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT,
|
||||
getter_AddRefs(mTexture), NULL);
|
||||
} else {
|
||||
// D3DPOOL_MANAGED is fine here since we require Dynamic Textures for D3D9Ex
|
||||
// devices.
|
||||
device()->CreateTexture(mBounds.width, mBounds.height, 1, 0,
|
||||
D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
|
||||
getter_AddRefs(mTexture), NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -230,7 +238,7 @@ CanvasLayerD3D9::RenderLayer()
|
||||
opacity[0] = GetOpacity();
|
||||
device()->SetPixelShaderConstantF(0, opacity, 1);
|
||||
|
||||
mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER);
|
||||
mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER);
|
||||
|
||||
if (!mGLBufferIsPremultiplied) {
|
||||
device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
|
@ -76,7 +76,7 @@ ColorLayerD3D9::RenderLayer()
|
||||
|
||||
device()->SetPixelShaderConstantF(0, color, 1);
|
||||
|
||||
mD3DManager->SetShaderMode(LayerManagerD3D9::SOLIDCOLORLAYER);
|
||||
mD3DManager->SetShaderMode(DeviceManagerD3D9::SOLIDCOLORLAYER);
|
||||
|
||||
device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
|
||||
}
|
||||
|
@ -254,7 +254,7 @@ ContainerLayerD3D9::RenderLayer()
|
||||
opacityVector[0] = opacity;
|
||||
device()->SetPixelShaderConstantF(0, opacityVector, 1);
|
||||
|
||||
mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER);
|
||||
mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER);
|
||||
|
||||
device()->SetTexture(0, renderTexture);
|
||||
device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
|
||||
|
562
gfx/layers/d3d9/DeviceManagerD3D9.cpp
Normal file
562
gfx/layers/d3d9/DeviceManagerD3D9.cpp
Normal file
@ -0,0 +1,562 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Corporation code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Bas Schouten <bschouten@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "DeviceManagerD3D9.h"
|
||||
#include "LayerManagerD3D9Shaders.h"
|
||||
#include "ThebesLayerD3D9.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsPrintfCString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
const LPCWSTR kClassName = L"D3D9WindowClass";
|
||||
|
||||
#define USE_D3D9EX
|
||||
|
||||
typedef IDirect3D9* (WINAPI*Direct3DCreate9Func)(
|
||||
UINT SDKVersion
|
||||
);
|
||||
|
||||
typedef HRESULT (WINAPI*Direct3DCreate9ExFunc)(
|
||||
UINT SDKVersion,
|
||||
IDirect3D9Ex **ppD3D
|
||||
);
|
||||
|
||||
struct vertex {
|
||||
float x, y;
|
||||
};
|
||||
|
||||
SwapChainD3D9::SwapChainD3D9(DeviceManagerD3D9 *aDeviceManager)
|
||||
: mDeviceManager(aDeviceManager)
|
||||
, mWnd(0)
|
||||
{
|
||||
mDeviceManager->mSwapChains.AppendElement(this);
|
||||
}
|
||||
|
||||
SwapChainD3D9::~SwapChainD3D9()
|
||||
{
|
||||
mDeviceManager->mSwapChains.RemoveElement(this);
|
||||
}
|
||||
|
||||
bool
|
||||
SwapChainD3D9::Init(HWND hWnd)
|
||||
{
|
||||
RECT r;
|
||||
::GetClientRect(hWnd, &r);
|
||||
|
||||
mWnd = hWnd;
|
||||
|
||||
D3DPRESENT_PARAMETERS pp;
|
||||
memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
|
||||
|
||||
pp.BackBufferFormat = D3DFMT_UNKNOWN;
|
||||
pp.SwapEffect = D3DSWAPEFFECT_COPY;
|
||||
pp.Windowed = TRUE;
|
||||
pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||
pp.hDeviceWindow = mWnd;
|
||||
if (r.left == r.right || r.top == r.bottom) {
|
||||
pp.BackBufferHeight = 1;
|
||||
pp.BackBufferWidth = 1;
|
||||
}
|
||||
|
||||
HRESULT hr = mDeviceManager->device()->
|
||||
CreateAdditionalSwapChain(&pp,
|
||||
getter_AddRefs(mSwapChain));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to create swap chain for window.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SwapChainD3D9::PrepareForRendering()
|
||||
{
|
||||
RECT r;
|
||||
if (!::GetClientRect(mWnd, &r)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mDeviceManager->VerifyReadyForRendering()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mSwapChain) {
|
||||
Init(mWnd);
|
||||
}
|
||||
|
||||
if (mSwapChain) {
|
||||
nsRefPtr<IDirect3DSurface9> backBuffer;
|
||||
mSwapChain->GetBackBuffer(0,
|
||||
D3DBACKBUFFER_TYPE_MONO,
|
||||
getter_AddRefs(backBuffer));
|
||||
|
||||
D3DSURFACE_DESC desc;
|
||||
backBuffer->GetDesc(&desc);
|
||||
|
||||
if (desc.Width == r.right - r.left && desc.Height == r.bottom - r.top) {
|
||||
mDeviceManager->device()->SetRenderTarget(0, backBuffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
mSwapChain = nsnull;
|
||||
|
||||
Init(mWnd);
|
||||
|
||||
if (!mSwapChain) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mSwapChain->GetBackBuffer(0,
|
||||
D3DBACKBUFFER_TYPE_MONO,
|
||||
getter_AddRefs(backBuffer));
|
||||
|
||||
mDeviceManager->device()->SetRenderTarget(0, backBuffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
SwapChainD3D9::Present(const nsIntRect &aRect)
|
||||
{
|
||||
RECT r;
|
||||
r.left = aRect.x;
|
||||
r.top = aRect.y;
|
||||
r.right = aRect.XMost();
|
||||
r.bottom = aRect.YMost();
|
||||
|
||||
mSwapChain->Present(&r, &r, 0, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
SwapChainD3D9::Reset()
|
||||
{
|
||||
mSwapChain = nsnull;
|
||||
}
|
||||
|
||||
#define HAS_CAP(a, b) (((a) & (b)) == (b))
|
||||
#define LACKS_CAP(a, b) !(((a) & (b)) == (b))
|
||||
|
||||
DeviceManagerD3D9::DeviceManagerD3D9()
|
||||
: mHasDynamicTextures(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
DeviceManagerD3D9::Init()
|
||||
{
|
||||
WNDCLASSW wc;
|
||||
HRESULT hr;
|
||||
|
||||
if (!GetClassInfoW(GetModuleHandle(NULL), kClassName, &wc)) {
|
||||
ZeroMemory(&wc, sizeof(WNDCLASSW));
|
||||
wc.hInstance = GetModuleHandle(NULL);
|
||||
wc.lpfnWndProc = ::DefWindowProc;
|
||||
wc.lpszClassName = kClassName;
|
||||
if (!RegisterClassW(&wc)) {
|
||||
NS_WARNING("Failed to register window class for DeviceManager.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
mFocusWnd = ::CreateWindowW(kClassName, L"D3D9Window", WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL,
|
||||
NULL, GetModuleHandle(NULL), NULL);
|
||||
|
||||
if (!mFocusWnd) {
|
||||
NS_WARNING("Failed to create DeviceManagerD3D9 Window.");
|
||||
return false;
|
||||
}
|
||||
|
||||
HMODULE d3d9 = LoadLibraryW(L"d3d9.dll");
|
||||
Direct3DCreate9Func d3d9Create = (Direct3DCreate9Func)
|
||||
GetProcAddress(d3d9, "Direct3DCreate9");
|
||||
Direct3DCreate9ExFunc d3d9CreateEx = (Direct3DCreate9ExFunc)
|
||||
GetProcAddress(d3d9, "Direct3DCreate9Ex");
|
||||
|
||||
#ifdef USE_D3D9EX
|
||||
if (d3d9CreateEx) {
|
||||
hr = d3d9CreateEx(D3D_SDK_VERSION, getter_AddRefs(mD3D9Ex));
|
||||
if (SUCCEEDED(hr)) {
|
||||
mD3D9 = mD3D9Ex;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!mD3D9) {
|
||||
if (!d3d9Create) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mD3D9 = dont_AddRef(d3d9Create(D3D_SDK_VERSION));
|
||||
|
||||
if (!mD3D9) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
D3DPRESENT_PARAMETERS pp;
|
||||
memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
|
||||
|
||||
pp.BackBufferWidth = 1;
|
||||
pp.BackBufferHeight = 1;
|
||||
pp.BackBufferFormat = D3DFMT_A8R8G8B8;
|
||||
pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
pp.Windowed = TRUE;
|
||||
pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
|
||||
pp.hDeviceWindow = mFocusWnd;
|
||||
|
||||
if (mD3D9Ex) {
|
||||
hr = mD3D9Ex->CreateDeviceEx(D3DADAPTER_DEFAULT,
|
||||
D3DDEVTYPE_HAL,
|
||||
mFocusWnd,
|
||||
D3DCREATE_FPU_PRESERVE |
|
||||
D3DCREATE_MULTITHREADED |
|
||||
D3DCREATE_MIXED_VERTEXPROCESSING,
|
||||
&pp,
|
||||
NULL,
|
||||
getter_AddRefs(mDeviceEx));
|
||||
if (SUCCEEDED(hr)) {
|
||||
mDevice = mDeviceEx;
|
||||
}
|
||||
|
||||
D3DCAPS9 caps;
|
||||
if (mDeviceEx->GetDeviceCaps(&caps)) {
|
||||
if (LACKS_CAP(caps.Caps2, D3DCAPS2_DYNAMICTEXTURES)) {
|
||||
// XXX - Should we actually hit this we'll need a CanvasLayer that
|
||||
// supports static D3DPOOL_DEFAULT textures.
|
||||
NS_WARNING("D3D9Ex device not used because of lack of support for \
|
||||
dynamic textures. This is unexpected.");
|
||||
mDevice = nsnull;
|
||||
mDeviceEx = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!mDevice) {
|
||||
hr = mD3D9->CreateDevice(D3DADAPTER_DEFAULT,
|
||||
D3DDEVTYPE_HAL,
|
||||
mFocusWnd,
|
||||
D3DCREATE_FPU_PRESERVE |
|
||||
D3DCREATE_MULTITHREADED |
|
||||
D3DCREATE_MIXED_VERTEXPROCESSING,
|
||||
&pp,
|
||||
getter_AddRefs(mDevice));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to create Device for DeviceManagerD3D9.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!VerifyCaps()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVS,
|
||||
getter_AddRefs(mLayerVS));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = mDevice->CreatePixelShader((DWORD*)RGBShaderPS,
|
||||
getter_AddRefs(mRGBPS));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = mDevice->CreatePixelShader((DWORD*)YCbCrShaderPS,
|
||||
getter_AddRefs(mYCbCrPS));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = mDevice->CreatePixelShader((DWORD*)SolidColorShaderPS,
|
||||
getter_AddRefs(mSolidColorPS));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = mDevice->CreateVertexBuffer(sizeof(vertex) * 4,
|
||||
D3DUSAGE_WRITEONLY,
|
||||
0,
|
||||
D3DPOOL_DEFAULT,
|
||||
getter_AddRefs(mVB),
|
||||
NULL);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
vertex *vertices;
|
||||
hr = mVB->Lock(0, 0, (void**)&vertices, 0);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
vertices[0].x = vertices[0].y = 0;
|
||||
vertices[1].x = 1; vertices[1].y = 0;
|
||||
vertices[2].x = 0; vertices[2].y = 1;
|
||||
vertices[3].x = 1; vertices[3].y = 1;
|
||||
|
||||
mVB->Unlock();
|
||||
|
||||
hr = mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex));
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
D3DVERTEXELEMENT9 elements[] = {
|
||||
{ 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,
|
||||
D3DDECLUSAGE_POSITION, 0 },
|
||||
D3DDECL_END()
|
||||
};
|
||||
|
||||
mDevice->CreateVertexDeclaration(elements, getter_AddRefs(mVD));
|
||||
|
||||
nsCOMPtr<nsIConsoleService>
|
||||
console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
|
||||
|
||||
D3DADAPTER_IDENTIFIER9 identifier;
|
||||
mD3D9->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &identifier);
|
||||
|
||||
if (console) {
|
||||
nsString msg;
|
||||
msg +=
|
||||
NS_LITERAL_STRING("Direct3D 9 DeviceManager Initialized Succesfully.\nDriver: ");
|
||||
msg += NS_ConvertUTF8toUTF16(
|
||||
nsDependentCString((const char*)identifier.Driver));
|
||||
msg += NS_LITERAL_STRING("\nDescription: ");
|
||||
msg += NS_ConvertUTF8toUTF16(
|
||||
nsDependentCString((const char*)identifier.Description));
|
||||
msg += NS_LITERAL_STRING("\nVersion: ");
|
||||
msg += NS_ConvertUTF8toUTF16(
|
||||
nsPrintfCString("%d.%d.%d.%d",
|
||||
HIWORD(identifier.DriverVersion.HighPart),
|
||||
LOWORD(identifier.DriverVersion.HighPart),
|
||||
HIWORD(identifier.DriverVersion.LowPart),
|
||||
LOWORD(identifier.DriverVersion.LowPart)));
|
||||
console->LogStringMessage(msg.get());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
DeviceManagerD3D9::SetupRenderState()
|
||||
{
|
||||
mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex));
|
||||
mDevice->SetVertexDeclaration(mVD);
|
||||
mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
|
||||
mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
|
||||
mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
|
||||
mDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
||||
mDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
||||
mDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
||||
mDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
||||
mDevice->SetSamplerState(2, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
||||
mDevice->SetSamplerState(2, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
||||
}
|
||||
|
||||
already_AddRefed<SwapChainD3D9>
|
||||
DeviceManagerD3D9::CreateSwapChain(HWND hWnd)
|
||||
{
|
||||
nsRefPtr<SwapChainD3D9> swapChain = new SwapChainD3D9(this);
|
||||
|
||||
if (!swapChain->Init(hWnd)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return swapChain.forget();
|
||||
}
|
||||
|
||||
void
|
||||
DeviceManagerD3D9::SetShaderMode(ShaderMode aMode)
|
||||
{
|
||||
switch (aMode) {
|
||||
case RGBLAYER:
|
||||
mDevice->SetVertexShader(mLayerVS);
|
||||
mDevice->SetPixelShader(mRGBPS);
|
||||
break;
|
||||
case YCBCRLAYER:
|
||||
mDevice->SetVertexShader(mLayerVS);
|
||||
mDevice->SetPixelShader(mYCbCrPS);
|
||||
break;
|
||||
case SOLIDCOLORLAYER:
|
||||
mDevice->SetVertexShader(mLayerVS);
|
||||
mDevice->SetPixelShader(mSolidColorPS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
DeviceManagerD3D9::VerifyReadyForRendering()
|
||||
{
|
||||
HRESULT hr = mDevice->TestCooperativeLevel();
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
if (IsD3D9Ex()) {
|
||||
hr = mDeviceEx->CheckDeviceState(mFocusWnd);
|
||||
if (FAILED(hr)) {
|
||||
D3DPRESENT_PARAMETERS pp;
|
||||
memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
|
||||
|
||||
pp.BackBufferWidth = 1;
|
||||
pp.BackBufferHeight = 1;
|
||||
pp.BackBufferFormat = D3DFMT_A8R8G8B8;
|
||||
pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
pp.Windowed = TRUE;
|
||||
pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
|
||||
pp.hDeviceWindow = mFocusWnd;
|
||||
|
||||
hr = mDeviceEx->ResetEx(&pp, NULL);
|
||||
// Handle D3DERR_DEVICEREMOVED!
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hr != D3DERR_DEVICENOTRESET) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < mThebesLayers.Length(); i++) {
|
||||
mThebesLayers[i]->CleanResources();
|
||||
}
|
||||
for(unsigned int i = 0; i < mSwapChains.Length(); i++) {
|
||||
mSwapChains[i]->Reset();
|
||||
}
|
||||
|
||||
D3DPRESENT_PARAMETERS pp;
|
||||
memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
|
||||
|
||||
pp.BackBufferWidth = 1;
|
||||
pp.BackBufferHeight = 1;
|
||||
pp.BackBufferFormat = D3DFMT_A8R8G8B8;
|
||||
pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
pp.Windowed = TRUE;
|
||||
pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
|
||||
pp.hDeviceWindow = mFocusWnd;
|
||||
|
||||
hr = mDevice->Reset(&pp);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DeviceManagerD3D9::VerifyCaps()
|
||||
{
|
||||
D3DCAPS9 caps;
|
||||
HRESULT hr = mDevice->GetDeviceCaps(&caps);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.DevCaps, D3DDEVCAPS_TEXTUREVIDEOMEMORY)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.PrimitiveMiscCaps, D3DPMISCCAPS_CULLNONE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.SrcBlendCaps, D3DPBLENDCAPS_ONE) ||
|
||||
LACKS_CAP(caps.SrcBlendCaps, D3DBLEND_SRCALPHA) ||
|
||||
LACKS_CAP(caps.DestBlendCaps, D3DPBLENDCAPS_INVSRCALPHA)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.RasterCaps, D3DPRASTERCAPS_SCISSORTEST)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_ALPHA) ||
|
||||
HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_SQUAREONLY) ||
|
||||
(HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_POW2) &&
|
||||
LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_NONPOW2CONDITIONAL))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MAGFLINEAR) ||
|
||||
LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MINFLINEAR)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.TextureAddressCaps, D3DPTADDRESSCAPS_CLAMP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (caps.MaxTextureHeight < 4096 ||
|
||||
caps.MaxTextureWidth < 4096) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((caps.PixelShaderVersion & 0xffff) < 0x200 ||
|
||||
(caps.VertexShaderVersion & 0xffff) < 0x200) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (HAS_CAP(caps.Caps2, D3DCAPS2_DYNAMICTEXTURES)) {
|
||||
mHasDynamicTextures = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} /* namespace layers */
|
||||
} /* namespace mozilla */
|
207
gfx/layers/d3d9/DeviceManagerD3D9.h
Normal file
207
gfx/layers/d3d9/DeviceManagerD3D9.h
Normal file
@ -0,0 +1,207 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Corporation code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Bas Schouten <bschouten@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef GFX_DEVICEMANAGERD3D9_H
|
||||
#define GFX_DEVICEMANAGERD3D9_H
|
||||
|
||||
#include "gfxTypes.h"
|
||||
#include "nsRect.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "d3d9.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class DeviceManagerD3D9;
|
||||
class ThebesLayerD3D9;
|
||||
|
||||
/**
|
||||
* SwapChain class, this class manages the swap chain belonging to a
|
||||
* LayerManagerD3D9.
|
||||
*/
|
||||
class THEBES_API SwapChainD3D9
|
||||
{
|
||||
NS_INLINE_DECL_REFCOUNTING(SwapChainD3D9)
|
||||
public:
|
||||
~SwapChainD3D9();
|
||||
|
||||
/**
|
||||
* This function will prepare the device this swap chain belongs to for
|
||||
* rendering to this swap chain. Only after calling this function can the
|
||||
* swap chain be drawn to, and only until this function is called on another
|
||||
* swap chain belonging to this device will the device draw to it. Passed in
|
||||
* is the size of the swap chain. If the window size differs from the size
|
||||
* during the last call to this function the swap chain will resize. Note that
|
||||
* in no case does this function guarantee the backbuffer to still have its
|
||||
* old content.
|
||||
*/
|
||||
bool PrepareForRendering();
|
||||
|
||||
/**
|
||||
* This function will present the selected rectangle of the swap chain to
|
||||
* its associated window.
|
||||
*/
|
||||
void Present(const nsIntRect &aRect);
|
||||
|
||||
private:
|
||||
friend class DeviceManagerD3D9;
|
||||
|
||||
SwapChainD3D9(DeviceManagerD3D9 *aDeviceManager);
|
||||
|
||||
bool Init(HWND hWnd);
|
||||
|
||||
/**
|
||||
* This causes us to release our swap chain, clearing out our resource usage
|
||||
* so the master device may reset.
|
||||
*/
|
||||
void Reset();
|
||||
|
||||
nsRefPtr<IDirect3DSwapChain9> mSwapChain;
|
||||
nsRefPtr<DeviceManagerD3D9> mDeviceManager;
|
||||
HWND mWnd;
|
||||
};
|
||||
|
||||
/**
|
||||
* Device manager, this class is used by the layer managers to share the D3D9
|
||||
* device and create swap chains for the individual windows the layer managers
|
||||
* belong to.
|
||||
*/
|
||||
class THEBES_API DeviceManagerD3D9
|
||||
{
|
||||
public:
|
||||
DeviceManagerD3D9();
|
||||
|
||||
// We want the nsrefcnt return value. So we cannot use the inline refcnt macro
|
||||
NS_IMPL_ADDREF(DeviceManagerD3D9)
|
||||
NS_IMPL_RELEASE(DeviceManagerD3D9)
|
||||
|
||||
bool Init();
|
||||
|
||||
/**
|
||||
* Sets up the render state for the device for layer rendering.
|
||||
*/
|
||||
void SetupRenderState();
|
||||
|
||||
/**
|
||||
* Create a swap chain setup to work with the specified window.
|
||||
*/
|
||||
already_AddRefed<SwapChainD3D9> CreateSwapChain(HWND hWnd);
|
||||
|
||||
IDirect3DDevice9 *device() { return mDevice; }
|
||||
|
||||
bool IsD3D9Ex() { return mDeviceEx; }
|
||||
|
||||
bool HasDynamicTextures() { return mHasDynamicTextures; }
|
||||
|
||||
enum ShaderMode {
|
||||
RGBLAYER,
|
||||
YCBCRLAYER,
|
||||
SOLIDCOLORLAYER
|
||||
};
|
||||
|
||||
void SetShaderMode(ShaderMode aMode);
|
||||
|
||||
/**
|
||||
* We keep a list of all thebes layers since we need their D3DPOOL_DEFAULT
|
||||
* surfaces to be released when we want to reset the device.
|
||||
*/
|
||||
nsTArray<ThebesLayerD3D9*> mThebesLayers;
|
||||
private:
|
||||
friend class SwapChainD3D9;
|
||||
|
||||
/**
|
||||
* This function verifies the device is ready for rendering, internally this
|
||||
* will test the cooperative level of the device and reset the device if
|
||||
* needed. If this returns false subsequent rendering calls may return errors.
|
||||
*/
|
||||
bool VerifyReadyForRendering();
|
||||
|
||||
/* Array used to store all swap chains for device resets */
|
||||
nsTArray<SwapChainD3D9*> mSwapChains;
|
||||
|
||||
/* The D3D device we use */
|
||||
nsRefPtr<IDirect3DDevice9> mDevice;
|
||||
|
||||
/* The D3D9Ex device - only valid on Vista+ with WDDM */
|
||||
nsRefPtr<IDirect3DDevice9Ex> mDeviceEx;
|
||||
|
||||
/* An instance of the D3D9 object */
|
||||
nsRefPtr<IDirect3D9> mD3D9;
|
||||
|
||||
/* An instance of the D3D9Ex object - only valid on Vista+ with WDDM */
|
||||
nsRefPtr<IDirect3D9Ex> mD3D9Ex;
|
||||
|
||||
/* Vertex shader used for layer quads */
|
||||
nsRefPtr<IDirect3DVertexShader9> mLayerVS;
|
||||
|
||||
/* Pixel shader used for RGB textures */
|
||||
nsRefPtr<IDirect3DPixelShader9> mRGBPS;
|
||||
|
||||
/* Pixel shader used for RGB textures */
|
||||
nsRefPtr<IDirect3DPixelShader9> mYCbCrPS;
|
||||
|
||||
/* Pixel shader used for solid colors */
|
||||
nsRefPtr<IDirect3DPixelShader9> mSolidColorPS;
|
||||
|
||||
/* Vertex buffer containing our basic vertex structure */
|
||||
nsRefPtr<IDirect3DVertexBuffer9> mVB;
|
||||
|
||||
/* Our vertex declaration */
|
||||
nsRefPtr<IDirect3DVertexDeclaration9> mVD;
|
||||
|
||||
/* Our focus window - this is really a dummy window we can associate our
|
||||
* device with.
|
||||
*/
|
||||
HWND mFocusWnd;
|
||||
|
||||
/* If this device supports dynamic textures */
|
||||
bool mHasDynamicTextures;
|
||||
|
||||
nsAutoRefCnt mRefCnt;
|
||||
NS_DECL_OWNINGTHREAD
|
||||
|
||||
/**
|
||||
* Verifies all required device capabilities are present.
|
||||
*/
|
||||
bool VerifyCaps();
|
||||
};
|
||||
|
||||
} /* namespace layers */
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* GFX_DEVICEMANAGERD3D9_H */
|
@ -185,7 +185,7 @@ ImageLayerD3D9::RenderLayer()
|
||||
opacity[0] = GetOpacity();
|
||||
device()->SetPixelShaderConstantF(0, opacity, 1);
|
||||
|
||||
mD3DManager->SetShaderMode(LayerManagerD3D9::YCBCRLAYER);
|
||||
mD3DManager->SetShaderMode(DeviceManagerD3D9::YCBCRLAYER);
|
||||
|
||||
device()->SetTexture(0, yuvImage->mYTexture);
|
||||
device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
@ -227,7 +227,7 @@ ImageLayerD3D9::RenderLayer()
|
||||
opacity[0] = GetOpacity();
|
||||
device()->SetPixelShaderConstantF(0, opacity, 1);
|
||||
|
||||
mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER);
|
||||
mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER);
|
||||
|
||||
device()->SetTexture(0, cairoImage->mTexture);
|
||||
device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
|
||||
@ -244,6 +244,7 @@ PlanarYCbCrImageD3D9::PlanarYCbCrImageD3D9(mozilla::layers::LayerManagerD3D9* aM
|
||||
void
|
||||
PlanarYCbCrImageD3D9::SetData(const PlanarYCbCrImage::Data &aData)
|
||||
{
|
||||
// XXX - For D3D9Ex we really should just copy to systemmem surfaces here.
|
||||
// For now, we copy the data
|
||||
int width_shift = 0;
|
||||
int height_shift = 0;
|
||||
@ -309,76 +310,116 @@ PlanarYCbCrImageD3D9::AllocateTextures()
|
||||
{
|
||||
|
||||
|
||||
D3DLOCKED_RECT lockrect;
|
||||
D3DLOCKED_RECT lockrectY;
|
||||
D3DLOCKED_RECT lockrectCb;
|
||||
D3DLOCKED_RECT lockrectCr;
|
||||
PRUint8* src;
|
||||
PRUint8* dest;
|
||||
//XXX: ensure correct usage flags
|
||||
mManager->device()->CreateTexture(mData.mYSize.width, mData.mYSize.height,
|
||||
1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
|
||||
getter_AddRefs(mYTexture), NULL);
|
||||
|
||||
nsRefPtr<IDirect3DSurface9> tmpSurfaceY;
|
||||
nsRefPtr<IDirect3DSurface9> tmpSurfaceCb;
|
||||
nsRefPtr<IDirect3DSurface9> tmpSurfaceCr;
|
||||
|
||||
/* lock the entire texture */
|
||||
mYTexture->LockRect(0, &lockrect, NULL, 0);
|
||||
if (mManager->deviceManager()->IsD3D9Ex()) {
|
||||
// D3D9Ex does not support the managed pool, could use dynamic textures
|
||||
// here. But since an Image is immutable static textures are probably a
|
||||
// better idea.
|
||||
mManager->device()->CreateTexture(mData.mYSize.width, mData.mYSize.height,
|
||||
1, 0, D3DFMT_L8, D3DPOOL_DEFAULT,
|
||||
getter_AddRefs(mYTexture), NULL);
|
||||
mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
|
||||
1, 0, D3DFMT_L8, D3DPOOL_DEFAULT,
|
||||
getter_AddRefs(mCbTexture), NULL);
|
||||
mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
|
||||
1, 0, D3DFMT_L8, D3DPOOL_DEFAULT,
|
||||
getter_AddRefs(mCrTexture), NULL);
|
||||
mManager->device()->CreateOffscreenPlainSurface(mData.mYSize.width,
|
||||
mData.mYSize.height,
|
||||
D3DFMT_L8,
|
||||
D3DPOOL_SYSTEMMEM,
|
||||
getter_AddRefs(tmpSurfaceY),
|
||||
NULL);
|
||||
mManager->device()->CreateOffscreenPlainSurface(mData.mCbCrSize.width,
|
||||
mData.mCbCrSize.height,
|
||||
D3DFMT_L8,
|
||||
D3DPOOL_SYSTEMMEM,
|
||||
getter_AddRefs(tmpSurfaceCb),
|
||||
NULL);
|
||||
mManager->device()->CreateOffscreenPlainSurface(mData.mCbCrSize.width,
|
||||
mData.mCbCrSize.height,
|
||||
D3DFMT_L8,
|
||||
D3DPOOL_SYSTEMMEM,
|
||||
getter_AddRefs(tmpSurfaceCr),
|
||||
NULL);
|
||||
tmpSurfaceY->LockRect(&lockrectY, NULL, 0);
|
||||
tmpSurfaceCb->LockRect(&lockrectCb, NULL, 0);
|
||||
tmpSurfaceCr->LockRect(&lockrectCr, NULL, 0);
|
||||
} else {
|
||||
mManager->device()->CreateTexture(mData.mYSize.width, mData.mYSize.height,
|
||||
1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
|
||||
getter_AddRefs(mYTexture), NULL);
|
||||
mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
|
||||
1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
|
||||
getter_AddRefs(mCbTexture), NULL);
|
||||
mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
|
||||
1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
|
||||
getter_AddRefs(mCrTexture), NULL);
|
||||
|
||||
/* lock the entire texture */
|
||||
mYTexture->LockRect(0, &lockrectY, NULL, 0);
|
||||
mCbTexture->LockRect(0, &lockrectCb, NULL, 0);
|
||||
mCrTexture->LockRect(0, &lockrectCr, NULL, 0);
|
||||
}
|
||||
|
||||
src = mData.mYChannel;
|
||||
//FIX cast
|
||||
dest = (PRUint8*)lockrect.pBits;
|
||||
dest = (PRUint8*)lockrectY.pBits;
|
||||
|
||||
// copy over data
|
||||
for (int h=0; h<mData.mYSize.height; h++) {
|
||||
memcpy(dest, src, mData.mYSize.width);
|
||||
dest += lockrect.Pitch;
|
||||
dest += lockrectY.Pitch;
|
||||
src += mData.mYStride;
|
||||
}
|
||||
|
||||
mYTexture->UnlockRect(0);
|
||||
|
||||
//XXX: ensure correct usage flags
|
||||
mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
|
||||
1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
|
||||
getter_AddRefs(mCbTexture), NULL);
|
||||
|
||||
|
||||
/* lock the entire texture */
|
||||
mCbTexture->LockRect(0, &lockrect, NULL, 0);
|
||||
|
||||
src = mData.mCbChannel;
|
||||
//FIX cast
|
||||
dest = (PRUint8*)lockrect.pBits;
|
||||
dest = (PRUint8*)lockrectCb.pBits;
|
||||
|
||||
// copy over data
|
||||
for (int h=0; h<mData.mCbCrSize.height; h++) {
|
||||
memcpy(dest, src, mData.mCbCrSize.width);
|
||||
dest += lockrect.Pitch;
|
||||
dest += lockrectCb.Pitch;
|
||||
src += mData.mCbCrStride;
|
||||
}
|
||||
|
||||
mCbTexture->UnlockRect(0);
|
||||
|
||||
|
||||
//XXX: ensure correct usage flags
|
||||
mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
|
||||
1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
|
||||
getter_AddRefs(mCrTexture), NULL);
|
||||
|
||||
|
||||
/* lock the entire texture */
|
||||
mCrTexture->LockRect(0, &lockrect, NULL, 0);
|
||||
|
||||
src = mData.mCrChannel;
|
||||
//FIX cast
|
||||
dest = (PRUint8*)lockrect.pBits;
|
||||
dest = (PRUint8*)lockrectCr.pBits;
|
||||
|
||||
// copy over data
|
||||
for (int h=0; h<mData.mCbCrSize.height; h++) {
|
||||
memcpy(dest, src, mData.mCbCrSize.width);
|
||||
dest += lockrect.Pitch;
|
||||
dest += lockrectCr.Pitch;
|
||||
src += mData.mCbCrStride;
|
||||
}
|
||||
|
||||
mCrTexture->UnlockRect(0);
|
||||
|
||||
if (mManager->deviceManager()->IsD3D9Ex()) {
|
||||
tmpSurfaceY->UnlockRect();
|
||||
tmpSurfaceCb->UnlockRect();
|
||||
tmpSurfaceCr->UnlockRect();
|
||||
nsRefPtr<IDirect3DSurface9> dstSurface;
|
||||
mYTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
|
||||
mManager->device()->UpdateSurface(tmpSurfaceY, NULL, dstSurface, NULL);
|
||||
mCbTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
|
||||
mManager->device()->UpdateSurface(tmpSurfaceCb, NULL, dstSurface, NULL);
|
||||
mCrTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
|
||||
mManager->device()->UpdateSurface(tmpSurfaceCr, NULL, dstSurface, NULL);
|
||||
} else {
|
||||
mYTexture->UnlockRect(0);
|
||||
mCbTexture->UnlockRect(0);
|
||||
mCrTexture->UnlockRect(0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -426,31 +467,49 @@ CairoImageD3D9::SetData(const CairoImage::Data &aData)
|
||||
context->SetSource(aData.mSurface);
|
||||
context->Paint();
|
||||
|
||||
//XXX: make sure we're using the correct usage flags
|
||||
mManager->device()->CreateTexture(aData.mSize.width, aData.mSize.height,
|
||||
1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
|
||||
getter_AddRefs(mTexture), NULL);
|
||||
if (mManager->deviceManager()->IsD3D9Ex()) {
|
||||
// D3D9Ex doesn't support managed textures. We could use dynamic textures
|
||||
// here but since Images are immutable that probably isn't such a great
|
||||
// idea.
|
||||
mManager->device()->CreateTexture(aData.mSize.width, aData.mSize.height,
|
||||
1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT,
|
||||
getter_AddRefs(mTexture), NULL);
|
||||
nsRefPtr<IDirect3DSurface9> surface;
|
||||
mManager->device()->CreateOffscreenPlainSurface(aData.mSize.width,
|
||||
aData.mSize.height,
|
||||
D3DFMT_A8R8G8B8,
|
||||
D3DPOOL_SYSTEMMEM,
|
||||
getter_AddRefs(surface),
|
||||
NULL);
|
||||
D3DLOCKED_RECT lockedRect;
|
||||
surface->LockRect(&lockedRect, NULL, 0);
|
||||
for (int y = 0; y < aData.mSize.height; y++) {
|
||||
memcpy((char*)lockedRect.pBits + lockedRect.Pitch * y,
|
||||
imageSurface->Data() + imageSurface->Stride() * y,
|
||||
aData.mSize.width * 4);
|
||||
}
|
||||
surface->UnlockRect();
|
||||
nsRefPtr<IDirect3DSurface9> dstSurface;
|
||||
mTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
|
||||
mManager->device()->UpdateSurface(surface, NULL, dstSurface, NULL);
|
||||
} else {
|
||||
mManager->device()->CreateTexture(aData.mSize.width, aData.mSize.height,
|
||||
1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
|
||||
getter_AddRefs(mTexture), NULL);
|
||||
D3DLOCKED_RECT lockrect;
|
||||
/* lock the entire texture */
|
||||
mTexture->LockRect(0, &lockrect, NULL, 0);
|
||||
|
||||
D3DLOCKED_RECT lockrect;
|
||||
/* lock the entire texture */
|
||||
mTexture->LockRect(0, &lockrect, NULL, 0);
|
||||
// copy over data. If we don't need to do any swaping we can
|
||||
// use memcpy
|
||||
for (int y = 0; y < aData.mSize.height; y++) {
|
||||
memcpy((char*)lockrect.pBits + lockrect.Pitch * y,
|
||||
imageSurface->Data() + imageSurface->Stride() * y,
|
||||
aData.mSize.width * 4);
|
||||
}
|
||||
|
||||
PRUint8* src = imageSurface->Data();
|
||||
//FIX cast
|
||||
PRUint8* dest = (PRUint8*)lockrect.pBits;
|
||||
|
||||
// copy over data. If we don't need to do any swaping we can
|
||||
// use memcpy
|
||||
for (int i=0; i<aData.mSize.width*aData.mSize.height; i++) {
|
||||
dest[0] = src[0];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[2];
|
||||
dest[3] = src[3];
|
||||
dest += 4;
|
||||
src += 4;
|
||||
mTexture->UnlockRect(0);
|
||||
}
|
||||
|
||||
mTexture->UnlockRect(0);
|
||||
}
|
||||
|
||||
already_AddRefed<gfxASurface>
|
||||
|
@ -43,25 +43,10 @@
|
||||
#include "ColorLayerD3D9.h"
|
||||
#include "CanvasLayerD3D9.h"
|
||||
|
||||
#include "LayerManagerD3D9Shaders.h"
|
||||
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsPrintfCString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
struct vertex {
|
||||
float x, y;
|
||||
};
|
||||
|
||||
IDirect3D9 *LayerManagerD3D9::mD3D9 = NULL;
|
||||
|
||||
typedef IDirect3D9* (WINAPI*Direct3DCreate9Func)(
|
||||
UINT SDKVersion
|
||||
);
|
||||
|
||||
DeviceManagerD3D9 *LayerManagerD3D9::mDeviceManager = nsnull;
|
||||
|
||||
LayerManagerD3D9::LayerManagerD3D9(nsIWidget *aWidget)
|
||||
{
|
||||
@ -72,145 +57,39 @@ LayerManagerD3D9::LayerManagerD3D9(nsIWidget *aWidget)
|
||||
|
||||
LayerManagerD3D9::~LayerManagerD3D9()
|
||||
{
|
||||
}
|
||||
/* Important to release this first since it also holds a reference to the
|
||||
* device manager
|
||||
*/
|
||||
mSwapChain = nsnull;
|
||||
|
||||
#define HAS_CAP(a, b) (((a) & (b)) == (b))
|
||||
#define LACKS_CAP(a, b) !(((a) & (b)) == (b))
|
||||
if (mDeviceManager) {
|
||||
if (!mDeviceManager->Release()) {
|
||||
mDeviceManager = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
LayerManagerD3D9::Initialize()
|
||||
{
|
||||
if (!mD3D9) {
|
||||
Direct3DCreate9Func d3d9create = (Direct3DCreate9Func)
|
||||
GetProcAddress(LoadLibraryW(L"d3d9.dll"), "Direct3DCreate9");
|
||||
if (!d3d9create) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (!mDeviceManager) {
|
||||
mDeviceManager = new DeviceManagerD3D9;
|
||||
|
||||
mD3D9 = d3d9create(D3D_SDK_VERSION);
|
||||
if (!mD3D9) {
|
||||
if (!mDeviceManager->Init()) {
|
||||
mDeviceManager = nsnull;
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
D3DPRESENT_PARAMETERS pp;
|
||||
memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
|
||||
mDeviceManager->AddRef();
|
||||
|
||||
pp.BackBufferFormat = D3DFMT_A8R8G8B8;
|
||||
pp.SwapEffect = D3DSWAPEFFECT_COPY;
|
||||
pp.Windowed = TRUE;
|
||||
pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
|
||||
pp.hDeviceWindow = (HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW);
|
||||
mSwapChain = mDeviceManager->
|
||||
CreateSwapChain((HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW));
|
||||
|
||||
HRESULT hr = mD3D9->CreateDevice(D3DADAPTER_DEFAULT,
|
||||
D3DDEVTYPE_HAL,
|
||||
NULL,
|
||||
D3DCREATE_FPU_PRESERVE |
|
||||
D3DCREATE_MULTITHREADED |
|
||||
D3DCREATE_MIXED_VERTEXPROCESSING,
|
||||
&pp,
|
||||
getter_AddRefs(mDevice));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
if (!mSwapChain) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (!VerifyCaps()) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVS,
|
||||
getter_AddRefs(mLayerVS));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
hr = mDevice->CreatePixelShader((DWORD*)RGBShaderPS,
|
||||
getter_AddRefs(mRGBPS));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
hr = mDevice->CreatePixelShader((DWORD*)YCbCrShaderPS,
|
||||
getter_AddRefs(mYCbCrPS));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
hr = mDevice->CreatePixelShader((DWORD*)SolidColorShaderPS,
|
||||
getter_AddRefs(mSolidColorPS));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
hr = mDevice->CreateVertexBuffer(sizeof(vertex) * 4,
|
||||
0,
|
||||
0,
|
||||
D3DPOOL_MANAGED,
|
||||
getter_AddRefs(mVB),
|
||||
NULL);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
vertex *vertices;
|
||||
hr = mVB->Lock(0, 0, (void**)&vertices, 0);
|
||||
if (FAILED(hr)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
vertices[0].x = vertices[0].y = 0;
|
||||
vertices[1].x = 1; vertices[1].y = 0;
|
||||
vertices[2].x = 0; vertices[2].y = 1;
|
||||
vertices[3].x = 1; vertices[3].y = 1;
|
||||
|
||||
mVB->Unlock();
|
||||
|
||||
hr = mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex));
|
||||
if (FAILED(hr)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
D3DVERTEXELEMENT9 elements[] = {
|
||||
{ 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,
|
||||
D3DDECLUSAGE_POSITION, 0 },
|
||||
D3DDECL_END()
|
||||
};
|
||||
|
||||
mDevice->CreateVertexDeclaration(elements, getter_AddRefs(mVD));
|
||||
|
||||
SetupRenderState();
|
||||
|
||||
nsCOMPtr<nsIConsoleService>
|
||||
console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
|
||||
|
||||
D3DADAPTER_IDENTIFIER9 identifier;
|
||||
mD3D9->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &identifier);
|
||||
|
||||
if (console) {
|
||||
nsString msg;
|
||||
msg +=
|
||||
NS_LITERAL_STRING("Direct3D 9 LayerManager Initialized Succesfully.\nDriver: ");
|
||||
msg += NS_ConvertUTF8toUTF16(
|
||||
nsDependentCString((const char*)identifier.Driver));
|
||||
msg += NS_LITERAL_STRING("\nDescription: ");
|
||||
msg += NS_ConvertUTF8toUTF16(
|
||||
nsDependentCString((const char*)identifier.Description));
|
||||
msg += NS_LITERAL_STRING("\nVersion: ");
|
||||
msg += NS_ConvertUTF8toUTF16(
|
||||
nsPrintfCString("%d.%d.%d.%d",
|
||||
HIWORD(identifier.DriverVersion.HighPart),
|
||||
LOWORD(identifier.DriverVersion.HighPart),
|
||||
HIWORD(identifier.DriverVersion.LowPart),
|
||||
LOWORD(identifier.DriverVersion.LowPart)));
|
||||
console->LogStringMessage(msg.get());
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
@ -298,38 +177,21 @@ LayerManagerD3D9::CreateImageContainer()
|
||||
return container.forget();
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D9::SetShaderMode(ShaderMode aMode)
|
||||
{
|
||||
switch (aMode) {
|
||||
case RGBLAYER:
|
||||
mDevice->SetVertexShader(mLayerVS);
|
||||
mDevice->SetPixelShader(mRGBPS);
|
||||
break;
|
||||
case YCBCRLAYER:
|
||||
mDevice->SetVertexShader(mLayerVS);
|
||||
mDevice->SetPixelShader(mYCbCrPS);
|
||||
break;
|
||||
case SOLIDCOLORLAYER:
|
||||
mDevice->SetVertexShader(mLayerVS);
|
||||
mDevice->SetPixelShader(mSolidColorPS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D9::Render()
|
||||
{
|
||||
if (!SetupBackBuffer()) {
|
||||
if (!mSwapChain->PrepareForRendering()) {
|
||||
return;
|
||||
}
|
||||
deviceManager()->SetupRenderState();
|
||||
|
||||
SetupPipeline();
|
||||
nsIntRect rect;
|
||||
mWidget->GetClientBounds(rect);
|
||||
|
||||
mDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0, 0);
|
||||
device()->Clear(0, NULL, D3DCLEAR_TARGET, 0x00000000, 0, 0);
|
||||
|
||||
mDevice->BeginScene();
|
||||
device()->BeginScene();
|
||||
|
||||
if (mRootLayer) {
|
||||
const nsIntRect *clipRect = mRootLayer->GetLayer()->GetClipRect();
|
||||
@ -344,24 +206,18 @@ LayerManagerD3D9::Render()
|
||||
r.right = rect.width;
|
||||
r.bottom = rect.height;
|
||||
}
|
||||
mDevice->SetScissorRect(&r);
|
||||
device()->SetScissorRect(&r);
|
||||
|
||||
mRootLayer->RenderLayer();
|
||||
}
|
||||
|
||||
mDevice->EndScene();
|
||||
device()->EndScene();
|
||||
|
||||
if (!mTarget) {
|
||||
const nsIntRect *r;
|
||||
for (nsIntRegionRectIterator iter(mClippingRegion);
|
||||
(r = iter.Next()) != nsnull;) {
|
||||
RECT rect;
|
||||
rect.left = r->x;
|
||||
rect.top = r->y;
|
||||
rect.right = r->XMost();
|
||||
rect.bottom = r->YMost();
|
||||
|
||||
mDevice->Present(&rect, &rect, NULL, NULL);
|
||||
mSwapChain->Present(*r);
|
||||
}
|
||||
} else {
|
||||
PaintToTarget();
|
||||
@ -387,86 +243,29 @@ LayerManagerD3D9::SetupPipeline()
|
||||
viewMatrix[3][1] = 1.0f;
|
||||
viewMatrix[3][3] = 1.0f;
|
||||
|
||||
HRESULT hr = mDevice->SetVertexShaderConstantF(8, &viewMatrix[0][0], 4);
|
||||
HRESULT hr = device()->SetVertexShaderConstantF(8, &viewMatrix[0][0], 4);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to set projection shader constant!");
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
LayerManagerD3D9::SetupBackBuffer()
|
||||
{
|
||||
nsRefPtr<IDirect3DSurface9> backBuffer;
|
||||
mDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO,
|
||||
getter_AddRefs(backBuffer));
|
||||
|
||||
D3DSURFACE_DESC desc;
|
||||
nsIntRect rect;
|
||||
mWidget->GetClientBounds(rect);
|
||||
backBuffer->GetDesc(&desc);
|
||||
|
||||
HRESULT hr = mDevice->TestCooperativeLevel();
|
||||
|
||||
/* The device is lost or something else is wrong, failure */
|
||||
if (FAILED(hr) && hr != D3DERR_DEVICENOTRESET) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the backbuffer is the right size, and the device is not lost, we can
|
||||
* safely render without doing anything.
|
||||
*/
|
||||
if ((desc.Width == rect.width && desc.Height == rect.height) &&
|
||||
SUCCEEDED(hr)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Our device is lost or our backbuffer needs resizing, start by clearing
|
||||
* out all D3DPOOL_DEFAULT surfaces.
|
||||
*/
|
||||
for(unsigned int i = 0; i < mThebesLayers.Length(); i++) {
|
||||
mThebesLayers[i]->CleanResources();
|
||||
}
|
||||
|
||||
backBuffer = NULL;
|
||||
|
||||
D3DPRESENT_PARAMETERS pp;
|
||||
memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
|
||||
|
||||
pp.BackBufferFormat = D3DFMT_A8R8G8B8;
|
||||
pp.SwapEffect = D3DSWAPEFFECT_COPY;
|
||||
pp.Windowed = TRUE;
|
||||
pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
|
||||
pp.hDeviceWindow = (HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW);
|
||||
|
||||
hr = mDevice->Reset(&pp);
|
||||
if (FAILED(hr)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
SetupRenderState();
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D9::PaintToTarget()
|
||||
{
|
||||
nsRefPtr<IDirect3DSurface9> backBuff;
|
||||
nsRefPtr<IDirect3DSurface9> destSurf;
|
||||
mDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO,
|
||||
device()->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO,
|
||||
getter_AddRefs(backBuff));
|
||||
|
||||
D3DSURFACE_DESC desc;
|
||||
backBuff->GetDesc(&desc);
|
||||
|
||||
mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height,
|
||||
device()->CreateOffscreenPlainSurface(desc.Width, desc.Height,
|
||||
D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM,
|
||||
getter_AddRefs(destSurf), NULL);
|
||||
|
||||
mDevice->GetRenderTargetData(backBuff, destSurf);
|
||||
device()->GetRenderTargetData(backBuff, destSurf);
|
||||
|
||||
D3DLOCKED_RECT rect;
|
||||
destSurf->LockRect(&rect, NULL, D3DLOCK_READONLY);
|
||||
@ -483,81 +282,6 @@ LayerManagerD3D9::PaintToTarget()
|
||||
destSurf->UnlockRect();
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D9::SetupRenderState()
|
||||
{
|
||||
mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex));
|
||||
mDevice->SetVertexDeclaration(mVD);
|
||||
mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
|
||||
mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
|
||||
mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
|
||||
mDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
||||
mDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
||||
mDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
||||
mDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
||||
mDevice->SetSamplerState(2, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
||||
mDevice->SetSamplerState(2, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
||||
}
|
||||
|
||||
PRBool
|
||||
LayerManagerD3D9::VerifyCaps()
|
||||
{
|
||||
D3DCAPS9 caps;
|
||||
HRESULT hr = mDevice->GetDeviceCaps(&caps);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.DevCaps, D3DDEVCAPS_TEXTUREVIDEOMEMORY)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.PrimitiveMiscCaps, D3DPMISCCAPS_CULLNONE)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.SrcBlendCaps, D3DPBLENDCAPS_ONE) ||
|
||||
LACKS_CAP(caps.SrcBlendCaps, D3DBLEND_SRCALPHA) ||
|
||||
LACKS_CAP(caps.DestBlendCaps, D3DPBLENDCAPS_INVSRCALPHA)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.RasterCaps, D3DPRASTERCAPS_SCISSORTEST)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_ALPHA) ||
|
||||
HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_SQUAREONLY) ||
|
||||
(HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_POW2) &&
|
||||
LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_NONPOW2CONDITIONAL))) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MAGFLINEAR) ||
|
||||
LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MINFLINEAR)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (LACKS_CAP(caps.TextureAddressCaps, D3DPTADDRESSCAPS_CLAMP)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (caps.MaxTextureHeight < 4096 ||
|
||||
caps.MaxTextureWidth < 4096) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if ((caps.PixelShaderVersion & 0xffff) < 0x200 ||
|
||||
(caps.VertexShaderVersion & 0xffff) < 0x200) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
LayerD3D9::LayerD3D9(LayerManagerD3D9 *aManager)
|
||||
: mD3DManager(aManager)
|
||||
{
|
||||
|
@ -46,6 +46,8 @@
|
||||
#include "gfxContext.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
#include "DeviceManagerD3D9.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
@ -122,49 +124,27 @@ public:
|
||||
*/
|
||||
void SetClippingEnabled(PRBool aEnabled);
|
||||
|
||||
IDirect3DDevice9 *device() const { return mDevice; }
|
||||
void SetShaderMode(DeviceManagerD3D9::ShaderMode aMode)
|
||||
{ mDeviceManager->SetShaderMode(aMode); }
|
||||
|
||||
enum ShaderMode {
|
||||
RGBLAYER,
|
||||
YCBCRLAYER,
|
||||
SOLIDCOLORLAYER
|
||||
};
|
||||
|
||||
void SetShaderMode(ShaderMode aMode);
|
||||
|
||||
nsTArray<ThebesLayerD3D9*> mThebesLayers;
|
||||
IDirect3DDevice9 *device() const { return mDeviceManager->device(); }
|
||||
DeviceManagerD3D9 *deviceManager() const { return mDeviceManager; }
|
||||
|
||||
private:
|
||||
/* Direct3D9 instance */
|
||||
static IDirect3D9 *mD3D9;
|
||||
/* Device manager instance */
|
||||
static DeviceManagerD3D9 *mDeviceManager;
|
||||
|
||||
/* Swap chain associated with this layer manager */
|
||||
nsRefPtr<SwapChainD3D9> mSwapChain;
|
||||
|
||||
/* Widget associated with this layer manager */
|
||||
nsIWidget *mWidget;
|
||||
|
||||
/*
|
||||
* Context target, NULL when drawing directly to our swap chain.
|
||||
*/
|
||||
nsRefPtr<gfxContext> mTarget;
|
||||
|
||||
nsRefPtr<IDirect3DDevice9> mDevice;
|
||||
|
||||
/* Vertex shader used for layer quads */
|
||||
nsRefPtr<IDirect3DVertexShader9> mLayerVS;
|
||||
|
||||
/* Pixel shader used for RGB textures */
|
||||
nsRefPtr<IDirect3DPixelShader9> mRGBPS;
|
||||
|
||||
/* Pixel shader used for RGB textures */
|
||||
nsRefPtr<IDirect3DPixelShader9> mYCbCrPS;
|
||||
|
||||
/* Pixel shader used for solid colors */
|
||||
nsRefPtr<IDirect3DPixelShader9> mSolidColorPS;
|
||||
|
||||
/* Vertex buffer containing our basic vertex structure */
|
||||
nsRefPtr<IDirect3DVertexBuffer9> mVB;
|
||||
|
||||
/* Our vertex declaration */
|
||||
nsRefPtr<IDirect3DVertexDeclaration9> mVD;
|
||||
|
||||
/* Current root layer. */
|
||||
LayerD3D9 *mRootLayer;
|
||||
|
||||
@ -175,32 +155,21 @@ private:
|
||||
* Region we're clipping our current drawing to.
|
||||
*/
|
||||
nsIntRegion mClippingRegion;
|
||||
|
||||
/*
|
||||
* Render the current layer tree to the active target.
|
||||
*/
|
||||
void Render();
|
||||
|
||||
/*
|
||||
* Setup the pipeline.
|
||||
*/
|
||||
void SetupPipeline();
|
||||
/*
|
||||
* Setup the backbuffer.
|
||||
*
|
||||
* \return PR_TRUE if setup was succesful
|
||||
*/
|
||||
PRBool SetupBackBuffer();
|
||||
/*
|
||||
* Setup the render state for the surface.
|
||||
*/
|
||||
void SetupRenderState();
|
||||
|
||||
/*
|
||||
* Copies the content of our backbuffer to the set transaction target.
|
||||
*/
|
||||
void PaintToTarget();
|
||||
/*
|
||||
* Verifies all required device capabilities are present.
|
||||
*/
|
||||
PRBool VerifyCaps();
|
||||
|
||||
};
|
||||
|
||||
|
@ -39,6 +39,9 @@
|
||||
#include "gfxPlatform.h"
|
||||
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#ifdef CAIRO_HAS_D2D_SURFACE
|
||||
#include "gfxD2DSurface.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
@ -69,12 +72,12 @@ ThebesLayerD3D9::ThebesLayerD3D9(LayerManagerD3D9 *aManager)
|
||||
, LayerD3D9(aManager)
|
||||
{
|
||||
mImplData = static_cast<LayerD3D9*>(this);
|
||||
aManager->mThebesLayers.AppendElement(this);
|
||||
aManager->deviceManager()->mThebesLayers.AppendElement(this);
|
||||
}
|
||||
|
||||
ThebesLayerD3D9::~ThebesLayerD3D9()
|
||||
{
|
||||
mD3DManager->mThebesLayers.RemoveElement(this);
|
||||
mD3DManager->deviceManager()->mThebesLayers.RemoveElement(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -101,7 +104,8 @@ ThebesLayerD3D9::SetVisibleRegion(const nsIntRegion &aRegion)
|
||||
return;
|
||||
}
|
||||
|
||||
D3DFORMAT fmt = UseOpaqueSurface(this) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8;
|
||||
D3DFORMAT fmt = (UseOpaqueSurface(this) && !mD2DSurface) ?
|
||||
D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8;
|
||||
|
||||
D3DSURFACE_DESC desc;
|
||||
mTexture->GetLevelDesc(0, &desc);
|
||||
@ -116,10 +120,8 @@ ThebesLayerD3D9::SetVisibleRegion(const nsIntRegion &aRegion)
|
||||
|
||||
nsIntRect oldBounds = oldVisibleRegion.GetBounds();
|
||||
nsIntRect newBounds = mVisibleRegion.GetBounds();
|
||||
|
||||
device()->CreateTexture(newBounds.width, newBounds.height, 1,
|
||||
D3DUSAGE_RENDERTARGET, fmt,
|
||||
D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL);
|
||||
|
||||
CreateNewTexture(gfxIntSize(newBounds.width, newBounds.height));
|
||||
|
||||
// Old visible region will become the region that is covered by both the
|
||||
// old and the new visible region.
|
||||
@ -191,13 +193,14 @@ ThebesLayerD3D9::RenderLayer()
|
||||
if (mVisibleRegion.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
HRESULT hr;
|
||||
|
||||
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
||||
|
||||
// We differentiate between these formats since D3D9 will only allow us to
|
||||
// call GetDC on an opaque surface.
|
||||
D3DFORMAT fmt = UseOpaqueSurface(this) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8;
|
||||
D3DFORMAT fmt = (UseOpaqueSurface(this) && !mD2DSurface) ?
|
||||
D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8;
|
||||
|
||||
if (mTexture) {
|
||||
D3DSURFACE_DESC desc;
|
||||
mTexture->GetLevelDesc(0, &desc);
|
||||
@ -211,103 +214,16 @@ ThebesLayerD3D9::RenderLayer()
|
||||
}
|
||||
|
||||
if (!mTexture) {
|
||||
device()->CreateTexture(visibleRect.width, visibleRect.height, 1,
|
||||
D3DUSAGE_RENDERTARGET, fmt,
|
||||
D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL);
|
||||
CreateNewTexture(gfxIntSize(visibleRect.width, visibleRect.height));
|
||||
mValidRegion.SetEmpty();
|
||||
}
|
||||
|
||||
if (!mValidRegion.IsEqual(mVisibleRegion)) {
|
||||
nsIntRegion region;
|
||||
region.Sub(mVisibleRegion, mValidRegion);
|
||||
nsIntRect bounds = region.GetBounds();
|
||||
|
||||
gfxASurface::gfxImageFormat imageFormat = gfxASurface::ImageFormatARGB32;
|
||||
nsRefPtr<gfxASurface> destinationSurface;
|
||||
nsRefPtr<gfxContext> context;
|
||||
DrawRegion(region);
|
||||
|
||||
nsRefPtr<IDirect3DTexture9> tmpTexture;
|
||||
device()->CreateTexture(bounds.width, bounds.height, 1,
|
||||
0, fmt,
|
||||
D3DPOOL_SYSTEMMEM, getter_AddRefs(tmpTexture), NULL);
|
||||
|
||||
nsRefPtr<IDirect3DSurface9> surf;
|
||||
HDC dc;
|
||||
if (UseOpaqueSurface(this)) {
|
||||
hr = tmpTexture->GetSurfaceLevel(0, getter_AddRefs(surf));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
// Uh-oh, bail.
|
||||
NS_WARNING("Failed to get texture surface level.");
|
||||
return;
|
||||
}
|
||||
|
||||
hr = surf->GetDC(&dc);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to get device context for texture surface.");
|
||||
return;
|
||||
}
|
||||
|
||||
destinationSurface = new gfxWindowsSurface(dc);
|
||||
} else {
|
||||
// XXX - We may consider retaining a SYSTEMMEM texture texture the size
|
||||
// of our DEFAULT texture and then use UpdateTexture and add dirty rects
|
||||
// to update in a single call.
|
||||
destinationSurface =
|
||||
gfxPlatform::GetPlatform()->
|
||||
CreateOffscreenSurface(gfxIntSize(bounds.width,
|
||||
bounds.height),
|
||||
imageFormat);
|
||||
}
|
||||
|
||||
context = new gfxContext(destinationSurface);
|
||||
context->Translate(gfxPoint(-bounds.x, -bounds.y));
|
||||
LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
|
||||
cbInfo.Callback(this, context, region, nsIntRegion(), cbInfo.CallbackData);
|
||||
|
||||
if (UseOpaqueSurface(this)) {
|
||||
surf->ReleaseDC(dc);
|
||||
} else {
|
||||
D3DLOCKED_RECT r;
|
||||
tmpTexture->LockRect(0, &r, NULL, 0);
|
||||
|
||||
nsRefPtr<gfxImageSurface> imgSurface =
|
||||
new gfxImageSurface((unsigned char *)r.pBits,
|
||||
gfxIntSize(bounds.width,
|
||||
bounds.height),
|
||||
r.Pitch,
|
||||
imageFormat);
|
||||
|
||||
context = new gfxContext(imgSurface);
|
||||
context->SetSource(destinationSurface);
|
||||
context->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
context->Paint();
|
||||
|
||||
imgSurface = NULL;
|
||||
|
||||
tmpTexture->UnlockRect(0);
|
||||
}
|
||||
|
||||
nsRefPtr<IDirect3DSurface9> srcSurface;
|
||||
nsRefPtr<IDirect3DSurface9> dstSurface;
|
||||
|
||||
mTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
|
||||
tmpTexture->GetSurfaceLevel(0, getter_AddRefs(srcSurface));
|
||||
|
||||
nsIntRegionRectIterator iter(region);
|
||||
const nsIntRect *iterRect;
|
||||
while ((iterRect = iter.Next())) {
|
||||
RECT rect;
|
||||
rect.left = iterRect->x - bounds.x;
|
||||
rect.top = iterRect->y - bounds.y;
|
||||
rect.right = rect.left + iterRect->width;
|
||||
rect.bottom = rect.top + iterRect->height;
|
||||
POINT point;
|
||||
point.x = iterRect->x - visibleRect.x;
|
||||
point.y = iterRect->y - visibleRect.y;
|
||||
device()->UpdateSurface(srcSurface, &rect, dstSurface, &point);
|
||||
}
|
||||
mValidRegion = mVisibleRegion;
|
||||
}
|
||||
|
||||
@ -338,7 +254,7 @@ ThebesLayerD3D9::RenderLayer()
|
||||
opacity[0] = GetOpacity();
|
||||
device()->SetPixelShaderConstantF(0, opacity, 1);
|
||||
|
||||
mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER);
|
||||
mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER);
|
||||
|
||||
device()->SetTexture(0, mTexture);
|
||||
device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
|
||||
@ -362,5 +278,168 @@ ThebesLayerD3D9::IsEmpty()
|
||||
return !mTexture;
|
||||
}
|
||||
|
||||
void
|
||||
ThebesLayerD3D9::DrawRegion(const nsIntRegion &aRegion)
|
||||
{
|
||||
HRESULT hr;
|
||||
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
||||
nsRefPtr<gfxContext> context;
|
||||
|
||||
#ifdef CAIRO_HAS_D2D_SURFACE
|
||||
if (mD2DSurface) {
|
||||
context = new gfxContext(mD2DSurface);
|
||||
nsIntRegionRectIterator iter(aRegion);
|
||||
context->Translate(gfxPoint(-visibleRect.x, -visibleRect.y));
|
||||
context->NewPath();
|
||||
const nsIntRect *iterRect;
|
||||
while ((iterRect = iter.Next())) {
|
||||
context->Rectangle(gfxRect(iterRect->x, iterRect->y, iterRect->width, iterRect->height));
|
||||
}
|
||||
context->Clip();
|
||||
if (mD2DSurface->GetContentType() != gfxASurface::CONTENT_COLOR) {
|
||||
context->SetOperator(gfxContext::OPERATOR_CLEAR);
|
||||
context->Paint();
|
||||
context->SetOperator(gfxContext::OPERATOR_OVER);
|
||||
}
|
||||
LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
|
||||
cbInfo.Callback(this, context, aRegion, nsIntRegion(), cbInfo.CallbackData);
|
||||
mD2DSurface->Flush();
|
||||
|
||||
// XXX - This call is quite expensive, we may want to consider doing our
|
||||
// drawing in a seperate 'validation' iteration. And then flushing once for
|
||||
// all the D2D surfaces we might have drawn, before doing our D3D9 rendering
|
||||
// loop.
|
||||
cairo_d2d_finish_device(gfxWindowsPlatform::GetPlatform()->GetD2DDevice());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
D3DFORMAT fmt = UseOpaqueSurface(this) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8;
|
||||
nsIntRect bounds = aRegion.GetBounds();
|
||||
|
||||
gfxASurface::gfxImageFormat imageFormat = gfxASurface::ImageFormatARGB32;
|
||||
nsRefPtr<gfxASurface> destinationSurface;
|
||||
|
||||
nsRefPtr<IDirect3DTexture9> tmpTexture;
|
||||
device()->CreateTexture(bounds.width, bounds.height, 1,
|
||||
0, fmt,
|
||||
D3DPOOL_SYSTEMMEM, getter_AddRefs(tmpTexture), NULL);
|
||||
|
||||
nsRefPtr<IDirect3DSurface9> surf;
|
||||
HDC dc;
|
||||
if (UseOpaqueSurface(this)) {
|
||||
hr = tmpTexture->GetSurfaceLevel(0, getter_AddRefs(surf));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
// Uh-oh, bail.
|
||||
NS_WARNING("Failed to get texture surface level.");
|
||||
return;
|
||||
}
|
||||
|
||||
hr = surf->GetDC(&dc);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to get device context for texture surface.");
|
||||
return;
|
||||
}
|
||||
|
||||
destinationSurface = new gfxWindowsSurface(dc);
|
||||
} else {
|
||||
// XXX - We may consider retaining a SYSTEMMEM texture texture the size
|
||||
// of our DEFAULT texture and then use UpdateTexture and add dirty rects
|
||||
// to update in a single call.
|
||||
destinationSurface =
|
||||
gfxPlatform::GetPlatform()->
|
||||
CreateOffscreenSurface(gfxIntSize(bounds.width,
|
||||
bounds.height),
|
||||
imageFormat);
|
||||
}
|
||||
|
||||
context = new gfxContext(destinationSurface);
|
||||
context->Translate(gfxPoint(-bounds.x, -bounds.y));
|
||||
LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
|
||||
cbInfo.Callback(this, context, aRegion, nsIntRegion(), cbInfo.CallbackData);
|
||||
|
||||
if (UseOpaqueSurface(this)) {
|
||||
surf->ReleaseDC(dc);
|
||||
} else {
|
||||
D3DLOCKED_RECT r;
|
||||
tmpTexture->LockRect(0, &r, NULL, 0);
|
||||
|
||||
nsRefPtr<gfxImageSurface> imgSurface =
|
||||
new gfxImageSurface((unsigned char *)r.pBits,
|
||||
gfxIntSize(bounds.width,
|
||||
bounds.height),
|
||||
r.Pitch,
|
||||
imageFormat);
|
||||
|
||||
context = new gfxContext(imgSurface);
|
||||
context->SetSource(destinationSurface);
|
||||
context->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
context->Paint();
|
||||
|
||||
imgSurface = NULL;
|
||||
|
||||
tmpTexture->UnlockRect(0);
|
||||
}
|
||||
|
||||
nsRefPtr<IDirect3DSurface9> srcSurface;
|
||||
nsRefPtr<IDirect3DSurface9> dstSurface;
|
||||
|
||||
mTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
|
||||
tmpTexture->GetSurfaceLevel(0, getter_AddRefs(srcSurface));
|
||||
|
||||
nsIntRegionRectIterator iter(aRegion);
|
||||
const nsIntRect *iterRect;
|
||||
while ((iterRect = iter.Next())) {
|
||||
RECT rect;
|
||||
rect.left = iterRect->x - bounds.x;
|
||||
rect.top = iterRect->y - bounds.y;
|
||||
rect.right = rect.left + iterRect->width;
|
||||
rect.bottom = rect.top + iterRect->height;
|
||||
POINT point;
|
||||
point.x = iterRect->x - visibleRect.x;
|
||||
point.y = iterRect->y - visibleRect.y;
|
||||
device()->UpdateSurface(srcSurface, &rect, dstSurface, &point);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ThebesLayerD3D9::CreateNewTexture(const gfxIntSize &aSize)
|
||||
{
|
||||
if (aSize.width == 0 | aSize.height == 0) {
|
||||
// Nothing to do.
|
||||
return;
|
||||
}
|
||||
|
||||
mTexture = nsnull;
|
||||
#ifdef CAIRO_HAS_D2D_SURFACE
|
||||
if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
|
||||
gfxWindowsPlatform::RENDER_DIRECT2D) {
|
||||
if (mD3DManager->deviceManager()->IsD3D9Ex()) {
|
||||
// We should have D3D9Ex where we have D2D.
|
||||
HANDLE sharedHandle = 0;
|
||||
device()->CreateTexture(aSize.width, aSize.height, 1,
|
||||
D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
|
||||
D3DPOOL_DEFAULT, getter_AddRefs(mTexture), &sharedHandle);
|
||||
|
||||
mD2DSurface = new gfxD2DSurface(sharedHandle, UseOpaqueSurface(this) ?
|
||||
gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA);
|
||||
|
||||
// If there's an error, go on and do what we always do.
|
||||
if (mD2DSurface->CairoStatus()) {
|
||||
mD2DSurface = nsnull;
|
||||
mTexture = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!mTexture) {
|
||||
device()->CreateTexture(aSize.width, aSize.height, 1,
|
||||
D3DUSAGE_RENDERTARGET, UseOpaqueSurface(this) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8,
|
||||
D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL);
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace layers */
|
||||
} /* namespace mozilla */
|
||||
|
@ -42,7 +42,6 @@
|
||||
#include "LayerManagerD3D9.h"
|
||||
#include "gfxImageSurface.h"
|
||||
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
@ -70,6 +69,15 @@ private:
|
||||
* D3D9 texture
|
||||
*/
|
||||
nsRefPtr<IDirect3DTexture9> mTexture;
|
||||
|
||||
/* This contains the D2D surface if we have one */
|
||||
nsRefPtr<gfxASurface> mD2DSurface;
|
||||
|
||||
/* Have a region of our layer drawn */
|
||||
void DrawRegion(const nsIntRegion &aRegion);
|
||||
|
||||
/* Create a new texture */
|
||||
void CreateNewTexture(const gfxIntSize &aSize);
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
|
@ -36,10 +36,22 @@
|
||||
#include "gfxD2DSurface.h"
|
||||
#include "cairo.h"
|
||||
#include "cairo-win32.h"
|
||||
#include "gfxWindowsPlatform.h"
|
||||
|
||||
gfxD2DSurface::gfxD2DSurface(HWND aWnd, gfxContentType aContent)
|
||||
{
|
||||
Init(cairo_d2d_surface_create_for_hwnd(aWnd, (cairo_content_t)aContent));
|
||||
Init(cairo_d2d_surface_create_for_hwnd(
|
||||
gfxWindowsPlatform::GetPlatform()->GetD2DDevice(),
|
||||
aWnd,
|
||||
(cairo_content_t)aContent));
|
||||
}
|
||||
|
||||
gfxD2DSurface::gfxD2DSurface(HANDLE handle, gfxContentType aContent)
|
||||
{
|
||||
Init(cairo_d2d_surface_create_for_handle(
|
||||
gfxWindowsPlatform::GetPlatform()->GetD2DDevice(),
|
||||
handle,
|
||||
(cairo_content_t)aContent));
|
||||
}
|
||||
|
||||
gfxD2DSurface::gfxD2DSurface(cairo_surface_t *csurf)
|
||||
@ -50,7 +62,10 @@ gfxD2DSurface::gfxD2DSurface(cairo_surface_t *csurf)
|
||||
gfxD2DSurface::gfxD2DSurface(const gfxIntSize& size,
|
||||
gfxImageFormat imageFormat)
|
||||
{
|
||||
Init(cairo_d2d_surface_create((cairo_format_t)imageFormat, size.width, size.height));
|
||||
Init(cairo_d2d_surface_create(
|
||||
gfxWindowsPlatform::GetPlatform()->GetD2DDevice(),
|
||||
(cairo_format_t)imageFormat,
|
||||
size.width, size.height));
|
||||
}
|
||||
|
||||
gfxD2DSurface::~gfxD2DSurface()
|
||||
|
@ -51,6 +51,7 @@ public:
|
||||
gfxD2DSurface(const gfxIntSize& size,
|
||||
gfxImageFormat imageFormat = ImageFormatRGB24);
|
||||
|
||||
gfxD2DSurface(HANDLE handle, gfxContentType aContent);
|
||||
|
||||
gfxD2DSurface(cairo_surface_t *csurf);
|
||||
|
||||
|
@ -2235,17 +2235,19 @@ gfxFontGroup::InitTextRun(gfxContext *aContext,
|
||||
PRUint32 matchedLength = range.Length();
|
||||
gfxFont *matchedFont = (range.font ? range.font.get() : nsnull);
|
||||
|
||||
// create the glyph run for this range
|
||||
aTextRun->AddGlyphRun(matchedFont ? matchedFont : mainFont,
|
||||
runStart, (matchedLength > 0));
|
||||
if (matchedFont) {
|
||||
// create the glyph run for this range
|
||||
aTextRun->AddGlyphRun(matchedFont, runStart, (matchedLength > 0));
|
||||
|
||||
// do glyph layout and record the resulting positioned glyphs
|
||||
matchedFont->InitTextRun(aContext, aTextRun, aString,
|
||||
runStart, matchedLength, aRunScript);
|
||||
} else {
|
||||
// create the glyph run before calling SetMissing Glyph
|
||||
aTextRun->AddGlyphRun(mainFont, runStart, matchedLength);
|
||||
|
||||
if (!matchedFont->InitTextRun(aContext, aTextRun, aString,
|
||||
runStart, matchedLength,
|
||||
aRunScript)) {
|
||||
// glyph layout failed! treat as missing glyphs
|
||||
matchedFont = nsnull;
|
||||
}
|
||||
}
|
||||
if (!matchedFont) {
|
||||
for (PRUint32 index = runStart; index < runStart + matchedLength; index++) {
|
||||
// Record the char code so we can draw a box with the Unicode value
|
||||
if (NS_IS_HIGH_SURROGATE(aString[index]) &&
|
||||
@ -3627,6 +3629,8 @@ PRUint32
|
||||
gfxTextRun::FindFirstGlyphRunContaining(PRUint32 aOffset)
|
||||
{
|
||||
NS_ASSERTION(aOffset <= mCharacterCount, "Bad offset looking for glyphrun");
|
||||
NS_ASSERTION(mCharacterCount == 0 || mGlyphRuns.Length() > 0,
|
||||
"non-empty text but no glyph runs present!");
|
||||
if (aOffset == mCharacterCount)
|
||||
return mGlyphRuns.Length();
|
||||
PRUint32 start = 0;
|
||||
|
@ -394,48 +394,15 @@ private:
|
||||
PRPackedBool mFontSelected;
|
||||
};
|
||||
|
||||
#define MAX_ITEM_LENGTH 32768
|
||||
|
||||
static PRUint32 FindNextItemStart(int aOffset, int aLimit,
|
||||
nsTArray<SCRIPT_LOGATTR> &aLogAttr,
|
||||
const PRUnichar *aString)
|
||||
{
|
||||
if (aOffset + MAX_ITEM_LENGTH >= aLimit) {
|
||||
// The item starting at aOffset can't be longer than the max length,
|
||||
// so starting the next item at aLimit won't cause ScriptShape() to fail.
|
||||
return aLimit;
|
||||
}
|
||||
|
||||
// Try to start the next item before or after a space, since spaces
|
||||
// don't kern or ligate.
|
||||
PRUint32 off;
|
||||
int boundary = -1;
|
||||
for (off = MAX_ITEM_LENGTH; off > 1; --off) {
|
||||
if (aLogAttr[off].fCharStop) {
|
||||
if (off > boundary) {
|
||||
boundary = off;
|
||||
}
|
||||
if (aString[aOffset+off] == ' ' || aString[aOffset+off - 1] == ' ')
|
||||
return aOffset+off;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to start the next item at the last cluster boundary in the range.
|
||||
if (boundary > 0) {
|
||||
return aOffset+boundary;
|
||||
}
|
||||
|
||||
// No nice cluster boundaries inside MAX_ITEM_LENGTH characters, break
|
||||
// on the size limit. It won't be visually plesaing, but at least it
|
||||
// won't cause ScriptShape() to fail.
|
||||
return aOffset + MAX_ITEM_LENGTH;
|
||||
}
|
||||
#define MAX_ITEM_LENGTH 16384
|
||||
|
||||
class Uniscribe
|
||||
{
|
||||
public:
|
||||
Uniscribe(const PRUnichar *aString, PRUint32 aLength, PRBool aIsRTL) :
|
||||
mString(aString), mLength(aLength), mIsRTL(aIsRTL)
|
||||
Uniscribe(const PRUnichar *aString,
|
||||
PRUint32 aLength,
|
||||
gfxTextRun *aTextRun):
|
||||
mString(aString), mLength(aLength), mTextRun(aTextRun)
|
||||
{
|
||||
}
|
||||
~Uniscribe() {
|
||||
@ -446,44 +413,79 @@ public:
|
||||
memset(&mState, 0, sizeof(SCRIPT_STATE));
|
||||
// Lock the direction. Don't allow the itemizer to change directions
|
||||
// based on character type.
|
||||
mState.uBidiLevel = mIsRTL;
|
||||
mState.uBidiLevel = mTextRun->IsRightToLeft() ? 1 : 0;
|
||||
mState.fOverrideDirection = PR_TRUE;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// We try to avoid calling Uniscribe with text runs that may generate
|
||||
// more than this many glyphs, because of the possibility of arithmetic
|
||||
// overflow of 16-bit variables. If long runs need to be split because
|
||||
// of this, we'll look for whitespace to break on so that shaping needed
|
||||
// (e.g. for complex scripts) should be unaffected.
|
||||
#define MAX_UNISCRIBE_GLYPHS 32767
|
||||
|
||||
// Append mItems[aIndex] to aDest, adding extra items to aDest to ensure
|
||||
// that no item is too long for ScriptShape() to handle. See bug 366643.
|
||||
nsresult CopyItemSplitOversize(int aIndex, nsTArray<SCRIPT_ITEM> &aDest) {
|
||||
aDest.AppendElement(mItems[aIndex]);
|
||||
const int itemLength = mItems[aIndex+1].iCharPos - mItems[aIndex].iCharPos;
|
||||
if (ESTIMATE_MAX_GLYPHS(itemLength) > 65535) {
|
||||
// This items length would cause ScriptShape() to fail. We need to
|
||||
// add extra items here so that no item's length could cause the fail.
|
||||
|
||||
// Get cluster boundaries, so we can break cleanly if possible.
|
||||
nsTArray<SCRIPT_LOGATTR> logAttr;
|
||||
if (!logAttr.SetLength(itemLength))
|
||||
return NS_ERROR_FAILURE;
|
||||
HRESULT rv = ScriptBreak(mString+mItems[aIndex].iCharPos, itemLength,
|
||||
&mItems[aIndex].a, logAttr.Elements());
|
||||
if (FAILED(rv))
|
||||
return NS_ERROR_FAILURE;
|
||||
const int itemLength =
|
||||
mItems[aIndex+1].iCharPos - mItems[aIndex].iCharPos;
|
||||
if (ESTIMATE_MAX_GLYPHS(itemLength) > MAX_UNISCRIBE_GLYPHS) {
|
||||
// This item's length would cause ScriptShape() to fail.
|
||||
// We need to add extra items here so that no item's length
|
||||
// could cause the fail.
|
||||
|
||||
// We break on whitespace or cluster boundaries if possible.
|
||||
const int nextItemStart = mItems[aIndex+1].iCharPos;
|
||||
int start = FindNextItemStart(mItems[aIndex].iCharPos,
|
||||
nextItemStart, logAttr, mString);
|
||||
nextItemStart);
|
||||
|
||||
while (start < nextItemStart) {
|
||||
SCRIPT_ITEM item = mItems[aIndex];
|
||||
item.iCharPos = start;
|
||||
aDest.AppendElement(item);
|
||||
start = FindNextItemStart(start, nextItemStart, logAttr, mString);
|
||||
start = FindNextItemStart(start, nextItemStart);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRUint32 FindNextItemStart(int aOffset, int aLimit) {
|
||||
if (aOffset + MAX_ITEM_LENGTH >= aLimit) {
|
||||
// The item starting at aOffset can't be longer than max length,
|
||||
// so starting the next item at aLimit won't cause ScriptShape()
|
||||
// to fail.
|
||||
return aLimit;
|
||||
}
|
||||
// Try to start the next item before or after a space, since spaces
|
||||
// don't kern or ligate.
|
||||
PRInt32 off;
|
||||
int boundary = -1;
|
||||
for (off = MAX_ITEM_LENGTH; off > 1; --off) {
|
||||
if (mTextRun->IsClusterStart(off)) {
|
||||
if (off > boundary) {
|
||||
boundary = off;
|
||||
}
|
||||
if (mString[aOffset+off] == ' ' ||
|
||||
mString[aOffset+off - 1] == ' ') {
|
||||
return aOffset+off;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try to start the next item at last cluster boundary in the range.
|
||||
if (boundary > 0) {
|
||||
return aOffset+boundary;
|
||||
}
|
||||
|
||||
// No nice cluster boundaries inside MAX_ITEM_LENGTH characters, break
|
||||
// on the size limit. It won't be visually pleasing, but at least it
|
||||
// won't cause ScriptShape() to fail.
|
||||
return aOffset + MAX_ITEM_LENGTH;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
int Itemize() {
|
||||
@ -537,7 +539,7 @@ public:
|
||||
private:
|
||||
const PRUnichar *mString;
|
||||
const PRUint32 mLength;
|
||||
const PRBool mIsRTL;
|
||||
gfxTextRun *mTextRun;
|
||||
|
||||
SCRIPT_CONTROL mControl;
|
||||
SCRIPT_STATE mState;
|
||||
@ -556,15 +558,13 @@ gfxUniscribeShaper::InitTextRun(gfxContext *aContext,
|
||||
{
|
||||
DCFromContext aDC(aContext);
|
||||
|
||||
const PRBool isRTL = aTextRun->IsRightToLeft();
|
||||
|
||||
PRBool result = PR_TRUE;
|
||||
HRESULT rv;
|
||||
|
||||
gfxGDIFont *font = static_cast<gfxGDIFont*>(mFont);
|
||||
AutoSelectFont fs(aDC, font->GetHFONT());
|
||||
|
||||
Uniscribe us(aString + aRunStart, aRunLength, isRTL);
|
||||
Uniscribe us(aString + aRunStart, aRunLength, aTextRun);
|
||||
|
||||
/* itemize the string */
|
||||
int numItems = us.Itemize();
|
||||
@ -633,10 +633,9 @@ gfxUniscribeShaper::InitTextRun(gfxContext *aContext,
|
||||
}
|
||||
|
||||
if (FAILED(rv)) {
|
||||
aTextRun->ResetGlyphRuns();
|
||||
// Uniscribe doesn't like this font for some reason.
|
||||
// Returning FALSE will make the gfxGDIFont discard this
|
||||
// shaper and replace it with a "dumb" GDI one.
|
||||
// Returning FALSE will make the gfxGDIFont retry with the
|
||||
// "dumb" GDI one, unless useUniscribeOnly was set.
|
||||
result = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
|
@ -170,6 +170,7 @@ gfxWindowsPlatform::gfxWindowsPlatform()
|
||||
|
||||
#ifdef CAIRO_HAS_D2D_SURFACE
|
||||
NS_RegisterMemoryReporter(new D2DCacheReporter());
|
||||
mD2DDevice = NULL;
|
||||
#endif
|
||||
#ifdef CAIRO_HAS_DWRITE_FONT
|
||||
nsresult rv;
|
||||
@ -213,7 +214,8 @@ gfxWindowsPlatform::gfxWindowsPlatform()
|
||||
#ifndef CAIRO_HAS_D2D_SURFACE
|
||||
return;
|
||||
#else
|
||||
if (!cairo_d2d_has_support()) {
|
||||
mD2DDevice = cairo_d2d_create_device();
|
||||
if (!mD2DDevice) {
|
||||
return;
|
||||
}
|
||||
#ifdef CAIRO_HAS_DWRITE_FONT
|
||||
@ -235,6 +237,11 @@ gfxWindowsPlatform::~gfxWindowsPlatform()
|
||||
{
|
||||
// not calling FT_Done_FreeType because cairo may still hold references to
|
||||
// these FT_Faces. See bug 458169.
|
||||
#ifdef CAIRO_HAS_D2D_SURFACE
|
||||
if (mD2DDevice) {
|
||||
cairo_release_device(mD2DDevice);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
gfxPlatformFontList*
|
||||
|
@ -214,6 +214,9 @@ public:
|
||||
#ifdef CAIRO_HAS_DWRITE_FONT
|
||||
IDWriteFactory *GetDWriteFactory() { return mDWriteFactory; }
|
||||
#endif
|
||||
#ifdef CAIRO_HAS_D2D_SURFACE
|
||||
cairo_device_t *GetD2DDevice() { return mD2DDevice; }
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_FT2_FONTS
|
||||
FT_Library GetFTLibrary();
|
||||
@ -233,6 +236,9 @@ private:
|
||||
#ifdef CAIRO_HAS_DWRITE_FONT
|
||||
nsRefPtr<IDWriteFactory> mDWriteFactory;
|
||||
#endif
|
||||
#ifdef CAIRO_HAS_D2D_SURFACE
|
||||
cairo_device_t *mD2DDevice;
|
||||
#endif
|
||||
|
||||
virtual qcms_profile* GetPlatformCMSOutputProfile();
|
||||
|
||||
|
@ -60,6 +60,9 @@
|
||||
# include <locale.h>
|
||||
# include <stdlib.h>
|
||||
# include "nsIPosixLocale.h"
|
||||
#if (MOZ_PLATFORM_MAEMO >= 6)
|
||||
# include "nsIGConfService.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//
|
||||
@ -174,24 +177,43 @@ nsLocaleService::nsLocaleService(void)
|
||||
if ( resultLocale == NULL ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get system configuration
|
||||
const char* lang = getenv("LANG");
|
||||
#if (MOZ_PLATFORM_MAEMO >= 6)
|
||||
nsCAutoString gconfLocaleString;
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIGConfService> gconf =
|
||||
do_GetService(NS_GCONFSERVICE_CONTRACTID, &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = gconf->GetString(NS_LITERAL_CSTRING("/meegotouch/i18n/language"),
|
||||
gconfLocaleString);
|
||||
if (NS_SUCCEEDED(rv) && !gconfLocaleString.IsEmpty()) {
|
||||
lang = gconfLocaleString.get();
|
||||
// For setlocale() doing the right thing we need to export
|
||||
// this as LANG to the environment
|
||||
setenv("LANG", lang, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for( i = 0; i < LocaleListLength; i++ ) {
|
||||
nsresult result;
|
||||
// setlocale( , "") evaluates LC_* and LANG
|
||||
char* lc_temp = setlocale(posix_locale_category[i], "");
|
||||
CopyASCIItoUTF16(LocaleList[i], category);
|
||||
category_platform = category;
|
||||
category_platform = category;
|
||||
category_platform.AppendLiteral("##PLATFORM");
|
||||
if (lc_temp != nsnull) {
|
||||
result = posixConverter->GetXPLocale(lc_temp, xpLocale);
|
||||
CopyASCIItoUTF16(lc_temp, platformLocale);
|
||||
} else {
|
||||
char* lang = getenv("LANG");
|
||||
if ( lang == nsnull ) {
|
||||
platformLocale.AssignLiteral("en_US");
|
||||
result = posixConverter->GetXPLocale("en-US", xpLocale);
|
||||
}
|
||||
else {
|
||||
CopyASCIItoUTF16(lang, platformLocale);
|
||||
result = posixConverter->GetXPLocale(lang, xpLocale);
|
||||
result = posixConverter->GetXPLocale(lang, xpLocale);
|
||||
}
|
||||
}
|
||||
if (NS_FAILED(result)) {
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "base/singleton.h"
|
||||
#include "base/waitable_event.h"
|
||||
#ifdef CHROMIUM_MOZILLA_BUILD
|
||||
#include "mozilla/ipc/ProcessChild.h"
|
||||
#include "mozilla/ipc/BrowserProcessSubThread.h"
|
||||
typedef mozilla::ipc::BrowserProcessSubThread ChromeThread;
|
||||
#else
|
||||
@ -121,6 +122,8 @@ bool ChildProcessHost::Send(IPC::Message* msg) {
|
||||
void ChildProcessHost::Notify(NotificationType type) {
|
||||
#ifdef CHROMIUM_MOZILLA_BUILD
|
||||
MessageLoop* loop = ChromeThread::GetMessageLoop(ChromeThread::IO);
|
||||
if (!loop)
|
||||
loop = mozilla::ipc::ProcessChild::message_loop();
|
||||
if (!loop)
|
||||
loop = MessageLoop::current();
|
||||
loop->PostTask(
|
||||
|
@ -253,14 +253,6 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector<std::string> aExtraOpts)
|
||||
newEnvVars["LD_LIBRARY_PATH"] = path.get();
|
||||
#elif OS_MACOSX
|
||||
newEnvVars["DYLD_LIBRARY_PATH"] = path.get();
|
||||
#endif
|
||||
#ifdef MOZ_OMNIJAR
|
||||
// Make sure the child process can find the omnijar
|
||||
// See ScopedXPCOMStartup::Initialize in nsAppRunner.cpp
|
||||
nsCAutoString omnijarPath;
|
||||
if (mozilla::OmnijarPath())
|
||||
mozilla::OmnijarPath()->GetNativePath(omnijarPath);
|
||||
newEnvVars["OMNIJAR_PATH"] = omnijarPath.get();
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
@ -296,6 +288,17 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector<std::string> aExtraOpts)
|
||||
|
||||
childArgv.insert(childArgv.end(), aExtraOpts.begin(), aExtraOpts.end());
|
||||
|
||||
#ifdef MOZ_OMNIJAR
|
||||
// Make sure the child process can find the omnijar
|
||||
// See XRE_InitCommandLine in nsAppRunner.cpp
|
||||
nsCAutoString omnijarPath;
|
||||
if (mozilla::OmnijarPath()) {
|
||||
mozilla::OmnijarPath()->GetNativePath(omnijarPath);
|
||||
childArgv.push_back("-omnijar");
|
||||
childArgv.push_back(omnijarPath.get());
|
||||
}
|
||||
#endif
|
||||
|
||||
childArgv.push_back(pidstring);
|
||||
childArgv.push_back(childProcessType);
|
||||
|
||||
@ -346,6 +349,18 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector<std::string> aExtraOpts)
|
||||
}
|
||||
|
||||
cmdLine.AppendLooseValue(std::wstring(mGroupId.get()));
|
||||
|
||||
#ifdef MOZ_OMNIJAR
|
||||
// Make sure the child process can find the omnijar
|
||||
// See XRE_InitCommandLine in nsAppRunner.cpp
|
||||
nsAutoString omnijarPath;
|
||||
if (mozilla::OmnijarPath()) {
|
||||
mozilla::OmnijarPath()->GetPath(omnijarPath);
|
||||
cmdLine.AppendLooseValue(UTF8ToWide("-omnijar"));
|
||||
cmdLine.AppendLooseValue(omnijarPath.get());
|
||||
}
|
||||
#endif
|
||||
|
||||
cmdLine.AppendLooseValue(UTF8ToWide(pidstring));
|
||||
cmdLine.AppendLooseValue(UTF8ToWide(childProcessType));
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
|
@ -1215,6 +1215,9 @@ bool
|
||||
XPCShellEnvironment::EvaluateString(const nsString& aString,
|
||||
nsString* aResult)
|
||||
{
|
||||
XPCShellEnvironment* env = Environment(mCx);
|
||||
XPCShellEnvironment::AutoContextPusher pusher(env);
|
||||
|
||||
JSAutoRequest ar(mCx);
|
||||
|
||||
JS_ClearPendingException(mCx);
|
||||
|
@ -1231,8 +1231,10 @@ jsdScript::GetParameterNames(PRUint32* count, PRUnichar*** paramNames)
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
uintN nargs = JS_GetFunctionArgumentCount(cx, fun);
|
||||
if (!fun || !JS_FunctionHasLocalNames(cx, fun) || nargs == 0) {
|
||||
uintN nargs;
|
||||
if (!fun ||
|
||||
!JS_FunctionHasLocalNames(cx, fun) ||
|
||||
(nargs = JS_GetFunctionArgumentCount(cx, fun)) == 0) {
|
||||
*count = 0;
|
||||
*paramNames = nsnull;
|
||||
return NS_OK;
|
||||
|
@ -292,23 +292,12 @@ endif # ENABLE_TRACEJIT
|
||||
ifdef ENABLE_METHODJIT
|
||||
|
||||
###############################################
|
||||
# BEGIN include sources for the Nitro assembler
|
||||
# BEGIN include sources for the method JIT
|
||||
#
|
||||
VPATH += $(srcdir)/assembler \
|
||||
$(srcdir)/assembler/wtf \
|
||||
$(srcdir)/assembler/jit \
|
||||
$(srcdir)/assembler/assembler \
|
||||
$(srcdir)/methodjit
|
||||
VPATH += $(srcdir)/methodjit
|
||||
|
||||
CPPSRCS += Assertions.cpp \
|
||||
ExecutableAllocatorPosix.cpp \
|
||||
ExecutableAllocatorWin.cpp \
|
||||
ExecutableAllocator.cpp \
|
||||
ARMAssembler.cpp \
|
||||
MacroAssemblerARM.cpp \
|
||||
MethodJIT.cpp \
|
||||
CPPSRCS += MethodJIT.cpp \
|
||||
BytecodeAnalyzer.cpp \
|
||||
Logging.cpp \
|
||||
StubCalls.cpp \
|
||||
Compiler.cpp \
|
||||
FrameState.cpp \
|
||||
@ -344,6 +333,71 @@ ifeq (arm, $(TARGET_CPU))
|
||||
#CPPSRCS += only_on_arm.cpp
|
||||
endif
|
||||
#
|
||||
# END enclude sources for the method JIT
|
||||
#############################################
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_CPU), powerpc)
|
||||
|
||||
VPATH += $(srcdir)/assembler \
|
||||
$(srcdir)/assembler/wtf \
|
||||
$(srcdir)/yarr/pcre \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS += pcre_compile.cpp \
|
||||
pcre_exec.cpp \
|
||||
pcre_tables.cpp \
|
||||
pcre_xclass.cpp \
|
||||
pcre_ucp_searchfuncs.cpp \
|
||||
$(NULL)
|
||||
else
|
||||
|
||||
###############################################
|
||||
# BEGIN include sources for the Nitro assembler
|
||||
#
|
||||
VPATH += $(srcdir)/assembler \
|
||||
$(srcdir)/assembler/wtf \
|
||||
$(srcdir)/assembler/jit \
|
||||
$(srcdir)/assembler/assembler \
|
||||
$(srcdir)/methodjit \
|
||||
$(srcdir)/yarr \
|
||||
$(srcdir)/yarr/yarr \
|
||||
$(srcdir)/yarr/pcre \
|
||||
$(srcdir)/yarr/wtf \
|
||||
$(NONE)
|
||||
|
||||
CPPSRCS += Assertions.cpp \
|
||||
ExecutableAllocatorPosix.cpp \
|
||||
ExecutableAllocatorWin.cpp \
|
||||
ExecutableAllocator.cpp \
|
||||
ARMAssembler.cpp \
|
||||
Logging.cpp \
|
||||
MacroAssemblerARM.cpp \
|
||||
MacroAssemblerX86Common.cpp \
|
||||
RegexCompiler.cpp \
|
||||
RegexJIT.cpp \
|
||||
pcre_compile.cpp \
|
||||
pcre_exec.cpp \
|
||||
pcre_tables.cpp \
|
||||
pcre_xclass.cpp \
|
||||
pcre_ucp_searchfuncs.cpp \
|
||||
$(NONE)
|
||||
|
||||
ifeq (86, $(findstring 86,$(TARGET_CPU)))
|
||||
ifeq (x86_64, $(TARGET_CPU))
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
ASFILES += TrampolineMasmX64.asm
|
||||
endif
|
||||
#CPPSRCS += only_on_x86_64.cpp
|
||||
else
|
||||
#CPPSRCS += only_on_x86.cpp
|
||||
endif
|
||||
endif
|
||||
ifeq (arm, $(TARGET_CPU))
|
||||
#CPPSRCS += only_on_arm.cpp
|
||||
endif
|
||||
#
|
||||
# END enclude sources for the Nitro assembler
|
||||
#############################################
|
||||
|
||||
@ -825,7 +879,7 @@ endif
|
||||
## backwards to that point. Ideally, merge with the rest of the
|
||||
## Nitro assembler stuff, far above.
|
||||
ifdef ENABLE_METHODJIT
|
||||
INCLUDES += -I$(srcdir)/assembler
|
||||
INCLUDES += -I$(srcdir)/assembler -I$(srcdir)/yarr
|
||||
#
|
||||
# Needed to "configure" it correctly. Unfortunately these
|
||||
# flags wind up being applied to all code in js/src, not just
|
||||
|
@ -24,8 +24,8 @@
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <wtf/Platform.h> // MOCO
|
||||
|
||||
#include "assembler/wtf/Platform.h"
|
||||
|
||||
#if ENABLE_ASSEMBLER && WTF_CPU_ARM_TRADITIONAL
|
||||
|
||||
#include "ARMAssembler.h"
|
||||
|
@ -27,7 +27,7 @@
|
||||
#ifndef ARMAssembler_h
|
||||
#define ARMAssembler_h
|
||||
|
||||
#include <wtf/Platform.h>
|
||||
#include "assembler/wtf/Platform.h"
|
||||
|
||||
// Some debug code uses s(n)printf for instruction logging.
|
||||
#include <stdio.h>
|
||||
@ -35,7 +35,7 @@
|
||||
#if ENABLE_ASSEMBLER && WTF_CPU_ARM_TRADITIONAL
|
||||
|
||||
#include "AssemblerBufferWithConstantPool.h"
|
||||
#include <wtf/Assertions.h>
|
||||
#include "assembler/wtf/Assertions.h"
|
||||
|
||||
#include "methodjit/Logging.h"
|
||||
#define IPFX " %s"
|
||||
|
@ -27,13 +27,13 @@
|
||||
#ifndef ARMAssembler_h
|
||||
#define ARMAssembler_h
|
||||
|
||||
#include <wtf/Platform.h>
|
||||
#include "assembler/wtf/Platform.h"
|
||||
|
||||
#if ENABLE(ASSEMBLER) && CPU(ARM_THUMB2)
|
||||
|
||||
#include "AssemblerBuffer.h"
|
||||
#include <wtf/Assertions.h>
|
||||
#include <wtf/Vector.h>
|
||||
#include "assembler/wtf/Assertions.h"
|
||||
#include "assembler/wtf/Vector.h"
|
||||
#include <stdint.h>
|
||||
|
||||
namespace JSC {
|
||||
|
@ -26,9 +26,9 @@
|
||||
#ifndef AbstractMacroAssembler_h
|
||||
#define AbstractMacroAssembler_h
|
||||
|
||||
#include <wtf/Platform.h>
|
||||
#include <assembler/MacroAssemblerCodeRef.h>
|
||||
#include <assembler/CodeLocation.h>
|
||||
#include "assembler/wtf/Platform.h"
|
||||
#include "assembler/assembler/MacroAssemblerCodeRef.h"
|
||||
#include "assembler/assembler/CodeLocation.h"
|
||||
#include "jsstdint.h"
|
||||
|
||||
#if ENABLE_ASSEMBLER
|
||||
@ -410,12 +410,12 @@ public:
|
||||
|
||||
void append(JumpList& other)
|
||||
{
|
||||
m_jumps.append(other.m_jumps.begin(), other.m_jumps.size());
|
||||
m_jumps.append(other.m_jumps.begin(), other.m_jumps.length());
|
||||
}
|
||||
|
||||
bool empty()
|
||||
{
|
||||
return !m_jumps.size();
|
||||
return !m_jumps.length();
|
||||
}
|
||||
|
||||
const JumpVector& jumps() { return m_jumps; }
|
||||
|
@ -26,13 +26,13 @@
|
||||
#ifndef AssemblerBuffer_h
|
||||
#define AssemblerBuffer_h
|
||||
|
||||
#include <wtf/Platform.h>
|
||||
#include "assembler/wtf/Platform.h"
|
||||
|
||||
#if ENABLE_ASSEMBLER
|
||||
|
||||
#include <string.h>
|
||||
#include <jit/ExecutableAllocator.h>
|
||||
#include <wtf/Assertions.h>
|
||||
#include "assembler/jit/ExecutableAllocator.h"
|
||||
#include "assembler/wtf/Assertions.h"
|
||||
#include "jsstdint.h"
|
||||
|
||||
namespace JSC {
|
||||
|
@ -27,12 +27,12 @@
|
||||
#ifndef AssemblerBufferWithConstantPool_h
|
||||
#define AssemblerBufferWithConstantPool_h
|
||||
|
||||
#include <wtf/Platform.h>
|
||||
#include "assembler/wtf/Platform.h"
|
||||
|
||||
#if ENABLE_ASSEMBLER
|
||||
|
||||
#include "AssemblerBuffer.h"
|
||||
#include <wtf/SegmentedVector.h>
|
||||
#include "assembler/wtf/SegmentedVector.h"
|
||||
|
||||
#define ASSEMBLER_HAS_CONSTANT_POOL 1
|
||||
|
||||
|
@ -26,8 +26,8 @@
|
||||
#ifndef CodeLocation_h
|
||||
#define CodeLocation_h
|
||||
|
||||
#include <wtf/Platform.h>
|
||||
#include <assembler/MacroAssemblerCodeRef.h>
|
||||
#include "assembler/wtf/Platform.h"
|
||||
#include "assembler/assembler/MacroAssemblerCodeRef.h"
|
||||
|
||||
#if ENABLE_ASSEMBLER
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
#ifndef LinkBuffer_h
|
||||
#define LinkBuffer_h
|
||||
|
||||
#include <wtf/Platform.h>
|
||||
#include "assembler/wtf/Platform.h"
|
||||
|
||||
#if ENABLE_ASSEMBLER
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
#ifndef MacroAssembler_h
|
||||
#define MacroAssembler_h
|
||||
|
||||
#include <wtf/Platform.h>
|
||||
#include "assembler/wtf/Platform.h"
|
||||
|
||||
#if ENABLE_ASSEMBLER
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <wtf/Platform.h>
|
||||
#include "assembler/wtf/Platform.h"
|
||||
|
||||
#if ENABLE_ASSEMBLER && WTF_CPU_ARM_TRADITIONAL
|
||||
|
||||
@ -36,9 +36,18 @@
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <elf.h>
|
||||
|
||||
// lame check for kernel version
|
||||
// see bug 586550
|
||||
#include <linux/version.h>
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
|
||||
#include <asm/procinfo.h>
|
||||
#else
|
||||
#include <asm/hwcap.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
namespace JSC {
|
||||
|
||||
static bool isVFPPresent()
|
||||
|
@ -28,7 +28,7 @@
|
||||
#ifndef MacroAssemblerARM_h
|
||||
#define MacroAssemblerARM_h
|
||||
|
||||
#include <wtf/Platform.h>
|
||||
#include "assembler/wtf/Platform.h"
|
||||
|
||||
#if ENABLE_ASSEMBLER && WTF_CPU_ARM_TRADITIONAL
|
||||
|
||||
@ -972,7 +972,6 @@ public:
|
||||
// Truncates 'src' to an integer, and places the resulting 'dest'.
|
||||
// If the result is not representable as a 32 bit value, branch.
|
||||
// May also branch for some values that are representable in 32 bits
|
||||
// (specifically, in this case, INT_MIN and INT_MAX).
|
||||
Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
|
||||
{
|
||||
m_assembler.ftosizd_r(ARMRegisters::SD0, src);
|
||||
|
@ -27,7 +27,7 @@
|
||||
#ifndef MacroAssemblerARMv7_h
|
||||
#define MacroAssemblerARMv7_h
|
||||
|
||||
#include <wtf/Platform.h>
|
||||
#include "assembler/wtf/Platform.h"
|
||||
|
||||
#if ENABLE(ASSEMBLER)
|
||||
|
||||
|
@ -26,8 +26,8 @@
|
||||
#ifndef MacroAssemblerCodeRef_h
|
||||
#define MacroAssemblerCodeRef_h
|
||||
|
||||
#include <wtf/Platform.h>
|
||||
#include <jit/ExecutableAllocator.h>
|
||||
#include "assembler/wtf/Platform.h"
|
||||
#include "assembler/jit/ExecutableAllocator.h"
|
||||
|
||||
#if ENABLE_ASSEMBLER
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
#ifndef MacroAssemblerX86_h
|
||||
#define MacroAssemblerX86_h
|
||||
|
||||
#include <wtf/Platform.h>
|
||||
#include "assembler/wtf/Platform.h"
|
||||
|
||||
#if ENABLE_ASSEMBLER && WTF_CPU_X86
|
||||
|
||||
|
11
js/src/assembler/assembler/MacroAssemblerX86Common.cpp
Normal file
11
js/src/assembler/assembler/MacroAssemblerX86Common.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include "assembler/wtf/Platform.h"
|
||||
|
||||
#if WTF_CPU_X86 && !WTF_PLATFORM_MAC
|
||||
|
||||
#include "MacroAssemblerX86Common.h"
|
||||
|
||||
using namespace JSC;
|
||||
|
||||
MacroAssemblerX86Common::SSE2CheckState MacroAssemblerX86Common::s_sse2CheckState = NotCheckedSSE2;
|
||||
|
||||
#endif
|
@ -26,7 +26,7 @@
|
||||
#ifndef MacroAssemblerX86Common_h
|
||||
#define MacroAssemblerX86Common_h
|
||||
|
||||
#include <wtf/Platform.h>
|
||||
#include "assembler/wtf/Platform.h"
|
||||
|
||||
#if ENABLE_ASSEMBLER
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
#ifndef MacroAssemblerX86_64_h
|
||||
#define MacroAssemblerX86_64_h
|
||||
|
||||
#include <wtf/Platform.h>
|
||||
#include "assembler/wtf/Platform.h"
|
||||
|
||||
#if ENABLE_ASSEMBLER && WTF_CPU_X86_64
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
#ifndef RepatchBuffer_h
|
||||
#define RepatchBuffer_h
|
||||
|
||||
#include <wtf/Platform.h>
|
||||
#include "assembler/wtf/Platform.h"
|
||||
|
||||
#if ENABLE_ASSEMBLER
|
||||
|
||||
|
@ -26,13 +26,13 @@
|
||||
#ifndef X86Assembler_h
|
||||
#define X86Assembler_h
|
||||
|
||||
#include <wtf/Platform.h>
|
||||
#include "assembler/wtf/Platform.h"
|
||||
|
||||
#if ENABLE_ASSEMBLER && (WTF_CPU_X86 || WTF_CPU_X86_64)
|
||||
|
||||
#include "AssemblerBuffer.h"
|
||||
#include "jsstdint.h"
|
||||
#include <wtf/Assertions.h>
|
||||
#include "assembler/wtf/Assertions.h"
|
||||
#include "jsvector.h"
|
||||
|
||||
#include "methodjit/Logging.h"
|
||||
|
@ -894,31 +894,17 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */
|
||||
#if !defined(ENABLE_YARR_JIT)
|
||||
|
||||
/* YARR supports x86 & x86-64, and has been tested on Mac and Windows. */
|
||||
#if (WTF_CPU_X86 && WTF_PLATFORM_MAC) \
|
||||
|| (WTF_CPU_X86_64 && WTF_PLATFORM_MAC) \
|
||||
|| (WTF_CPU_ARM_THUMB2 && WTF_PLATFORM_IPHONE) \
|
||||
|| (WTF_CPU_X86 && WTF_PLATFORM_WIN)
|
||||
#define ENABLE_YARR 1
|
||||
#if WTF_CPU_X86 \
|
||||
|| WTF_CPU_X86_64 \
|
||||
|| WTF_CPU_ARM_THUMB2 \
|
||||
|| WTF_CPU_X86
|
||||
#define ENABLE_YARR_JIT 1
|
||||
#endif
|
||||
|
||||
#if WTF_PLATFORM_QT
|
||||
#if (WTF_CPU_X86 && WTF_PLATFORM_WIN_OS && WTF_COMPILER_MINGW && GCC_VERSION >= 40100) \
|
||||
|| (WTF_CPU_X86 && WTF_PLATFORM_WIN_OS && WTF_COMPILER_MSVC) \
|
||||
|| (WTF_CPU_X86 && WTF_PLATFORM_LINUX && GCC_VERSION >= 40100) \
|
||||
|| (WTF_CPU_ARM_TRADITIONAL && WTF_PLATFORM_LINUX)
|
||||
#define ENABLE_YARR 1
|
||||
#define ENABLE_YARR_JIT 1
|
||||
#endif
|
||||
#else
|
||||
#define ENABLE_YARR_JIT 0
|
||||
#endif
|
||||
|
||||
#endif /* !defined(ENABLE_YARR_JIT) */
|
||||
|
||||
/* Sanity Check */
|
||||
#if ENABLE_YARR_JIT && !ENABLE_YARR
|
||||
#error "YARR_JIT requires YARR"
|
||||
#endif
|
||||
|
||||
#if ENABLE_JIT || ENABLE_YARR_JIT
|
||||
#define ENABLE_ASSEMBLER 1
|
||||
#endif
|
||||
|
@ -1036,4 +1036,7 @@ event.h
|
||||
#ifdef MOZ_ENABLE_LIBPROXY
|
||||
proxy.h
|
||||
#endif
|
||||
#if MOZ_PLATFORM_MAEMO==6
|
||||
contentaction/contentaction.h
|
||||
#endif
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user