mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge latest green birch changeset and mozilla-central
This commit is contained in:
commit
38df1ffab0
@ -542,7 +542,7 @@ var Input = {
|
||||
switch (gestureName) {
|
||||
case 'dwell1':
|
||||
case 'explore1':
|
||||
this.moveCursor('moveToPoint', 'Simple', 'gesture',
|
||||
this.moveCursor('moveToPoint', 'SimpleTouch', 'gesture',
|
||||
aGesture.x, aGesture.y);
|
||||
break;
|
||||
case 'doubletap1':
|
||||
|
@ -57,8 +57,7 @@ this.EventManager.prototype = {
|
||||
this.present(Presentation.tabStateChanged(null, 'newtab'));
|
||||
|
||||
} catch (x) {
|
||||
Logger.error('Failed to start EventManager');
|
||||
Logger.logException(x);
|
||||
Logger.logException(x, 'Failed to start EventManager');
|
||||
}
|
||||
},
|
||||
|
||||
@ -117,8 +116,7 @@ this.EventManager.prototype = {
|
||||
}
|
||||
}
|
||||
} catch (x) {
|
||||
Logger.error('Error handling DOM event');
|
||||
Logger.logException(x);
|
||||
Logger.logException(x, 'Error handling DOM event');
|
||||
}
|
||||
},
|
||||
|
||||
@ -140,7 +138,7 @@ this.EventManager.prototype = {
|
||||
let pivot = aEvent.accessible.
|
||||
QueryInterface(Ci.nsIAccessibleDocument).virtualCursor;
|
||||
let position = pivot.position;
|
||||
if (position.role == Ci.nsIAccessibleRole.ROLE_INTERNAL_FRAME)
|
||||
if (position && position.role == Ci.nsIAccessibleRole.ROLE_INTERNAL_FRAME)
|
||||
break;
|
||||
let event = aEvent.
|
||||
QueryInterface(Ci.nsIAccessibleVirtualCursorChangeEvent);
|
||||
@ -421,8 +419,7 @@ const AccessibilityEventObserver = {
|
||||
try {
|
||||
eventManager.handleAccEvent(event);
|
||||
} catch (x) {
|
||||
Logger.error('Error handing accessible event');
|
||||
Logger.logException(x);
|
||||
Logger.logException(x, 'Error handing accessible event');
|
||||
} finally {
|
||||
return;
|
||||
}
|
||||
|
@ -22,6 +22,11 @@ XPCOMUtils.defineLazyModuleGetter(this, 'Utils',
|
||||
'resource://gre/modules/accessibility/Utils.jsm');
|
||||
XPCOMUtils.defineLazyModuleGetter(this, 'PrefCache',
|
||||
'resource://gre/modules/accessibility/Utils.jsm');
|
||||
XPCOMUtils.defineLazyModuleGetter(this, 'Logger',
|
||||
'resource://gre/modules/accessibility/Utils.jsm');
|
||||
XPCOMUtils.defineLazyModuleGetter(this, 'PluralForm',
|
||||
'resource://gre/modules/PluralForm.jsm');
|
||||
|
||||
|
||||
let gUtteranceOrder = new PrefCache('accessibility.accessfu.utterance');
|
||||
|
||||
@ -46,7 +51,7 @@ this.OutputGenerator = {
|
||||
let output = [];
|
||||
let self = this;
|
||||
let addOutput = function addOutput(aAccessible) {
|
||||
output.push.apply(output, self.genForObject(aAccessible));
|
||||
output.push.apply(output, self.genForObject(aAccessible, aContext));
|
||||
};
|
||||
let ignoreSubtree = function ignoreSubtree(aAccessible) {
|
||||
let roleString = Utils.AccRetrieval.getStringRole(aAccessible.role);
|
||||
@ -83,14 +88,18 @@ this.OutputGenerator = {
|
||||
* Generates output for an object.
|
||||
* @param {nsIAccessible} aAccessible accessible object to generate utterance
|
||||
* for.
|
||||
* @param {PivotContext} aContext object that generates and caches
|
||||
* context information for a given accessible and its relationship with
|
||||
* another accessible.
|
||||
* @return {Array} Two string array. The first string describes the object
|
||||
* and its states. The second string is the object's name. Whether the
|
||||
* object's description or it's role is included is determined by
|
||||
* {@link roleRuleMap}.
|
||||
*/
|
||||
genForObject: function genForObject(aAccessible) {
|
||||
genForObject: function genForObject(aAccessible, aContext) {
|
||||
let roleString = Utils.AccRetrieval.getStringRole(aAccessible.role);
|
||||
let func = this.objectOutputFunctions[roleString.replace(' ', '')] ||
|
||||
let func = this.objectOutputFunctions[
|
||||
OutputGenerator._getOutputName(roleString)] ||
|
||||
this.objectOutputFunctions.defaultFunc;
|
||||
|
||||
let flags = this.roleRuleMap[roleString] || 0;
|
||||
@ -103,7 +112,7 @@ this.OutputGenerator = {
|
||||
aAccessible.getState(state, extState);
|
||||
let states = {base: state.value, ext: extState.value};
|
||||
|
||||
return func.apply(this, [aAccessible, roleString, states, flags]);
|
||||
return func.apply(this, [aAccessible, roleString, states, flags, aContext]);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -158,10 +167,20 @@ this.OutputGenerator = {
|
||||
}
|
||||
},
|
||||
|
||||
_getOutputName: function _getOutputName(aName) {
|
||||
return aName.replace(' ', '');
|
||||
},
|
||||
|
||||
_getLocalizedRole: function _getLocalizedRole(aRoleStr) {},
|
||||
|
||||
_getLocalizedStates: function _getLocalizedStates(aStates) {},
|
||||
|
||||
_getPluralFormString: function _getPluralFormString(aString, aCount) {
|
||||
let str = gStringBundle.GetStringFromName(this._getOutputName(aString));
|
||||
str = PluralForm.get(aCount, str);
|
||||
return str.replace('#1', aCount);
|
||||
},
|
||||
|
||||
roleRuleMap: {
|
||||
'menubar': INCLUDE_DESC,
|
||||
'scrollbar': INCLUDE_DESC,
|
||||
@ -170,10 +189,11 @@ this.OutputGenerator = {
|
||||
'menupopup': INCLUDE_DESC,
|
||||
'menuitem': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
|
||||
'tooltip': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
|
||||
'columnheader': NAME_FROM_SUBTREE_RULE,
|
||||
'rowheader': NAME_FROM_SUBTREE_RULE,
|
||||
'columnheader': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
|
||||
'rowheader': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
|
||||
'column': NAME_FROM_SUBTREE_RULE,
|
||||
'row': NAME_FROM_SUBTREE_RULE,
|
||||
'cell': INCLUDE_DESC | INCLUDE_NAME,
|
||||
'application': INCLUDE_NAME,
|
||||
'document': INCLUDE_NAME,
|
||||
'grouping': INCLUDE_DESC | INCLUDE_NAME,
|
||||
@ -263,6 +283,32 @@ this.OutputGenerator = {
|
||||
this._addName(output, aAccessible, aFlags);
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
table: function table(aAccessible, aRoleStr, aStates, aFlags) {
|
||||
let output = [];
|
||||
let table;
|
||||
try {
|
||||
table = aAccessible.QueryInterface(Ci.nsIAccessibleTable);
|
||||
} catch (x) {
|
||||
Logger.logException(x);
|
||||
return output;
|
||||
} finally {
|
||||
// Check if it's a layout table, and bail out if true.
|
||||
// We don't want to speak any table information for layout tables.
|
||||
if (table.isProbablyForLayout()) {
|
||||
return output;
|
||||
}
|
||||
let tableColumnInfo = this._getPluralFormString('tableColumnInfo',
|
||||
table.columnCount);
|
||||
let tableRowInfo = this._getPluralFormString('tableRowInfo',
|
||||
table.rowCount);
|
||||
output.push(gStringBundle.formatStringFromName(
|
||||
this._getOutputName('tableInfo'), [this._getLocalizedRole(aRoleStr),
|
||||
tableColumnInfo, tableRowInfo], 3));
|
||||
this._addName(output, aAccessible, aFlags);
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -341,12 +387,11 @@ this.UtteranceGenerator = {
|
||||
},
|
||||
|
||||
objectOutputFunctions: {
|
||||
defaultFunc: function defaultFunc(aAccessible, aRoleStr, aStates, aFlags) {
|
||||
return OutputGenerator.objectOutputFunctions._generateBaseOutput.apply(this, arguments);
|
||||
},
|
||||
|
||||
entry: function entry(aAccessible, aRoleStr, aStates, aFlags) {
|
||||
return OutputGenerator.objectOutputFunctions.entry.apply(this, arguments);
|
||||
__proto__: OutputGenerator.objectOutputFunctions,
|
||||
|
||||
defaultFunc: function defaultFunc(aAccessible, aRoleStr, aStates, aFlags) {
|
||||
return this.objectOutputFunctions._generateBaseOutput.apply(this, arguments);
|
||||
},
|
||||
|
||||
heading: function heading(aAccessible, aRoleStr, aStates, aFlags) {
|
||||
@ -392,6 +437,53 @@ this.UtteranceGenerator = {
|
||||
[aAccessible, aRoleStr, aStates, aFlags]);
|
||||
|
||||
return [];
|
||||
},
|
||||
|
||||
cell: function cell(aAccessible, aRoleStr, aStates, aFlags, aContext) {
|
||||
let utterance = [];
|
||||
let cell = aContext.getCellInfo(aAccessible);
|
||||
if (cell) {
|
||||
let desc = [];
|
||||
let addCellChanged = function addCellChanged(aDesc, aChanged, aString, aIndex) {
|
||||
if (aChanged) {
|
||||
aDesc.push(gStringBundle.formatStringFromName(aString,
|
||||
[aIndex + 1], 1));
|
||||
}
|
||||
};
|
||||
let addExtent = function addExtent(aDesc, aExtent, aString) {
|
||||
if (aExtent > 1) {
|
||||
aDesc.push(gStringBundle.formatStringFromName(aString,
|
||||
[aExtent], 1));
|
||||
}
|
||||
};
|
||||
let addHeaders = function addHeaders(aDesc, aHeaders) {
|
||||
if (aHeaders.length > 0) {
|
||||
aDesc.push.apply(aDesc, aHeaders);
|
||||
}
|
||||
};
|
||||
|
||||
addCellChanged(desc, cell.columnChanged, 'columnInfo', cell.columnIndex);
|
||||
addCellChanged(desc, cell.rowChanged, 'rowInfo', cell.rowIndex);
|
||||
|
||||
addExtent(desc, cell.columnExtent, 'spansColumns');
|
||||
addExtent(desc, cell.rowExtent, 'spansRows');
|
||||
|
||||
addHeaders(desc, cell.columnHeaders);
|
||||
addHeaders(desc, cell.rowHeaders);
|
||||
|
||||
utterance.push(desc.join(' '));
|
||||
}
|
||||
|
||||
this._addName(utterance, aAccessible, aFlags);
|
||||
return utterance;
|
||||
},
|
||||
|
||||
columnheader: function columnheader() {
|
||||
return this.objectOutputFunctions.cell.apply(this, arguments);
|
||||
},
|
||||
|
||||
rowheader: function rowheader() {
|
||||
return this.objectOutputFunctions.cell.apply(this, arguments);
|
||||
}
|
||||
},
|
||||
|
||||
@ -401,7 +493,7 @@ this.UtteranceGenerator = {
|
||||
|
||||
_getLocalizedRole: function _getLocalizedRole(aRoleStr) {
|
||||
try {
|
||||
return gStringBundle.GetStringFromName(aRoleStr.replace(' ', ''));
|
||||
return gStringBundle.GetStringFromName(this._getOutputName(aRoleStr));
|
||||
} catch (x) {
|
||||
return '';
|
||||
}
|
||||
@ -467,8 +559,11 @@ this.BrailleGenerator = {
|
||||
defaultOutputOrder: OUTPUT_DESC_LAST,
|
||||
|
||||
objectOutputFunctions: {
|
||||
|
||||
__proto__: OutputGenerator.objectOutputFunctions,
|
||||
|
||||
defaultFunc: function defaultFunc(aAccessible, aRoleStr, aStates, aFlags) {
|
||||
let braille = OutputGenerator.objectOutputFunctions._generateBaseOutput.apply(this, arguments);
|
||||
let braille = this.objectOutputFunctions._generateBaseOutput.apply(this, arguments);
|
||||
|
||||
if (aAccessible.indexInParent === 1 &&
|
||||
aAccessible.parent.role == Ci.nsIAccessibleRole.ROLE_LISTITEM &&
|
||||
@ -492,6 +587,38 @@ this.BrailleGenerator = {
|
||||
return braille;
|
||||
},
|
||||
|
||||
cell: function cell(aAccessible, aRoleStr, aStates, aFlags, aContext) {
|
||||
let braille = [];
|
||||
let cell = aContext.getCellInfo(aAccessible);
|
||||
if (cell) {
|
||||
let desc = [];
|
||||
let addHeaders = function addHeaders(aDesc, aHeaders) {
|
||||
if (aHeaders.length > 0) {
|
||||
aDesc.push.apply(aDesc, aHeaders);
|
||||
}
|
||||
};
|
||||
|
||||
desc.push(gStringBundle.formatStringFromName(
|
||||
this._getOutputName('cellInfo'), [cell.columnIndex + 1,
|
||||
cell.rowIndex + 1], 2));
|
||||
|
||||
addHeaders(desc, cell.columnHeaders);
|
||||
addHeaders(desc, cell.rowHeaders);
|
||||
braille.push(desc.join(' '));
|
||||
}
|
||||
|
||||
this._addName(braille, aAccessible, aFlags);
|
||||
return braille;
|
||||
},
|
||||
|
||||
columnheader: function columnheader() {
|
||||
return this.objectOutputFunctions.cell.apply(this, arguments);
|
||||
},
|
||||
|
||||
rowheader: function rowheader() {
|
||||
return this.objectOutputFunctions.cell.apply(this, arguments);
|
||||
},
|
||||
|
||||
statictext: function statictext(aAccessible, aRoleStr, aStates, aFlags) {
|
||||
// Since we customize the list bullet's output, we add the static
|
||||
// text from the first node in each listitem, so skip it here.
|
||||
@ -523,10 +650,6 @@ this.BrailleGenerator = {
|
||||
|
||||
togglebutton: function radiobutton(aAccessible, aRoleStr, aStates, aFlags) {
|
||||
return this.objectOutputFunctions._useStateNotRole.apply(this, arguments);
|
||||
},
|
||||
|
||||
entry: function entry(aAccessible, aRoleStr, aStates, aFlags) {
|
||||
return OutputGenerator.objectOutputFunctions.entry.apply(this, arguments);
|
||||
}
|
||||
},
|
||||
|
||||
@ -538,12 +661,17 @@ this.BrailleGenerator = {
|
||||
return [];
|
||||
},
|
||||
|
||||
_getOutputName: function _getOutputName(aName) {
|
||||
return OutputGenerator._getOutputName(aName) + 'Abbr';
|
||||
},
|
||||
|
||||
_getLocalizedRole: function _getLocalizedRole(aRoleStr) {
|
||||
try {
|
||||
return gStringBundle.GetStringFromName(aRoleStr.replace(' ', '') + 'Abbr');
|
||||
return gStringBundle.GetStringFromName(this._getOutputName(aRoleStr));
|
||||
} catch (x) {
|
||||
try {
|
||||
return gStringBundle.GetStringFromName(aRoleStr.replace(' ', ''));
|
||||
return gStringBundle.GetStringFromName(
|
||||
OutputGenerator._getOutputName(aRoleStr));
|
||||
} catch (y) {
|
||||
return '';
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ VisualPresenter.prototype = {
|
||||
}
|
||||
};
|
||||
} catch (e) {
|
||||
Logger.error('Failed to get bounds: ' + e);
|
||||
Logger.logException(e, 'Failed to get bounds');
|
||||
return null;
|
||||
}
|
||||
},
|
||||
@ -398,6 +398,19 @@ SpeechPresenter.prototype = {
|
||||
]
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
actionInvoked: function SpeechPresenter_actionInvoked(aObject, aActionName) {
|
||||
return {
|
||||
type: this.type,
|
||||
details: {
|
||||
actions: [
|
||||
{method: 'speak',
|
||||
data: UtteranceGenerator.genForAction(aObject, aActionName).join(' '),
|
||||
options: {enqueue: false}}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -9,6 +9,10 @@ const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
const FILTER_IGNORE = Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
|
||||
const FILTER_MATCH = Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
const FILTER_IGNORE_SUBTREE = Ci.nsIAccessibleTraversalRule.FILTER_IGNORE_SUBTREE;
|
||||
|
||||
this.EXPORTED_SYMBOLS = ['TraversalRules'];
|
||||
|
||||
Cu.import('resource://gre/modules/accessibility/Utils.jsm');
|
||||
@ -35,14 +39,13 @@ BaseTraversalRule.prototype = {
|
||||
{
|
||||
if (aAccessible.role == Ci.nsIAccessibleRole.ROLE_INTERNAL_FRAME) {
|
||||
return (Utils.getMessageManager(aAccessible.DOMNode)) ?
|
||||
Ci.nsIAccessibleTraversalRule.FILTER_MATCH :
|
||||
Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
|
||||
FILTER_MATCH | FILTER_IGNORE_SUBTREE : FILTER_IGNORE;
|
||||
}
|
||||
|
||||
if (this._matchFunc)
|
||||
return this._matchFunc(aAccessible);
|
||||
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
return FILTER_MATCH;
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule])
|
||||
@ -78,40 +81,40 @@ this.TraversalRules = {
|
||||
case Ci.nsIAccessibleRole.ROLE_COMBOBOX:
|
||||
// We don't want to ignore the subtree because this is often
|
||||
// where the list box hangs out.
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
return FILTER_MATCH;
|
||||
case Ci.nsIAccessibleRole.ROLE_TEXT_LEAF:
|
||||
{
|
||||
// Nameless text leaves are boring, skip them.
|
||||
let name = aAccessible.name;
|
||||
if (name && name.trim())
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
return FILTER_MATCH;
|
||||
else
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
|
||||
return FILTER_IGNORE;
|
||||
}
|
||||
case Ci.nsIAccessibleRole.ROLE_LINK:
|
||||
// If the link has children we should land on them instead.
|
||||
// Image map links don't have children so we need to match those.
|
||||
if (aAccessible.childCount == 0)
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
return FILTER_MATCH;
|
||||
else
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
|
||||
return FILTER_IGNORE;
|
||||
case Ci.nsIAccessibleRole.ROLE_STATICTEXT:
|
||||
{
|
||||
let parent = aAccessible.parent;
|
||||
// Ignore prefix static text in list items. They are typically bullets or numbers.
|
||||
if (parent.childCount > 1 && aAccessible.indexInParent == 0 &&
|
||||
parent.role == Ci.nsIAccessibleRole.ROLE_LISTITEM)
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
|
||||
return FILTER_IGNORE;
|
||||
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
return FILTER_MATCH;
|
||||
}
|
||||
case Ci.nsIAccessibleRole.ROLE_GRAPHIC:
|
||||
return TraversalRules._shouldSkipImage(aAccessible);
|
||||
default:
|
||||
// Ignore the subtree, if there is one. So that we don't land on
|
||||
// the same content that was already presented by its parent.
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH |
|
||||
Ci.nsIAccessibleTraversalRule.FILTER_IGNORE_SUBTREE;
|
||||
return FILTER_MATCH |
|
||||
FILTER_IGNORE_SUBTREE;
|
||||
}
|
||||
}
|
||||
),
|
||||
@ -119,8 +122,8 @@ this.TraversalRules = {
|
||||
SimpleTouch: new BaseTraversalRule(
|
||||
gSimpleTraversalRoles,
|
||||
function Simple_match(aAccessible) {
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH |
|
||||
Ci.nsIAccessibleTraversalRule.FILTER_IGNORE_SUBTREE;
|
||||
return FILTER_MATCH |
|
||||
FILTER_IGNORE_SUBTREE;
|
||||
}
|
||||
),
|
||||
|
||||
@ -133,9 +136,9 @@ this.TraversalRules = {
|
||||
let extraState = {};
|
||||
aAccessible.getState(state, extraState);
|
||||
if (state.value & Ci.nsIAccessibleStates.STATE_LINKED) {
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
|
||||
return FILTER_IGNORE;
|
||||
} else {
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
return FILTER_MATCH;
|
||||
}
|
||||
}),
|
||||
|
||||
@ -193,9 +196,9 @@ this.TraversalRules = {
|
||||
let extraState = {};
|
||||
aAccessible.getState(state, extraState);
|
||||
if (state.value & Ci.nsIAccessibleStates.STATE_LINKED) {
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
return FILTER_MATCH;
|
||||
} else {
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
|
||||
return FILTER_IGNORE;
|
||||
}
|
||||
}),
|
||||
|
||||
@ -222,8 +225,8 @@ this.TraversalRules = {
|
||||
|
||||
_shouldSkipImage: function _shouldSkipImage(aAccessible) {
|
||||
if (gSkipEmptyImages.value && aAccessible.name === '') {
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
|
||||
return FILTER_IGNORE;
|
||||
}
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
return FILTER_MATCH;
|
||||
}
|
||||
};
|
||||
|
@ -191,15 +191,18 @@ this.Utils = {
|
||||
},
|
||||
|
||||
getAttributes: function getAttributes(aAccessible) {
|
||||
let attributesEnum = aAccessible.attributes.enumerate();
|
||||
let attributes = {};
|
||||
|
||||
// Populate |attributes| object with |aAccessible|'s attribute key-value
|
||||
// pairs.
|
||||
while (attributesEnum.hasMoreElements()) {
|
||||
let attribute = attributesEnum.getNext().QueryInterface(
|
||||
Ci.nsIPropertyElement);
|
||||
attributes[attribute.key] = attribute.value;
|
||||
if (aAccessible && aAccessible.attributes) {
|
||||
let attributesEnum = aAccessible.attributes.enumerate();
|
||||
|
||||
// Populate |attributes| object with |aAccessible|'s attribute key-value
|
||||
// pairs.
|
||||
while (attributesEnum.hasMoreElements()) {
|
||||
let attribute = attributesEnum.getNext().QueryInterface(
|
||||
Ci.nsIPropertyElement);
|
||||
attributes[attribute.key] = attribute.value;
|
||||
}
|
||||
}
|
||||
|
||||
return attributes;
|
||||
@ -268,12 +271,27 @@ this.Logger = {
|
||||
this, [this.ERROR].concat(Array.prototype.slice.call(arguments)));
|
||||
},
|
||||
|
||||
logException: function logException(aException) {
|
||||
logException: function logException(
|
||||
aException, aErrorMessage = 'An exception has occured') {
|
||||
try {
|
||||
let args = [aException.message];
|
||||
args.push.apply(args, aException.stack ? ['\n', aException.stack] :
|
||||
['(' + aException.fileName + ':' + aException.lineNumber + ')']);
|
||||
this.error.apply(this, args);
|
||||
let stackMessage = '';
|
||||
if (aException.stack) {
|
||||
stackMessage = ' ' + aException.stack.replace(/\n/g, '\n ');
|
||||
} else if (aException.location) {
|
||||
let frame = aException.location;
|
||||
let stackLines = [];
|
||||
while (frame && frame.lineNumber) {
|
||||
stackLines.push(
|
||||
' ' + frame.name + '@' + frame.filename + ':' + frame.lineNumber);
|
||||
frame = frame.caller;
|
||||
}
|
||||
stackMessage = stackLines.join('\n');
|
||||
} else {
|
||||
stackMessage = '(' + aException.fileName + ':' + aException.lineNumber + ')';
|
||||
}
|
||||
this.error(aErrorMessage + ':\n ' +
|
||||
aException.message + '\n' +
|
||||
stackMessage);
|
||||
} catch (x) {
|
||||
this.error(x);
|
||||
}
|
||||
@ -350,6 +368,45 @@ PivotContext.prototype = {
|
||||
return this._oldAccessible;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get a list of |aAccessible|'s ancestry up to the root.
|
||||
* @param {nsIAccessible} aAccessible.
|
||||
* @return {Array} Ancestry list.
|
||||
*/
|
||||
_getAncestry: function _getAncestry(aAccessible) {
|
||||
let ancestry = [];
|
||||
let parent = aAccessible;
|
||||
while (parent && (parent = parent.parent)) {
|
||||
ancestry.push(parent);
|
||||
}
|
||||
return ancestry.reverse();
|
||||
},
|
||||
|
||||
/**
|
||||
* A list of the old accessible's ancestry.
|
||||
*/
|
||||
get oldAncestry() {
|
||||
if (!this._oldAncestry) {
|
||||
if (!this._oldAccessible) {
|
||||
this._oldAncestry = [];
|
||||
} else {
|
||||
this._oldAncestry = this._getAncestry(this._oldAccessible);
|
||||
this._oldAncestry.push(this._oldAccessible);
|
||||
}
|
||||
}
|
||||
return this._oldAncestry;
|
||||
},
|
||||
|
||||
/**
|
||||
* A list of the current accessible's ancestry.
|
||||
*/
|
||||
get currentAncestry() {
|
||||
if (!this._currentAncestry) {
|
||||
this._currentAncestry = this._getAncestry(this._accessible);
|
||||
}
|
||||
return this._currentAncestry;
|
||||
},
|
||||
|
||||
/*
|
||||
* This is a list of the accessible's ancestry up to the common ancestor
|
||||
* of the accessible and the old accessible. It is useful for giving the
|
||||
@ -357,32 +414,10 @@ PivotContext.prototype = {
|
||||
*/
|
||||
get newAncestry() {
|
||||
if (!this._newAncestry) {
|
||||
let newLineage = [];
|
||||
let oldLineage = [];
|
||||
|
||||
let parent = this._accessible;
|
||||
while (parent && (parent = parent.parent))
|
||||
newLineage.push(parent);
|
||||
|
||||
parent = this._oldAccessible;
|
||||
while (parent && (parent = parent.parent))
|
||||
oldLineage.push(parent);
|
||||
|
||||
this._newAncestry = [];
|
||||
|
||||
while (true) {
|
||||
let newAncestor = newLineage.pop();
|
||||
let oldAncestor = oldLineage.pop();
|
||||
|
||||
if (newAncestor == undefined)
|
||||
break;
|
||||
|
||||
if (newAncestor != oldAncestor)
|
||||
this._newAncestry.push(newAncestor);
|
||||
}
|
||||
|
||||
this._newAncestry = [currentAncestor for (
|
||||
[index, currentAncestor] of Iterator(this.currentAncestry)) if (
|
||||
currentAncestor !== this.oldAncestry[index])];
|
||||
}
|
||||
|
||||
return this._newAncestry;
|
||||
},
|
||||
|
||||
@ -426,6 +461,99 @@ PivotContext.prototype = {
|
||||
return this._traverse(this._accessible, aPreorder, aStop);
|
||||
},
|
||||
|
||||
getCellInfo: function getCellInfo(aAccessible) {
|
||||
if (!this._cells) {
|
||||
this._cells = new WeakMap();
|
||||
}
|
||||
|
||||
let domNode = aAccessible.DOMNode;
|
||||
if (this._cells.has(domNode)) {
|
||||
return this._cells.get(domNode);
|
||||
}
|
||||
|
||||
let cellInfo = {};
|
||||
let getAccessibleCell = function getAccessibleCell(aAccessible) {
|
||||
if (!aAccessible) {
|
||||
return null;
|
||||
}
|
||||
if ([Ci.nsIAccessibleRole.ROLE_CELL,
|
||||
Ci.nsIAccessibleRole.ROLE_COLUMNHEADER,
|
||||
Ci.nsIAccessibleRole.ROLE_ROWHEADER].indexOf(
|
||||
aAccessible.role) < 0) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return aAccessible.QueryInterface(Ci.nsIAccessibleTableCell);
|
||||
} catch (x) {
|
||||
Logger.logException(x);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
let getHeaders = function getHeaders(aHeaderCells) {
|
||||
let enumerator = aHeaderCells.enumerate();
|
||||
while (enumerator.hasMoreElements()) {
|
||||
yield enumerator.getNext().QueryInterface(Ci.nsIAccessible).name;
|
||||
}
|
||||
};
|
||||
|
||||
cellInfo.current = getAccessibleCell(aAccessible);
|
||||
|
||||
if (!cellInfo.current) {
|
||||
Logger.warning(aAccessible,
|
||||
'does not support nsIAccessibleTableCell interface.');
|
||||
this._cells.set(domNode, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
let table = cellInfo.current.table;
|
||||
if (table.isProbablyForLayout()) {
|
||||
this._cells.set(domNode, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
cellInfo.previous = null;
|
||||
let oldAncestry = this.oldAncestry.reverse();
|
||||
let ancestor = oldAncestry.shift();
|
||||
while (!cellInfo.previous && ancestor) {
|
||||
let cell = getAccessibleCell(ancestor);
|
||||
if (cell && cell.table === table) {
|
||||
cellInfo.previous = cell;
|
||||
}
|
||||
ancestor = oldAncestry.shift();
|
||||
}
|
||||
|
||||
if (cellInfo.previous) {
|
||||
cellInfo.rowChanged = cellInfo.current.rowIndex !==
|
||||
cellInfo.previous.rowIndex;
|
||||
cellInfo.columnChanged = cellInfo.current.columnIndex !==
|
||||
cellInfo.previous.columnIndex;
|
||||
} else {
|
||||
cellInfo.rowChanged = true;
|
||||
cellInfo.columnChanged = true;
|
||||
}
|
||||
|
||||
cellInfo.rowExtent = cellInfo.current.rowExtent;
|
||||
cellInfo.columnExtent = cellInfo.current.columnExtent;
|
||||
cellInfo.columnIndex = cellInfo.current.columnIndex;
|
||||
cellInfo.rowIndex = cellInfo.current.rowIndex;
|
||||
|
||||
cellInfo.columnHeaders = [];
|
||||
if (cellInfo.columnChanged && cellInfo.current.role !==
|
||||
Ci.nsIAccessibleRole.ROLE_COLUMNHEADER) {
|
||||
cellInfo.columnHeaders = [headers for (headers of getHeaders(
|
||||
cellInfo.current.columnHeaderCells))];
|
||||
}
|
||||
cellInfo.rowHeaders = [];
|
||||
if (cellInfo.rowChanged && cellInfo.current.role ===
|
||||
Ci.nsIAccessibleRole.ROLE_CELL) {
|
||||
cellInfo.rowHeaders = [headers for (headers of getHeaders(
|
||||
cellInfo.current.rowHeaderCells))];
|
||||
}
|
||||
|
||||
this._cells.set(domNode, cellInfo);
|
||||
return cellInfo;
|
||||
},
|
||||
|
||||
get bounds() {
|
||||
if (!this._bounds) {
|
||||
let objX = {}, objY = {}, objW = {}, objH = {};
|
||||
|
@ -93,7 +93,7 @@ function virtualCursorControl(aMessage) {
|
||||
sendAsyncMessage('AccessFu:VirtualCursor', aMessage.json);
|
||||
}
|
||||
} catch (x) {
|
||||
Logger.error(x);
|
||||
Logger.logException(x, 'Failed to move virtual cursor');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,9 +15,10 @@ MOCHITEST_A11Y_FILES =\
|
||||
jsatcommon.js \
|
||||
output.js \
|
||||
test_alive.html \
|
||||
test_explicit_names.html \
|
||||
test_utterance_order.html \
|
||||
test_braille.html \
|
||||
test_explicit_names.html \
|
||||
test_tables.html \
|
||||
test_utterance_order.html \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -37,7 +37,8 @@ function testContextOutput(expected, aAccOrElmOrID, aOldAccOrElmOrID, aGenerator
|
||||
*/
|
||||
function testObjectOutput(aAccOrElmOrID, aGenerator) {
|
||||
var accessible = getAccessible(aAccOrElmOrID);
|
||||
var output = aGenerator.genForObject(accessible);
|
||||
var context = new PivotContext(accessible);
|
||||
var output = aGenerator.genForObject(accessible, context);
|
||||
var outputOrder;
|
||||
try {
|
||||
outputOrder = SpecialPowers.getIntPref(PREF_UTTERANCE_ORDER);
|
||||
|
@ -54,9 +54,10 @@
|
||||
expected: ["list 2 items", "Test List", "Last item", "2.", "list two"]
|
||||
}, {
|
||||
accOrElmOrID: "cell",
|
||||
expected: ["table", "Fruits and vegetables", "List of Fruits",
|
||||
"list 4 items","First item", "link", "Apples", "link", "Bananas",
|
||||
"link", "Peaches", "Last item", "link", "Plums"]
|
||||
expected: ["table with 1 column and 1 row", "Fruits and vegetables",
|
||||
"Column 1 Row 1", "List of Fruits", "list 4 items", "First item",
|
||||
"link", "Apples", "link", "Bananas", "link", "Peaches", "Last item",
|
||||
"link", "Plums"]
|
||||
}, {
|
||||
accOrElmOrID: "app.net",
|
||||
expected: ["list 2 items", "First item", "link", "star", "Last item",
|
||||
@ -71,13 +72,12 @@
|
||||
// Test pivot to li_one from list.
|
||||
accOrElmOrID: "li_one",
|
||||
oldAccOrElmOrID: "list",
|
||||
expected: ["list 2 items", "Test List", "First item", "Top of the list"]
|
||||
expected: ["First item", "Top of the list"]
|
||||
}, {
|
||||
// Test pivot to "apples" link from the table cell.
|
||||
accOrElmOrID: "apples",
|
||||
oldAccOrElmOrID: "cell",
|
||||
expected: ["List of Fruits", "list 4 items", "First item", "link",
|
||||
"Apples"]
|
||||
expected: ["list 4 items", "First item", "link", "Apples"]
|
||||
}, {
|
||||
// Test pivot to the table cell from the "apples" link.
|
||||
accOrElmOrID: "cell",
|
||||
|
297
accessible/tests/mochitest/jsat/test_tables.html
Normal file
297
accessible/tests/mochitest/jsat/test_tables.html
Normal file
@ -0,0 +1,297 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>[AccessFu] Improve reading of table semantics</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="output.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function doTest() {
|
||||
// Test the following accOrElmOrID.
|
||||
var tests = [{
|
||||
accOrElmOrID: "table1",
|
||||
expectedUtterance: [["table with 2 columns and 2 rows",
|
||||
"Column 1 Row 1", "col1", "Column 2 Row 1", "col2",
|
||||
"Column 1 Row 2 col1", "cell1", "Column 2 Row 2 col2", "cell2"], [
|
||||
"col1", "Column 1 Row 1", "col2", "Column 2 Row 1", "cell1",
|
||||
"Column 1 Row 2 col1", "cell2", "Column 2 Row 2 col2",
|
||||
"table with 2 columns and 2 rows"]],
|
||||
expectedBraille: [["tbl 2c 2r", "c1r1", "col1", "c2r1", "col2",
|
||||
"c1r2 col1", "cell1", "c2r2 col2", "cell2"], ["col1", "c1r1", "col2",
|
||||
"c2r1", "cell1", "c1r2 col1", "cell2", "c2r2 col2", "tbl 2c 2r"]]
|
||||
}, {
|
||||
accOrElmOrID: "table2",
|
||||
expectedUtterance: [["table with 2 columns and 2 rows",
|
||||
"Column 1 Row 1 col1", "cell1", "Column 2 Row 1 col2",
|
||||
"table with 1 column and 2 rows", "Column 1 Row 1", "colheader",
|
||||
"Column 1 Row 2 colheader", "bla", "Column 1 Row 2", "col1",
|
||||
"Column 2 Row 2", "col2"], ["cell1", "Column 1 Row 1 col1",
|
||||
"colheader", "Column 1 Row 1", "bla", "Column 1 Row 2 colheader",
|
||||
"table with 1 column and 2 rows", "Column 2 Row 1 col2", "col1",
|
||||
"Column 1 Row 2", "col2", "Column 2 Row 2",
|
||||
"table with 2 columns and 2 rows"]],
|
||||
expectedBraille: [["tbl 2c 2r", "c1r1 col1", "cell1", "c2r1 col2",
|
||||
"tbl 1c 2r", "c1r1", "colheader", "c1r2 colheader", "bla", "c1r2",
|
||||
"col1", "c2r2", "col2"], ["cell1", "c1r1 col1", "colheader", "c1r1",
|
||||
"bla", "c1r2 colheader", "tbl 1c 2r", "c2r1 col2", "col1", "c1r2",
|
||||
"col2", "c2r2", "tbl 2c 2r"]]
|
||||
}, {
|
||||
accOrElmOrID: "table3",
|
||||
expectedUtterance: [["table with 2 columns and 2 rows",
|
||||
"Column 2 Row 1 col2", "table with 1 column and 2 rows",
|
||||
"Column 1 Row 1", "colheader", "Column 1 Row 2 colheader", "bla"], [
|
||||
"colheader", "Column 1 Row 1", "bla", "Column 1 Row 2 colheader",
|
||||
"table with 1 column and 2 rows", "Column 2 Row 1 col2",
|
||||
"table with 2 columns and 2 rows"]],
|
||||
expectedBraille: [["tbl 1c 2r", "c1r1", "colheader", "c1r2 colheader",
|
||||
"bla"], ["colheader", "c1r1", "bla", "c1r2 colheader", "tbl 1c 2r"]]
|
||||
}, {
|
||||
accOrElmOrID: "table4",
|
||||
expectedUtterance: [["table with 4 columns and 3 rows",
|
||||
"Column 1 Row 1", "col1", "Column 2 Row 1", "col2", "Column 3 Row 1",
|
||||
"col3", "Column 1 Row 2 spans 2 columns col1", "row1",
|
||||
"Column 3 Row 2 col3 row1", "cell1",
|
||||
"Column 4 Row 2 spans 2 rows row1", "cell2", "Column 1 Row 3 col1",
|
||||
"row2", "Column 2 Row 3 col2 row2", "cell3",
|
||||
"Column 3 Row 3 col3 row2", "cell4"], ["col1", "Column 1 Row 1",
|
||||
"col2", "Column 2 Row 1", "col3", "Column 3 Row 1", "row1",
|
||||
"Column 1 Row 2 spans 2 columns col1", "cell1",
|
||||
"Column 3 Row 2 col3 row1", "cell2",
|
||||
"Column 4 Row 2 spans 2 rows row1", "row2", "Column 1 Row 3 col1",
|
||||
"cell3", "Column 2 Row 3 col2 row2", "cell4",
|
||||
"Column 3 Row 3 col3 row2", "table with 4 columns and 3 rows"]],
|
||||
expectedBraille: [["tbl 4c 3r", "c1r1", "col1", "c2r1", "col2", "c3r1",
|
||||
"col3", "c1r2 col1", "row1", "c3r2 col3 row1", "cell1", "c4r2 row1",
|
||||
"cell2", "c1r3 col1", "row2", "c2r3 col2 row2", "cell3",
|
||||
"c3r3 col3 row2", "cell4"], ["col1", "c1r1", "col2", "c2r1", "col3",
|
||||
"c3r1", "row1", "c1r2 col1", "cell1", "c3r2 col3 row1", "cell2",
|
||||
"c4r2 row1", "row2", "c1r3 col1", "cell3", "c2r3 col2 row2", "cell4",
|
||||
"c3r3 col3 row2", "tbl 4c 3r"]]
|
||||
}, {
|
||||
accOrElmOrID: "table5",
|
||||
expectedUtterance: [["Row1", "Row2"], ["Row1", "Row2"]],
|
||||
expectedBraille: [["Row1", "Row2"], ["Row1", "Row2"]]
|
||||
}, {
|
||||
// Test pivot to table1_th1 from table1.
|
||||
accOrElmOrID: "table1_th1",
|
||||
oldAccOrElmOrID: "table1",
|
||||
expectedUtterance: [["Column 1 Row 1", "col1"], ["col1",
|
||||
"Column 1 Row 1"]],
|
||||
expectedBraille: [["c1r1", "col1"], ["col1", "c1r1"]]
|
||||
}, {
|
||||
// Test pivot to table1_td2 from table1.
|
||||
accOrElmOrID: "table1_td2",
|
||||
oldAccOrElmOrID: "table1",
|
||||
expectedUtterance: [["Column 2 Row 2 col2", "cell2"], ["cell2",
|
||||
"Column 2 Row 2 col2"]],
|
||||
expectedBraille: [["c2r2 col2", "cell2"], ["cell2", "c2r2 col2"]]
|
||||
}, {
|
||||
// Test pivot to table1_td2 from table1_th1.
|
||||
accOrElmOrID: "table1_td2",
|
||||
oldAccOrElmOrID: "table1_th1",
|
||||
expectedUtterance: [["Column 2 Row 2 col2", "cell2"], ["cell2",
|
||||
"Column 2 Row 2 col2"]],
|
||||
expectedBraille: [["c2r2 col2", "cell2"], ["cell2", "c2r2 col2"]]
|
||||
}, {
|
||||
// Test pivot to table1_td2 from table1_td1.
|
||||
accOrElmOrID: "table1_td2",
|
||||
oldAccOrElmOrID: "table1_td1",
|
||||
expectedUtterance: [["Column 2 col2", "cell2"], ["cell2",
|
||||
"Column 2 col2"]],
|
||||
expectedBraille: [["c2r2 col2", "cell2"], ["cell2", "c2r2 col2"]]
|
||||
}, {
|
||||
// Test pivot to table2_cell_1 from table2.
|
||||
accOrElmOrID: "table2_cell_1",
|
||||
oldAccOrElmOrID: "table2",
|
||||
expectedUtterance: [["Column 1 Row 1 col1", "cell1"], ["cell1",
|
||||
"Column 1 Row 1 col1"]],
|
||||
expectedBraille: [["c1r1 col1", "cell1"], ["cell1", "c1r1 col1"]]
|
||||
}, {
|
||||
// Test pivot to table2_cell_2 from table2.
|
||||
accOrElmOrID: "table2_cell_2",
|
||||
oldAccOrElmOrID: "table2",
|
||||
expectedUtterance: [["Column 2 Row 1 col2",
|
||||
"table with 1 column and 2 rows", "Column 1 Row 1", "colheader",
|
||||
"Column 1 Row 2 colheader", "bla"], ["colheader", "Column 1 Row 1",
|
||||
"bla", "Column 1 Row 2 colheader", "table with 1 column and 2 rows",
|
||||
"Column 2 Row 1 col2"]],
|
||||
expectedBraille: [["c2r1 col2", "tbl 1c 2r", "c1r1", "colheader",
|
||||
"c1r2 colheader", "bla"], ["colheader", "c1r1", "bla",
|
||||
"c1r2 colheader", "tbl 1c 2r", "c2r1 col2"]]
|
||||
}, {
|
||||
// Test pivot to table2_cell_1 from table2_cell_2.
|
||||
accOrElmOrID: "table2_cell_1",
|
||||
oldAccOrElmOrID: "table2_cell_2",
|
||||
expectedUtterance: [["Column 1 col1", "cell1"], ["cell1",
|
||||
"Column 1 col1"]],
|
||||
expectedBraille: [["c1r1 col1", "cell1"], ["cell1", "c1r1 col1"]]
|
||||
}, {
|
||||
// Test pivot to table3_cell from table2.
|
||||
accOrElmOrID: "table3_cell",
|
||||
oldAccOrElmOrID: "table2",
|
||||
expectedUtterance: [["Column 2 Row 1 col2",
|
||||
"table with 1 column and 2 rows", "Column 1 Row 2 colheader",
|
||||
"bla"], ["bla", "Column 1 Row 2 colheader",
|
||||
"table with 1 column and 2 rows", "Column 2 Row 1 col2"]],
|
||||
expectedBraille: [["c1r2 colheader", "bla"], ["bla", "c1r2 colheader"]]
|
||||
}, {
|
||||
// Test pivot to table3_cell from table2_cell_1.
|
||||
accOrElmOrID: "table3_cell",
|
||||
oldAccOrElmOrID: "table2_cell_1",
|
||||
expectedUtterance: [["Column 2 col2", "table with 1 column and 2 rows",
|
||||
"Column 1 Row 2 colheader", "bla"], ["bla",
|
||||
"Column 1 Row 2 colheader", "table with 1 column and 2 rows",
|
||||
"Column 2 Row 1 col2"]],
|
||||
expectedBraille: [["c1r2 colheader", "bla"], ["bla", "c1r2 colheader"]]
|
||||
}, {
|
||||
// Test pivot to table3_cell from table3_ch.
|
||||
accOrElmOrID: "table3_cell",
|
||||
oldAccOrElmOrID: "table3_ch",
|
||||
expectedUtterance: [["Row 2", "bla"], ["bla", "Row 2"]],
|
||||
expectedBraille: [["c1r2", "bla"], ["bla", "c1r2"]]
|
||||
}, {
|
||||
// Test pivot to table3_cell from table1_td1.
|
||||
accOrElmOrID: "table3_cell",
|
||||
oldAccOrElmOrID: "table1_td1",
|
||||
expectedUtterance: [["table with 2 columns and 2 rows",
|
||||
"Column 2 Row 1 col2", "table with 1 column and 2 rows",
|
||||
"Column 1 Row 2 colheader", "bla"], ["bla",
|
||||
"Column 1 Row 2 colheader", "table with 1 column and 2 rows",
|
||||
"Column 2 Row 1 col2", "table with 2 columns and 2 rows"]],
|
||||
expectedBraille: [["c1r2 colheader", "bla"], ["bla", "c1r2 colheader"]]
|
||||
}, {
|
||||
// Test pivot to table4_ch_3 from table4.
|
||||
accOrElmOrID: "table4_ch_3",
|
||||
oldAccOrElmOrID: "table4",
|
||||
expectedUtterance: [["Column 3 Row 1", "col3"], ["col3",
|
||||
"Column 3 Row 1"]],
|
||||
expectedBraille: [["c3r1", "col3"], ["col3", "c3r1"]]
|
||||
}, {
|
||||
// Test pivot to table4_rh_1 from table4_ch_3.
|
||||
accOrElmOrID: "table4_rh_1",
|
||||
oldAccOrElmOrID: "table4_ch_3",
|
||||
expectedUtterance: [["Column 1 Row 2 spans 2 columns col1", "row1"], [
|
||||
"row1", "Column 1 Row 2 spans 2 columns col1"]],
|
||||
expectedBraille: [["c1r2 col1", "row1"], ["row1", "c1r2 col1"]]
|
||||
}, {
|
||||
// Test pivot to table4_cell_3 from table4_rh_1.
|
||||
accOrElmOrID: "table4_cell_3",
|
||||
oldAccOrElmOrID: "table4_rh_1",
|
||||
expectedUtterance: [["Column 4 spans 2 rows", "cell2"], ["cell2",
|
||||
"Column 4 spans 2 rows"]],
|
||||
expectedBraille: [["c4r2", "cell2"], ["cell2", "c4r2"]]
|
||||
}, {
|
||||
// Test pivot to table4_cell_5 from table4_cell_3.
|
||||
accOrElmOrID: "table4_cell_5",
|
||||
oldAccOrElmOrID: "table4_cell_3",
|
||||
expectedUtterance: [["Column 2 Row 3 col2 row2", "cell3"], ["cell3",
|
||||
"Column 2 Row 3 col2 row2"]],
|
||||
expectedBraille: [["c2r3 col2 row2", "cell3"], ["cell3",
|
||||
"c2r3 col2 row2"]]
|
||||
}];
|
||||
|
||||
SpecialPowers.setIntPref(PREF_UTTERANCE_ORDER, 0);
|
||||
|
||||
// Test outputs (utterance and braille) for tables including their
|
||||
// headers and cells.
|
||||
tests.forEach(function run(test) {
|
||||
var outputOrderValues = [0, 1];
|
||||
outputOrderValues.forEach(function testOutputOrder(outputOrder) {
|
||||
SpecialPowers.setIntPref(PREF_UTTERANCE_ORDER, outputOrder);
|
||||
testOutput(test.expectedUtterance[outputOrder], test.accOrElmOrID,
|
||||
test.oldAccOrElmOrID, 1);
|
||||
testOutput(test.expectedBraille[outputOrder], test.accOrElmOrID,
|
||||
test.oldAccOrElmOrID, 0);
|
||||
});
|
||||
});
|
||||
|
||||
// If there was an original utterance order preference, revert to it.
|
||||
SpecialPowers.clearUserPref(PREF_UTTERANCE_ORDER);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root">
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=830748"
|
||||
title="[AccessFu] Improve reading of table semantics">
|
||||
Mozilla Bug 830748
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test"></pre>
|
||||
<table id="table1">
|
||||
<thead>
|
||||
<tr>
|
||||
<th id="table1_th1">col1</th>
|
||||
<th>col2</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td id="table1_td1">cell1</td>
|
||||
<td id="table1_td2">cell2</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table id="table2" border="1">
|
||||
<tr>
|
||||
<td id="table2_cell_1" headers="table2_ch_1">cell1</td>
|
||||
<td id="table2_cell_2" headers="table2_ch_2">
|
||||
<table id="table3">
|
||||
<thead>
|
||||
<tr>
|
||||
<th id="table3_ch">colheader</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td id="table3_cell">bla</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="table2_ch_1" scope="col">col1</td>
|
||||
<td id="table2_ch_2" scope="col">col2</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table id="table4" border="1">
|
||||
<thead>
|
||||
<tr>
|
||||
<th id="table4_ch_1">col1</th>
|
||||
<th id="table4_ch_2">col2</th>
|
||||
<td id="table4_ch_3" scope="col">col3</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th id="table4_rh_1" colspan="2">row1</th>
|
||||
<td id="table4_cell_2">cell1</td>
|
||||
<td id="table4_cell_3" rowspan="2">cell2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="table4_rh_2" scope="row">row2</td>
|
||||
<td id="table4_cell_5">cell3</td>
|
||||
<td id="table4_cell_6">cell4</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table id="table5">
|
||||
<tr><td>Row1</td></tr>
|
||||
<tr><td>Row2</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -57,13 +57,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=753984
|
||||
}, {
|
||||
accOrElmOrID: "cell",
|
||||
expected: [[
|
||||
"table", "Fruits and vegetables", "list 4 items", "First item",
|
||||
"link", "Apples", "link", "Bananas", "link", "Peaches",
|
||||
"Last item", "link", "Plums"
|
||||
"table with 1 column and 1 row", "Fruits and vegetables",
|
||||
"Column 1 Row 1", "list 4 items", "First item", "link", "Apples",
|
||||
"link", "Bananas", "link", "Peaches", "Last item", "link", "Plums"
|
||||
], [
|
||||
"Apples", "link", "First item", "Bananas", "link", "Peaches",
|
||||
"link", "Plums", "link", "Last item", "list 4 items",
|
||||
"Fruits and vegetables", "table"
|
||||
"Column 1 Row 1", "Fruits and vegetables",
|
||||
"table with 1 column and 1 row"
|
||||
]]
|
||||
}, {
|
||||
// Test pivot to list from li_one.
|
||||
|
@ -180,6 +180,11 @@
|
||||
label="&viewImageInfoCmd.label;"
|
||||
accesskey="&viewImageInfoCmd.accesskey;"
|
||||
oncommand="gContextMenu.viewImageInfo();"/>
|
||||
<menuitem id="context-viewimagedesc"
|
||||
label="&viewImageDescCmd.label;"
|
||||
accesskey="&viewImageDescCmd.accesskey;"
|
||||
oncommand="gContextMenu.viewImageDesc(event);"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="context-savevideo"
|
||||
label="&saveVideoCmd.label;"
|
||||
accesskey="&saveVideoCmd.accesskey;"
|
||||
|
@ -261,6 +261,7 @@ nsContextMenu.prototype = {
|
||||
.disabled = !this.hasBGImage;
|
||||
|
||||
this.showItem("context-viewimageinfo", this.onImage);
|
||||
this.showItem("context-viewimagedesc", this.onImage && this.imageDescURL !== "");
|
||||
},
|
||||
|
||||
initMiscItems: function CM_initMiscItems() {
|
||||
@ -499,6 +500,7 @@ nsContextMenu.prototype = {
|
||||
this.onImage = false;
|
||||
this.onLoadedImage = false;
|
||||
this.onCompletedImage = false;
|
||||
this.imageDescURL = "";
|
||||
this.onCanvas = false;
|
||||
this.onVideo = false;
|
||||
this.onAudio = false;
|
||||
@ -548,6 +550,11 @@ nsContextMenu.prototype = {
|
||||
this.onCompletedImage = true;
|
||||
|
||||
this.mediaURL = this.target.currentURI.spec;
|
||||
|
||||
var descURL = this.target.getAttribute("longdesc");
|
||||
if (descURL) {
|
||||
this.imageDescURL = makeURLAbsolute(this.target.ownerDocument.body.baseURI, descURL);
|
||||
}
|
||||
}
|
||||
else if (this.target instanceof HTMLCanvasElement) {
|
||||
this.onCanvas = true;
|
||||
@ -874,6 +881,14 @@ nsContextMenu.prototype = {
|
||||
"mediaTab", this.target);
|
||||
},
|
||||
|
||||
viewImageDesc: function(e) {
|
||||
var doc = this.target.ownerDocument;
|
||||
urlSecurityCheck(this.imageDescURL, this.browser.contentPrincipal,
|
||||
Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
|
||||
openUILink(this.imageDescURL, e, { disallowInheritPrincipal: true,
|
||||
referrerURI: doc.documentURIObject });
|
||||
},
|
||||
|
||||
viewFrameInfo: function() {
|
||||
BrowserPageInfo(this.target.ownerDocument);
|
||||
},
|
||||
|
@ -66,5 +66,6 @@ Browser context menu subtest.
|
||||
<input id="test-select-input-text" type="text" value="input">
|
||||
<input id="test-select-input-text-type-password" type="password" value="password">
|
||||
<embed id="test-plugin" style="width: 200px; height: 200px;" type="application/x-test"></embed>
|
||||
<img id="test-longdesc" src="ctxmenu-image.png" longdesc="http://www.mozilla.org"></embed>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -939,6 +939,22 @@ function runTest(testNum) {
|
||||
tag.enabledState = SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED;
|
||||
}
|
||||
}
|
||||
openContextMenuFor(longdesc);
|
||||
return;
|
||||
|
||||
case 30:
|
||||
// Context menu for an image with longdesc
|
||||
checkContextMenu(["context-viewimage", true,
|
||||
"context-copyimage-contents", true,
|
||||
"context-copyimage", true,
|
||||
"---", null,
|
||||
"context-saveimage", true,
|
||||
"context-sendimage", true,
|
||||
"context-setDesktopBackground", true,
|
||||
"context-viewimageinfo", true,
|
||||
"context-viewimagedesc", true
|
||||
].concat(inspectItems));
|
||||
closeContextMenu();
|
||||
|
||||
// finish test
|
||||
subwindow.close();
|
||||
@ -968,7 +984,7 @@ var text, link, mailto, input, img, canvas, video_ok, video_bad, video_bad2,
|
||||
iframe, video_in_iframe, image_in_iframe, textarea, contenteditable,
|
||||
inputspell, pagemenu, dom_full_screen, plainTextItems, audio_in_video,
|
||||
selecttext, selecttextlink, imagelink, select_inputtext, select_inputtext_password,
|
||||
plugin;
|
||||
plugin, longdesc;
|
||||
|
||||
function startTest() {
|
||||
chromeWin = SpecialPowers.wrap(subwindow)
|
||||
@ -1017,6 +1033,7 @@ function startTest() {
|
||||
select_inputtext = subwindow.document.getElementById("test-select-input-text");
|
||||
select_inputtext_password = subwindow.document.getElementById("test-select-input-text-type-password");
|
||||
plugin = subwindow.document.getElementById("test-plugin");
|
||||
longdesc = subwindow.document.getElementById("test-longdesc");
|
||||
|
||||
contextMenu.addEventListener("popupshown", function() { runTest(++testNum); }, false);
|
||||
runTest(1);
|
||||
|
@ -63,7 +63,7 @@ richlistitem[type="download"]:not([selected]) button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*** Visibility of download buttons and indicator controls. ***/
|
||||
/*** Visibility of download buttons ***/
|
||||
|
||||
.download-state:not(:-moz-any([state="-1"],/* Starting (initial) */
|
||||
[state="5"], /* Starting (queued) */
|
||||
@ -76,16 +76,7 @@ richlistitem[type="download"]:not([selected]) button {
|
||||
.downloadRetry,
|
||||
|
||||
.download-state:not( [state="1"] /* Finished */)
|
||||
.downloadShow,
|
||||
|
||||
#downloads-indicator:-moz-any([progress],
|
||||
[counter],
|
||||
[paused]) #downloads-indicator-icon,
|
||||
|
||||
#downloads-indicator:not(:-moz-any([progress],
|
||||
[counter],
|
||||
[paused]))
|
||||
#downloads-indicator-progress-area
|
||||
.downloadShow
|
||||
|
||||
{
|
||||
visibility: hidden;
|
||||
@ -103,21 +94,3 @@ richlistitem[type="download"]:not([selected]) button {
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Hacks for toolbar full and text modes, until bug 573329 removes them */
|
||||
|
||||
toolbar[mode="text"] > #downloads-indicator {
|
||||
display: -moz-box;
|
||||
-moz-box-orient: vertical;
|
||||
-moz-box-pack: center;
|
||||
}
|
||||
|
||||
toolbar[mode="text"] > #downloads-indicator > .toolbarbutton-text {
|
||||
-moz-box-ordinal-group: 1;
|
||||
}
|
||||
|
||||
toolbar[mode="text"] > #downloads-indicator > .toolbarbutton-icon {
|
||||
display: -moz-box;
|
||||
-moz-box-ordinal-group: 2;
|
||||
visibility: collapse;
|
||||
}
|
||||
|
36
browser/components/downloads/content/indicator.css
Normal file
36
browser/components/downloads/content/indicator.css
Normal file
@ -0,0 +1,36 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*** Visibility of indicator controls ***/
|
||||
|
||||
#downloads-indicator:-moz-any([progress],
|
||||
[counter],
|
||||
[paused]) #downloads-indicator-icon,
|
||||
|
||||
#downloads-indicator:not(:-moz-any([progress],
|
||||
[counter],
|
||||
[paused]))
|
||||
#downloads-indicator-progress-area
|
||||
|
||||
{
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
/* Hacks for toolbar full and text modes, until bug 573329 removes them */
|
||||
|
||||
toolbar[mode="text"] > #downloads-indicator {
|
||||
display: -moz-box;
|
||||
-moz-box-orient: vertical;
|
||||
-moz-box-pack: center;
|
||||
}
|
||||
|
||||
toolbar[mode="text"] > #downloads-indicator > .toolbarbutton-text {
|
||||
-moz-box-ordinal-group: 1;
|
||||
}
|
||||
|
||||
toolbar[mode="text"] > #downloads-indicator > .toolbarbutton-icon {
|
||||
display: -moz-box;
|
||||
-moz-box-ordinal-group: 2;
|
||||
visibility: collapse;
|
||||
}
|
@ -6,8 +6,8 @@
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
- You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://browser/content/downloads/downloads.css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/downloads/downloads.css"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/downloads/indicator.css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/downloads/indicator.css"?>
|
||||
|
||||
<!DOCTYPE overlay [
|
||||
<!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd" >
|
||||
|
@ -8,6 +8,7 @@ browser.jar:
|
||||
content/browser/downloads/downloads.css (content/downloads.css)
|
||||
* content/browser/downloads/downloads.js (content/downloads.js)
|
||||
* content/browser/downloads/downloadsOverlay.xul (content/downloadsOverlay.xul)
|
||||
content/browser/downloads/indicator.css (content/indicator.css)
|
||||
content/browser/downloads/indicator.js (content/indicator.js)
|
||||
content/browser/downloads/indicatorOverlay.xul (content/indicatorOverlay.xul)
|
||||
* content/browser/downloads/allDownloadsViewOverlay.xul (content/allDownloadsViewOverlay.xul)
|
||||
|
@ -408,6 +408,8 @@ These should match what Safari and other Apple applications use on OS X Lion. --
|
||||
<!ENTITY viewImageCmd.accesskey "I">
|
||||
<!ENTITY viewImageInfoCmd.label "View Image Info">
|
||||
<!ENTITY viewImageInfoCmd.accesskey "f">
|
||||
<!ENTITY viewImageDescCmd.label "View Description">
|
||||
<!ENTITY viewImageDescCmd.accesskey "D">
|
||||
<!ENTITY viewVideoCmd.label "View Video">
|
||||
<!ENTITY viewVideoCmd.accesskey "I">
|
||||
<!ENTITY viewBGImageCmd.label "View Background Image">
|
||||
|
334
browser/metro/base/content/ContextUI.js
Normal file
334
browser/metro/base/content/ContextUI.js
Normal file
@ -0,0 +1,334 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Fired when any context ui is displayed
|
||||
const kContextUIShowEvent = "MozContextUIShow";
|
||||
// Fired when any context ui is dismissed
|
||||
const kContextUIDismissEvent = "MozContextUIDismiss";
|
||||
// Fired when the tabtray is displayed
|
||||
const kContextUITabsShowEvent = "MozContextUITabsShow";
|
||||
// add more as needed...
|
||||
|
||||
// delay for ContextUI's dismissWithDelay
|
||||
const kHideContextAndTrayDelayMsec = 3000;
|
||||
|
||||
// delay when showing the tab bar briefly as a new tab opens
|
||||
const kNewTabAnimationDelayMsec = 1000;
|
||||
|
||||
/*
|
||||
* Manages context UI (navbar, tabbar, appbar) and track visibility. Also
|
||||
* tracks events that summon and hide the context UI.
|
||||
*/
|
||||
var ContextUI = {
|
||||
_expandable: true,
|
||||
_hidingId: 0,
|
||||
|
||||
/*******************************************
|
||||
* init
|
||||
*/
|
||||
|
||||
init: function init() {
|
||||
Elements.browsers.addEventListener("mousedown", this, true);
|
||||
Elements.browsers.addEventListener("touchstart", this, true);
|
||||
Elements.browsers.addEventListener("AlertActive", this, true);
|
||||
|
||||
Elements.browsers.addEventListener('URLChanged', this, true);
|
||||
Elements.tabList.addEventListener('TabSelect', this, true);
|
||||
Elements.panelUI.addEventListener('ToolPanelShown', this, false);
|
||||
Elements.panelUI.addEventListener('ToolPanelHidden', this, false);
|
||||
|
||||
window.addEventListener("MozEdgeUIStarted", this, true);
|
||||
window.addEventListener("MozEdgeUICanceled", this, true);
|
||||
window.addEventListener("MozEdgeUICompleted", this, true);
|
||||
window.addEventListener("keypress", this, true);
|
||||
window.addEventListener("KeyboardChanged", this, false);
|
||||
|
||||
Elements.tray.addEventListener("transitionend", this, true);
|
||||
|
||||
Appbar.init();
|
||||
},
|
||||
|
||||
/*******************************************
|
||||
* Context UI state getters & setters
|
||||
*/
|
||||
|
||||
// any visiblilty
|
||||
get isVisible() {
|
||||
return this.navbarVisible || this.tabbarVisible || this.contextAppbarVisible;
|
||||
},
|
||||
|
||||
// navbar visiblilty
|
||||
get navbarVisible() {
|
||||
return (Elements.navbar.hasAttribute("visible") ||
|
||||
Elements.navbar.hasAttribute("startpage"));
|
||||
},
|
||||
|
||||
// tabbar visiblilty
|
||||
get tabbarVisible() {
|
||||
return Elements.tray.hasAttribute("expanded");
|
||||
},
|
||||
|
||||
// appbar visiblilty
|
||||
get contextAppbarVisible() {
|
||||
return Elements.contextappbar.isShowing;
|
||||
},
|
||||
|
||||
// currently not in use, for the always show tabs feature
|
||||
get isExpandable() { return this._expandable; },
|
||||
set isExpandable(aFlag) {
|
||||
this._expandable = aFlag;
|
||||
if (!this._expandable)
|
||||
this.dismiss();
|
||||
},
|
||||
|
||||
/*******************************************
|
||||
* Public api
|
||||
*/
|
||||
|
||||
/*
|
||||
* Toggle the current nav UI state. Fires context ui events.
|
||||
*/
|
||||
toggleNavUI: function () {
|
||||
// The navbar is forced open when the start page is visible. appbar.js
|
||||
// controls the "visible" property, and browser-ui controls the "startpage"
|
||||
// property. Hence we rely on the tabbar for current toggle state.
|
||||
if (this.tabbarVisible) {
|
||||
this.dismiss();
|
||||
} else {
|
||||
this.displayNavUI();
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Show the nav and tabs bar. Returns true if any non-visible UI
|
||||
* was shown. Fires context ui events.
|
||||
*/
|
||||
displayNavUI: function () {
|
||||
let shown = false;
|
||||
|
||||
if (!this.navbarVisible) {
|
||||
this.displayNavbar();
|
||||
shown = true;
|
||||
}
|
||||
|
||||
if (!this.tabbarVisible) {
|
||||
this.displayTabs();
|
||||
shown = true;
|
||||
}
|
||||
|
||||
if (shown) {
|
||||
ContentAreaObserver.update(window.innerWidth, window.innerHeight);
|
||||
this._fire(kContextUIShowEvent);
|
||||
}
|
||||
|
||||
return shown;
|
||||
},
|
||||
|
||||
/*
|
||||
* Dismiss any context UI currently visible. Returns true if any
|
||||
* visible UI was dismissed. Fires context ui events.
|
||||
*/
|
||||
dismiss: function () {
|
||||
let dismissed = false;
|
||||
|
||||
this._clearDelayedTimeout();
|
||||
|
||||
// No assurances this will hide the nav bar. It may have the
|
||||
// 'startpage' property set. This removes the 'visible' property.
|
||||
if (this.navbarVisible) {
|
||||
this.dismissNavbar();
|
||||
dismissed = true;
|
||||
}
|
||||
if (this.tabbarVisible) {
|
||||
this.dismissTabs();
|
||||
dismissed = true;
|
||||
}
|
||||
if (Elements.contextappbar.isShowing) {
|
||||
this.dismissContextAppbar();
|
||||
dismissed = true;
|
||||
}
|
||||
|
||||
if (dismissed) {
|
||||
ContentAreaObserver.update(window.innerWidth, window.innerHeight);
|
||||
this._fire(kContextUIDismissEvent);
|
||||
}
|
||||
|
||||
return dismissed;
|
||||
},
|
||||
|
||||
/*
|
||||
* Briefly show the tab bar and then hide it. Fires context ui events.
|
||||
*/
|
||||
peekTabs: function peekTabs() {
|
||||
if (this.tabbarVisible) {
|
||||
setTimeout(function () {
|
||||
ContextUI.dismissWithDelay(kNewTabAnimationDelayMsec);
|
||||
}, 0);
|
||||
} else {
|
||||
BrowserUI.setOnTabAnimationEnd(function () {
|
||||
ContextUI.dismissWithDelay(kNewTabAnimationDelayMsec);
|
||||
});
|
||||
this.displayTabs();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* Dismiss all context ui after a delay. Fires context ui events.
|
||||
*/
|
||||
dismissWithDelay: function dismissWithDelay(aDelay) {
|
||||
aDelay = aDelay || kHideContextAndTrayDelayMsec;
|
||||
this._clearDelayedTimeout();
|
||||
this._hidingId = setTimeout(function () {
|
||||
ContextUI.dismiss();
|
||||
}, aDelay);
|
||||
},
|
||||
|
||||
// Cancel any pending delayed dismiss
|
||||
cancelDismiss: function cancelDismiss() {
|
||||
this._clearDelayedTimeout();
|
||||
},
|
||||
|
||||
// Display the nav bar
|
||||
displayNavbar: function () {
|
||||
this._clearDelayedTimeout();
|
||||
Elements.navbar.show();
|
||||
},
|
||||
|
||||
// Display the tab tray
|
||||
displayTabs: function () {
|
||||
this._clearDelayedTimeout();
|
||||
this._setIsExpanded(true);
|
||||
},
|
||||
|
||||
// Display the app bar
|
||||
displayContextAppbar: function () {
|
||||
this._clearDelayedTimeout();
|
||||
Elements.contextappbar.show();
|
||||
},
|
||||
|
||||
// Dismiss the navbar if visible.
|
||||
dismissNavbar: function dismissNavbar() {
|
||||
Elements.navbar.dismiss();
|
||||
},
|
||||
|
||||
// Dismiss the tabstray if visible.
|
||||
dismissTabs: function dimissTabs() {
|
||||
this._clearDelayedTimeout();
|
||||
this._setIsExpanded(false);
|
||||
},
|
||||
|
||||
// Dismiss the appbar if visible.
|
||||
dismissContextAppbar: function dismissContextAppbar() {
|
||||
Elements.contextappbar.dismiss();
|
||||
},
|
||||
|
||||
/*******************************************
|
||||
* Internal utils
|
||||
*/
|
||||
|
||||
// tabtray state
|
||||
_setIsExpanded: function _setIsExpanded(aFlag, setSilently) {
|
||||
// if the tray can't be expanded, don't expand it.
|
||||
if (!this.isExpandable || this.tabbarVisible == aFlag)
|
||||
return;
|
||||
|
||||
if (aFlag)
|
||||
Elements.tray.setAttribute("expanded", "true");
|
||||
else
|
||||
Elements.tray.removeAttribute("expanded");
|
||||
|
||||
if (!setSilently)
|
||||
this._fire(kContextUITabsShowEvent);
|
||||
},
|
||||
|
||||
_clearDelayedTimeout: function _clearDelayedTimeout() {
|
||||
if (this._hidingId) {
|
||||
clearTimeout(this._hidingId);
|
||||
this._hidingId = 0;
|
||||
}
|
||||
},
|
||||
|
||||
/*******************************************
|
||||
* Events
|
||||
*/
|
||||
|
||||
_onEdgeUIStarted: function(aEvent) {
|
||||
this._hasEdgeSwipeStarted = true;
|
||||
this._clearDelayedTimeout();
|
||||
|
||||
if (StartUI.hide()) {
|
||||
this.dismiss();
|
||||
return;
|
||||
}
|
||||
this.toggleNavUI();
|
||||
},
|
||||
|
||||
_onEdgeUICanceled: function(aEvent) {
|
||||
this._hasEdgeSwipeStarted = false;
|
||||
StartUI.hide();
|
||||
this.dismiss();
|
||||
},
|
||||
|
||||
_onEdgeUICompleted: function(aEvent) {
|
||||
if (this._hasEdgeSwipeStarted) {
|
||||
this._hasEdgeSwipeStarted = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this._clearDelayedTimeout();
|
||||
if (StartUI.hide()) {
|
||||
this.dismiss();
|
||||
return;
|
||||
}
|
||||
this.toggleNavUI();
|
||||
},
|
||||
|
||||
handleEvent: function handleEvent(aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case "MozEdgeUIStarted":
|
||||
this._onEdgeUIStarted(aEvent);
|
||||
break;
|
||||
case "MozEdgeUICanceled":
|
||||
this._onEdgeUICanceled(aEvent);
|
||||
break;
|
||||
case "MozEdgeUICompleted":
|
||||
this._onEdgeUICompleted(aEvent);
|
||||
break;
|
||||
case "keypress":
|
||||
if (String.fromCharCode(aEvent.which) == "z" &&
|
||||
aEvent.getModifierState("Win"))
|
||||
this.toggleNavUI();
|
||||
break;
|
||||
case "transitionend":
|
||||
setTimeout(function () {
|
||||
ContentAreaObserver.updateContentArea();
|
||||
}, 0);
|
||||
break;
|
||||
case "KeyboardChanged":
|
||||
this.dismissTabs();
|
||||
break;
|
||||
case "mousedown":
|
||||
if (aEvent.button == 0 && this.isVisible)
|
||||
this.dismiss();
|
||||
break;
|
||||
case 'URLChanged':
|
||||
this.dismissTabs();
|
||||
break;
|
||||
case 'TabSelect':
|
||||
case 'ToolPanelShown':
|
||||
case 'ToolPanelHidden':
|
||||
case "touchstart":
|
||||
case "AlertActive":
|
||||
this.dismiss();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_fire: function (name) {
|
||||
let event = document.createEvent("Events");
|
||||
event.initEvent(name, true, true);
|
||||
window.dispatchEvent(event);
|
||||
}
|
||||
};
|
@ -12,16 +12,16 @@ var Appbar = {
|
||||
activeTileset: null,
|
||||
|
||||
init: function Appbar_init() {
|
||||
window.addEventListener('MozContextUIShow', this);
|
||||
window.addEventListener('MozContextUIDismiss', this);
|
||||
window.addEventListener('MozAppbarDismiss', this);
|
||||
// fired from appbar bindings
|
||||
Elements.contextappbar.addEventListener('MozAppbarShowing', this, false);
|
||||
Elements.contextappbar.addEventListener('MozAppbarDismissing', this, false);
|
||||
|
||||
// fired when a context sensitive item (bookmarks) changes state
|
||||
window.addEventListener('MozContextActionsChange', this, false);
|
||||
|
||||
// browser events we need to update button state on
|
||||
Elements.browsers.addEventListener('URLChanged', this, true);
|
||||
Elements.tabList.addEventListener('TabSelect', this, true);
|
||||
Elements.panelUI.addEventListener('ToolPanelShown', this, false);
|
||||
Elements.panelUI.addEventListener('ToolPanelHidden', this, false);
|
||||
|
||||
// tilegroup selection events for all modules get bubbled up
|
||||
window.addEventListener("selectionchange", this, false);
|
||||
@ -31,22 +31,10 @@ var Appbar = {
|
||||
switch (aEvent.type) {
|
||||
case 'URLChanged':
|
||||
case 'TabSelect':
|
||||
this.update();
|
||||
Elements.navbar.dismiss();
|
||||
Elements.contextappbar.dismiss();
|
||||
break;
|
||||
case 'MozContextUIShow':
|
||||
Elements.navbar.show();
|
||||
break;
|
||||
case 'MozAppbarDismiss':
|
||||
case 'MozContextUIDismiss':
|
||||
case 'ToolPanelShown':
|
||||
case 'ToolPanelHidden':
|
||||
Elements.navbar.dismiss();
|
||||
Elements.contextappbar.dismiss();
|
||||
break;
|
||||
case 'MozAppbarShowing':
|
||||
this.update();
|
||||
break;
|
||||
|
||||
case 'MozAppbarDismissing':
|
||||
if (this.activeTileset) {
|
||||
this.activeTileset.clearSelection();
|
||||
@ -54,11 +42,13 @@ var Appbar = {
|
||||
this.clearContextualActions();
|
||||
this.activeTileset = null;
|
||||
break;
|
||||
|
||||
case 'MozContextActionsChange':
|
||||
let actions = aEvent.actions;
|
||||
// could transition in old, new buttons?
|
||||
this.showContextualActions(actions);
|
||||
break;
|
||||
|
||||
case "selectionchange":
|
||||
let nodeName = aEvent.target.nodeName;
|
||||
if ('richgrid' === nodeName) {
|
||||
|
@ -28,7 +28,7 @@
|
||||
<![CDATA[
|
||||
window.addEventListener('MozContextUIShow', this);
|
||||
window.addEventListener('MozContextUIDismiss', this);
|
||||
window.addEventListener('MozAppbarDismiss', this);
|
||||
window.addEventListener('MozAppbarDismissing', this);
|
||||
]]>
|
||||
</constructor>
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
<![CDATA[
|
||||
window.removeEventListener('MozContextUIShow', this);
|
||||
window.removeEventListener('MozContextUIDismiss', this);
|
||||
window.removeEventListener('MozAppbarDismiss', this);
|
||||
window.removeEventListener('MozAppbarDismissing', this);
|
||||
]]>
|
||||
</destructor>
|
||||
|
||||
@ -92,7 +92,7 @@
|
||||
<![CDATA[
|
||||
switch (aEvent.type) {
|
||||
case 'MozContextUIShow':
|
||||
case 'MozAppbarDismiss':
|
||||
case 'MozAppbarDismissing':
|
||||
case 'MozContextUIDismiss':
|
||||
this.hide();
|
||||
break;
|
||||
|
@ -114,13 +114,13 @@
|
||||
<implementation implements="nsIDOMEventListener">
|
||||
<constructor>
|
||||
<![CDATA[
|
||||
window.addEventListener("MozContextUIExpand", this, true);
|
||||
window.addEventListener("MozContextUITabsShow", this, true);
|
||||
]]>
|
||||
</constructor>
|
||||
|
||||
<destructor>
|
||||
<![CDATA[
|
||||
window.removeEventListener("MozContextUIExpand", this, true);
|
||||
window.removeEventListener("MozContextUITabsShow", this, true);
|
||||
]]>
|
||||
</destructor>
|
||||
|
||||
@ -129,7 +129,7 @@
|
||||
<body>
|
||||
<![CDATA[
|
||||
switch (event.type) {
|
||||
case "MozContextUIExpand":
|
||||
case "MozContextUITabsShow":
|
||||
this.strip.ensureElementIsVisible(this.selectedTab, false);
|
||||
break;
|
||||
}
|
||||
|
@ -136,6 +136,7 @@ let ScriptContexts = {};
|
||||
["SSLExceptions", "chrome://browser/content/exceptions.js"],
|
||||
["ItemPinHelper", "chrome://browser/content/helperui/ItemPinHelper.js"],
|
||||
["NavButtonSlider", "chrome://browser/content/NavButtonSlider.js"],
|
||||
["ContextUI", "chrome://browser/content/ContextUI.js"],
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
["Sync", "chrome://browser/content/sync.js"],
|
||||
["SyncPairDevice", "chrome://browser/content/sync.js"],
|
||||
|
@ -4,6 +4,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
Cu.import("resource://gre/modules/PageThumbs.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/dbg-server.jsm")
|
||||
|
||||
/**
|
||||
* Constants
|
||||
@ -14,13 +15,6 @@ Cu.import("resource://gre/modules/PageThumbs.jsm");
|
||||
const TOOLBARSTATE_LOADING = 1;
|
||||
const TOOLBARSTATE_LOADED = 2;
|
||||
|
||||
// delay for ContextUI's dismissWithDelay
|
||||
const kHideContextAndTrayDelayMsec = 3000;
|
||||
|
||||
// delay when showing the tab bar briefly as a new tab opens
|
||||
const kNewTabAnimationDelayMsec = 500;
|
||||
|
||||
|
||||
// Page for which the start UI is shown
|
||||
const kStartOverlayURI = "about:start";
|
||||
|
||||
@ -448,7 +442,7 @@ var BrowserUI = {
|
||||
animateClosingTab: function animateClosingTab(tabToClose) {
|
||||
tabToClose.chromeTab.setAttribute("closing", "true");
|
||||
|
||||
let wasCollapsed = !ContextUI.isExpanded;
|
||||
let wasCollapsed = !ContextUI.tabbarVisible;
|
||||
if (wasCollapsed) {
|
||||
ContextUI.displayTabs();
|
||||
}
|
||||
@ -1254,7 +1248,7 @@ var BrowserUI = {
|
||||
this._editURI(true);
|
||||
break;
|
||||
case "cmd_addBookmark":
|
||||
Elements.navbar.show();
|
||||
ContextUI.displayNavbar();
|
||||
Appbar.onStarButton(true);
|
||||
break;
|
||||
case "cmd_bookmarks":
|
||||
@ -1319,266 +1313,6 @@ var BrowserUI = {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tracks whether context UI (app bar, tab bar, url bar) is shown or hidden.
|
||||
* Manages events to summon and hide the context UI.
|
||||
*/
|
||||
var ContextUI = {
|
||||
_expandable: true,
|
||||
_hidingId: 0,
|
||||
|
||||
/*******************************************
|
||||
* init
|
||||
*/
|
||||
|
||||
init: function init() {
|
||||
Elements.browsers.addEventListener("mousedown", this, true);
|
||||
Elements.browsers.addEventListener("touchstart", this, true);
|
||||
Elements.browsers.addEventListener("AlertActive", this, true);
|
||||
window.addEventListener("MozEdgeUIStarted", this, true);
|
||||
window.addEventListener("MozEdgeUICanceled", this, true);
|
||||
window.addEventListener("MozEdgeUICompleted", this, true);
|
||||
window.addEventListener("keypress", this, true);
|
||||
window.addEventListener("KeyboardChanged", this, false);
|
||||
|
||||
Elements.tray.addEventListener("transitionend", this, true);
|
||||
|
||||
Appbar.init();
|
||||
},
|
||||
|
||||
/*******************************************
|
||||
* Context UI state getters & setters
|
||||
*/
|
||||
|
||||
get isVisible() {
|
||||
return (Elements.navbar.hasAttribute("visible") ||
|
||||
Elements.navbar.hasAttribute("startpage"));
|
||||
},
|
||||
get isExpanded() { return Elements.tray.hasAttribute("expanded"); },
|
||||
get isExpandable() { return this._expandable; },
|
||||
|
||||
set isExpandable(aFlag) {
|
||||
this._expandable = aFlag;
|
||||
if (!this._expandable)
|
||||
this.dismiss();
|
||||
},
|
||||
|
||||
/*******************************************
|
||||
* Context UI state control
|
||||
*/
|
||||
|
||||
toggle: function toggle() {
|
||||
if (!this._expandable) {
|
||||
// exandable setter takes care of resetting state
|
||||
// so if we're not expandable, there's nothing to do here
|
||||
return;
|
||||
}
|
||||
// if we're not showing, show
|
||||
if (!this.dismiss()) {
|
||||
dump("* ContextUI is hidden, show it\n");
|
||||
this.show();
|
||||
}
|
||||
},
|
||||
|
||||
// show all context UI
|
||||
// returns true if any non-visible UI was shown
|
||||
show: function() {
|
||||
let shown = false;
|
||||
if (!this.isExpanded) {
|
||||
// show the tab tray
|
||||
this._setIsExpanded(true);
|
||||
shown = true;
|
||||
}
|
||||
if (!Elements.navbar.isShowing) {
|
||||
// show the navbar
|
||||
Elements.navbar.show();
|
||||
shown = true;
|
||||
}
|
||||
|
||||
this._clearDelayedTimeout();
|
||||
if (shown) {
|
||||
ContentAreaObserver.update(window.innerWidth, window.innerHeight);
|
||||
}
|
||||
return shown;
|
||||
},
|
||||
|
||||
// Display the nav bar
|
||||
displayNavbar: function displayNavbar() {
|
||||
this._clearDelayedTimeout();
|
||||
Elements.navbar.show();
|
||||
},
|
||||
|
||||
// Display the toolbar and tabs
|
||||
displayTabs: function displayTabs() {
|
||||
this._clearDelayedTimeout();
|
||||
this._setIsExpanded(true, true);
|
||||
},
|
||||
|
||||
/** Briefly show the tab bar and then hide it */
|
||||
peekTabs: function peekTabs() {
|
||||
if (this.isExpanded) {
|
||||
setTimeout(function () {
|
||||
ContextUI.dismissWithDelay(kNewTabAnimationDelayMsec);
|
||||
}, 0);
|
||||
} else {
|
||||
BrowserUI.setOnTabAnimationEnd(function () {
|
||||
ContextUI.dismissWithDelay(kNewTabAnimationDelayMsec);
|
||||
});
|
||||
|
||||
this.displayTabs();
|
||||
}
|
||||
},
|
||||
|
||||
// Dismiss all context UI.
|
||||
// Returns true if any visible UI was dismissed.
|
||||
dismiss: function dismiss() {
|
||||
let dismissed = false;
|
||||
if (this.isExpanded) {
|
||||
this._setIsExpanded(false);
|
||||
dismissed = true;
|
||||
}
|
||||
if (Elements.navbar.isShowing) {
|
||||
this.dismissAppbar();
|
||||
dismissed = true;
|
||||
}
|
||||
this._clearDelayedTimeout();
|
||||
if (dismissed) {
|
||||
ContentAreaObserver.update(window.innerWidth, window.innerHeight);
|
||||
}
|
||||
return dismissed;
|
||||
},
|
||||
|
||||
// Dismiss all context ui after a delay
|
||||
dismissWithDelay: function dismissWithDelay(aDelay) {
|
||||
aDelay = aDelay || kHideContextAndTrayDelayMsec;
|
||||
this._clearDelayedTimeout();
|
||||
this._hidingId = setTimeout(function () {
|
||||
ContextUI.dismiss();
|
||||
}, aDelay);
|
||||
},
|
||||
|
||||
// Cancel any pending delayed dismiss
|
||||
cancelDismiss: function cancelDismiss() {
|
||||
this._clearDelayedTimeout();
|
||||
},
|
||||
|
||||
dismissTabs: function dimissTabs() {
|
||||
this._clearDelayedTimeout();
|
||||
this._setIsExpanded(false, true);
|
||||
},
|
||||
|
||||
dismissAppbar: function dismissAppbar() {
|
||||
this._fire("MozAppbarDismiss");
|
||||
},
|
||||
|
||||
/*******************************************
|
||||
* Internal tray state setters
|
||||
*/
|
||||
|
||||
// tab tray state
|
||||
_setIsExpanded: function _setIsExpanded(aFlag, setSilently) {
|
||||
// if the tray can't be expanded, don't expand it.
|
||||
if (!this.isExpandable || this.isExpanded == aFlag)
|
||||
return;
|
||||
|
||||
if (aFlag)
|
||||
Elements.tray.setAttribute("expanded", "true");
|
||||
else
|
||||
Elements.tray.removeAttribute("expanded");
|
||||
|
||||
if (!setSilently)
|
||||
this._fire("MozContextUIExpand");
|
||||
},
|
||||
|
||||
/*******************************************
|
||||
* Internal utils
|
||||
*/
|
||||
|
||||
_clearDelayedTimeout: function _clearDelayedTimeout() {
|
||||
if (this._hidingId) {
|
||||
clearTimeout(this._hidingId);
|
||||
this._hidingId = 0;
|
||||
}
|
||||
},
|
||||
|
||||
/*******************************************
|
||||
* Events
|
||||
*/
|
||||
|
||||
_onEdgeUIStarted: function(aEvent) {
|
||||
this._hasEdgeSwipeStarted = true;
|
||||
this._clearDelayedTimeout();
|
||||
|
||||
if (StartUI.hide()) {
|
||||
this.dismiss();
|
||||
return;
|
||||
}
|
||||
this.toggle();
|
||||
},
|
||||
|
||||
_onEdgeUICanceled: function(aEvent) {
|
||||
this._hasEdgeSwipeStarted = false;
|
||||
StartUI.hide();
|
||||
this.dismiss();
|
||||
},
|
||||
|
||||
_onEdgeUICompleted: function(aEvent) {
|
||||
if (this._hasEdgeSwipeStarted) {
|
||||
this._hasEdgeSwipeStarted = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this._clearDelayedTimeout();
|
||||
if (StartUI.hide()) {
|
||||
this.dismiss();
|
||||
return;
|
||||
}
|
||||
this.toggle();
|
||||
},
|
||||
|
||||
handleEvent: function handleEvent(aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case "MozEdgeUIStarted":
|
||||
this._onEdgeUIStarted(aEvent);
|
||||
break;
|
||||
case "MozEdgeUICanceled":
|
||||
this._onEdgeUICanceled(aEvent);
|
||||
break;
|
||||
case "MozEdgeUICompleted":
|
||||
this._onEdgeUICompleted(aEvent);
|
||||
break;
|
||||
case "mousedown":
|
||||
if (aEvent.button == 0 && this.isVisible)
|
||||
this.dismiss();
|
||||
break;
|
||||
case "touchstart":
|
||||
// ContextUI can hide the notification bar. Workaround until bug 845348 is fixed.
|
||||
case "AlertActive":
|
||||
this.dismiss();
|
||||
break;
|
||||
case "keypress":
|
||||
if (String.fromCharCode(aEvent.which) == "z" &&
|
||||
aEvent.getModifierState("Win"))
|
||||
this.toggle();
|
||||
break;
|
||||
case "transitionend":
|
||||
setTimeout(function () {
|
||||
ContentAreaObserver.updateContentArea();
|
||||
}, 0);
|
||||
break;
|
||||
case "KeyboardChanged":
|
||||
this.dismissTabs();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_fire: function (name) {
|
||||
let event = document.createEvent("Events");
|
||||
event.initEvent(name, true, true);
|
||||
window.dispatchEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
var StartUI = {
|
||||
get isVisible() { return this.isStartPageVisible || this.isFiltering; },
|
||||
get isStartPageVisible() { return Elements.windowState.hasAttribute("startpage"); },
|
||||
@ -1608,6 +1342,13 @@ var StartUI = {
|
||||
if (section.init)
|
||||
section.init();
|
||||
});
|
||||
|
||||
if (!DebuggerServer.initialized) {
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.addBrowserActors();
|
||||
DebuggerServer.addActors('chrome://browser/content/dbg-metro-actors.js');
|
||||
}
|
||||
DebuggerServer.openListener(6000);
|
||||
},
|
||||
|
||||
uninit: function() {
|
||||
|
@ -974,8 +974,8 @@ var Browser = {
|
||||
|
||||
onAboutPolicyClick: function() {
|
||||
FlyoutPanelsUI.hide();
|
||||
BrowserUI.newTab(Services.prefs.getCharPref("app.privacyURL"),
|
||||
Browser.selectedTab);
|
||||
let linkStr = Services.urlFormatter.formatURLPref("app.privacyURL");
|
||||
BrowserUI.newTab(linkStr, Browser.selectedTab);
|
||||
}
|
||||
|
||||
};
|
||||
|
66
browser/metro/base/content/dbg-metro-actors.js
Normal file
66
browser/metro/base/content/dbg-metro-actors.js
Normal file
@ -0,0 +1,66 @@
|
||||
/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
const error = Components.utils.reportError;
|
||||
|
||||
/* Metrofx specific actors, modelled from the android fennec actors */
|
||||
|
||||
/** aConnection DebuggerServerConnection, the conection to the client.
|
||||
*/
|
||||
function createRootActor(aConnection) {
|
||||
let parameters = {
|
||||
tabList: new MetroTabList(aConnection),
|
||||
globalActorFactories: DebuggerServer.globalActorFactories,
|
||||
onShutdown: sendShutdownEvent
|
||||
};
|
||||
return new RootActor(aConnection, parameters);
|
||||
}
|
||||
|
||||
/** aConnection DebuggerServerConnection, the conection to the client.
|
||||
*/
|
||||
function MetroTabList(aConnection) {
|
||||
BrowserTabList.call(this, aConnection);
|
||||
}
|
||||
|
||||
MetroTabList.prototype = Object.create(BrowserTabList.prototype);
|
||||
MetroTabList.prototype.constructor = MetroTabList;
|
||||
/**
|
||||
* We want to avoid mysterious behavior if tabs are closed or opened mid-iteration.
|
||||
* We want at the end, a list of the actors that were live when we began the iteration.
|
||||
* So, we update the map first, iterate over it again to yield the actors.
|
||||
*/
|
||||
MetroTabList.prototype.iterator = function() {
|
||||
|
||||
let initialMapSize = this._actorByBrowser.size;
|
||||
let foundCount = 0;
|
||||
for (let win of allAppShellDOMWindows("navigator:browser")) {
|
||||
let selectedTab = win.Browser.selectedBrowser;
|
||||
|
||||
for (let browser of win.Browser.browsers) {
|
||||
let actor = this._actorByBrowser.get(browser);
|
||||
if (actor) {
|
||||
foundCount++;
|
||||
} else {
|
||||
actor = new BrowserTabActor(this._connection, browser);
|
||||
this._actorByBrowser.set(browser, actor);
|
||||
}
|
||||
|
||||
// Set the 'selected' properties on all actors correctly.
|
||||
actor.selected = (browser === selectedTab);
|
||||
}
|
||||
}
|
||||
|
||||
if (this._testing && initialMapSize !== foundCount) {
|
||||
throw error("_actorByBrowser map contained actors for dead tabs");
|
||||
}
|
||||
|
||||
this._mustNotify = true;
|
||||
this._checkListening();
|
||||
|
||||
for (let [browser, actor] of this._actorByBrowser) {
|
||||
yield actor;
|
||||
}
|
||||
};
|
@ -58,7 +58,6 @@ var FindHelperUI = {
|
||||
Elements.tabList.addEventListener("TabSelect", this, true);
|
||||
Elements.browsers.addEventListener("URLChanged", this, true);
|
||||
window.addEventListener("MozContextUIShow", this, true);
|
||||
window.addEventListener("MozContextUIExpand", this, true);
|
||||
},
|
||||
|
||||
receiveMessage: function findHelperReceiveMessage(aMessage) {
|
||||
@ -81,7 +80,6 @@ var FindHelperUI = {
|
||||
handleEvent: function findHelperHandleEvent(aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case "MozContextUIShow":
|
||||
case "MozContextUIExpand":
|
||||
case "TabSelect":
|
||||
this.hide();
|
||||
break;
|
||||
|
@ -88,11 +88,13 @@ chrome.jar:
|
||||
content/TopSites.js (content/TopSites.js)
|
||||
content/console.js (content/console.js)
|
||||
content/AnimatedZoom.js (content/AnimatedZoom.js)
|
||||
content/dbg-metro-actors.js (content/dbg-metro-actors.js)
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
* content/sync.js (content/sync.js)
|
||||
content/RemoteTabs.js (content/RemoteTabs.js)
|
||||
#endif
|
||||
content/NavButtonSlider.js (content/NavButtonSlider.js)
|
||||
content/ContextUI.js (content/ContextUI.js)
|
||||
|
||||
% override chrome://global/content/config.xul chrome://browser/content/config.xul
|
||||
% override chrome://global/content/netError.xhtml chrome://browser/content/netError.xhtml
|
||||
|
@ -19,27 +19,27 @@ gTests.push({
|
||||
});
|
||||
|
||||
is(StartUI.isVisible, true, "Start UI is displayed on about:start");
|
||||
is(ContextUI.isVisible, true, "Navbar is displayed on about:start");
|
||||
is(ContextUI.isExpanded, false, "Tabbar is not displayed initially");
|
||||
is(Elements.navbar.isShowing, false, "Appbar is not displayed initially");
|
||||
is(ContextUI.navbarVisible, true, "Navbar is displayed on about:start");
|
||||
is(ContextUI.tabbarVisible, false, "Tabbar is not displayed initially");
|
||||
is(ContextUI.contextAppbarVisible, false, "Appbar is not displayed initially");
|
||||
|
||||
// toggle on
|
||||
doEdgeUIGesture();
|
||||
is(ContextUI.isVisible, true, "Navbar is still visible after one swipe");
|
||||
is(ContextUI.isExpanded, true, "Tabbar is visible after one swipe");
|
||||
is(Elements.navbar.isShowing, true, "Appbar is visible after one swipe");
|
||||
is(ContextUI.navbarVisible, true, "Navbar is still visible after one swipe");
|
||||
is(ContextUI.tabbarVisible, true, "Tabbar is visible after one swipe");
|
||||
is(ContextUI.contextAppbarVisible, false, "Appbar is hidden after one swipe");
|
||||
|
||||
// toggle off
|
||||
doEdgeUIGesture();
|
||||
is(ContextUI.isVisible, true, "Navbar is still visible after second swipe");
|
||||
is(ContextUI.isExpanded, false, "Tabbar is hidden after second swipe");
|
||||
is(Elements.navbar.isShowing, false, "Appbar is hidden after second swipe");
|
||||
is(ContextUI.navbarVisible, true, "Navbar is still visible after second swipe");
|
||||
is(ContextUI.tabbarVisible, false, "Tabbar is hidden after second swipe");
|
||||
is(ContextUI.contextAppbarVisible, false, "Appbar is hidden after second swipe");
|
||||
|
||||
// sanity check - toggle on again
|
||||
doEdgeUIGesture();
|
||||
is(ContextUI.isVisible, true, "Navbar is still visible after third swipe");
|
||||
is(ContextUI.isExpanded, true, "Tabbar is visible after third swipe");
|
||||
is(Elements.navbar.isShowing, true, "Appbar is visible after third swipe");
|
||||
is(ContextUI.navbarVisible, true, "Navbar is still visible after third swipe");
|
||||
is(ContextUI.tabbarVisible, true, "Tabbar is visible after third swipe");
|
||||
is(ContextUI.contextAppbarVisible, false, "Appbar is hidden after third swipe");
|
||||
|
||||
is(StartUI.isVisible, true, "Start UI is still visible");
|
||||
}
|
||||
@ -51,19 +51,16 @@ gTests.push({
|
||||
yield addTab("about:");
|
||||
ContextUI.dismiss();
|
||||
is(StartUI.isVisible, false, "Start UI is not visible on about:");
|
||||
is(ContextUI.isVisible, false, "Navbar is not initially visible on about:");
|
||||
is(ContextUI.isExpanded, false, "Tabbar is not initially visible on about:");
|
||||
is(Elements.navbar.isShowing, false, "Appbar is not initially visible on about on about::");
|
||||
is(ContextUI.navbarVisible, false, "Navbar is not initially visible on about:");
|
||||
is(ContextUI.tabbarVisible, false, "Tabbar is not initially visible on about:");
|
||||
|
||||
doEdgeUIGesture();
|
||||
is(ContextUI.isVisible, true, "Navbar is visible after one swipe");
|
||||
is(ContextUI.isExpanded, true, "Tabbar is visble after one swipe");
|
||||
is(Elements.navbar.isShowing, true, "Appbar is visible after one swipe");
|
||||
is(ContextUI.navbarVisible, true, "Navbar is visible after one swipe");
|
||||
is(ContextUI.tabbarVisible, true, "Tabbar is visble after one swipe");
|
||||
|
||||
doEdgeUIGesture();
|
||||
is(ContextUI.isVisible, false, "Navbar is not visible after second swipe");
|
||||
is(ContextUI.isExpanded, false, "Tabbar is not visible after second swipe");
|
||||
is(Elements.navbar.isShowing, false, "Appbar is hidden after second swipe");
|
||||
is(ContextUI.navbarVisible, false, "Navbar is not visible after second swipe");
|
||||
is(ContextUI.tabbarVisible, false, "Tabbar is not visible after second swipe");
|
||||
|
||||
is(StartUI.isVisible, false, "Start UI is still not visible");
|
||||
}
|
||||
@ -74,12 +71,12 @@ gTests.push({
|
||||
run: function testAbout() {
|
||||
let tab = yield addTab("about:");
|
||||
ContextUI.dismiss();
|
||||
is(ContextUI.isVisible, false, "Navbar is not initially visible");
|
||||
is(ContextUI.isExpanded, false, "Tab bar is not initially visible");
|
||||
is(ContextUI.navbarVisible, false, "Navbar is not initially visible");
|
||||
is(ContextUI.tabbarVisible, false, "Tab bar is not initially visible");
|
||||
|
||||
EventUtils.synthesizeKey('l', { accelKey: true });
|
||||
is(ContextUI.isVisible, true, "Navbar is visible");
|
||||
is(ContextUI.isExpanded, false, "Tab bar is not visible");
|
||||
is(ContextUI.navbarVisible, true, "Navbar is visible");
|
||||
is(ContextUI.tabbarVisible, false, "Tab bar is not visible");
|
||||
|
||||
let edit = document.getElementById("urlbar-edit");
|
||||
is(edit.value, "about:", "Location field contains the page URL");
|
||||
|
@ -171,23 +171,22 @@ function clearSelection(aTarget) {
|
||||
Asynchronous Metro ui helpers
|
||||
=============================================================================*/
|
||||
|
||||
// Hides the tab and context app bar if they are visible
|
||||
function hideContextUI()
|
||||
{
|
||||
purgeEventQueue();
|
||||
|
||||
return Task.spawn(function() {
|
||||
if (ContextUI.isExpanded) {
|
||||
if (ContextUI.tabbarVisible) {
|
||||
let promise = waitForEvent(Elements.tray, "transitionend", null, Elements.tray);
|
||||
if (ContextUI.dismiss())
|
||||
{
|
||||
info("ContextUI dismissed, waiting...");
|
||||
if (ContextUI.dismiss()) {
|
||||
yield promise;
|
||||
}
|
||||
}
|
||||
|
||||
if (Elements.contextappbar.isShowing) {
|
||||
if (ContextUI.contextAppbarVisible) {
|
||||
let promise = waitForEvent(Elements.contextappbar, "transitionend", null, Elements.contextappbar);
|
||||
Elements.contextappbar.dismiss();
|
||||
ContextUI.dismissContextAppbar();
|
||||
yield promise;
|
||||
}
|
||||
});
|
||||
@ -196,7 +195,7 @@ function hideContextUI()
|
||||
function showNavBar()
|
||||
{
|
||||
let promise = waitForEvent(Elements.navbar, "transitionend");
|
||||
if (!ContextUI.isVisible) {
|
||||
if (!ContextUI.navbarVisible) {
|
||||
ContextUI.displayNavbar();
|
||||
return promise;
|
||||
}
|
||||
|
@ -385,7 +385,7 @@ pref("breakpad.reportURL", "https://crash-stats.mozilla.com/report/index/");
|
||||
// TODO: This is not the correct article for metro!!!
|
||||
pref("app.sync.tutorialURL", "https://support.mozilla.org/kb/sync-firefox-between-desktop-and-mobile");
|
||||
pref("app.support.baseURL", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/");
|
||||
pref("app.privacyURL", "https://www.mozilla.org/legal/privacy/");
|
||||
pref("app.privacyURL", "http://www.mozilla.org/%LOCALE%/legal/privacy/firefox.html");
|
||||
pref("app.creditsURL", "http://www.mozilla.org/credits/");
|
||||
pref("app.channelURL", "http://www.mozilla.org/%LOCALE%/firefox/channel/");
|
||||
|
||||
|
@ -402,7 +402,7 @@ appbar[visible] {
|
||||
-moz-image-region: rect(0 80px 40px 40px);
|
||||
}
|
||||
|
||||
#toolbar > .appbar-primary:not([checked]):active {
|
||||
#toolbar > .appbar-primary[checked] {
|
||||
-moz-image-region: rect(0 120px 40px 80px);
|
||||
}
|
||||
|
||||
@ -410,6 +410,10 @@ appbar[visible] {
|
||||
-moz-image-region: rect(0 160px 40px 120px);
|
||||
}
|
||||
|
||||
#toolbar > .appbar-primary:active {
|
||||
-moz-image-region: rect(0 120px 40px 80px);
|
||||
}
|
||||
|
||||
@media (min-resolution: 130dpi) {
|
||||
#toolbar > .appbar-primary > .toolbarbutton-icon {
|
||||
width: 40px;
|
||||
@ -424,13 +428,17 @@ appbar[visible] {
|
||||
-moz-image-region: rect(0 112px 56px 56px);
|
||||
}
|
||||
|
||||
#toolbar > .appbar-primary:not([checked]):active {
|
||||
-moz-image-region: rect(0 168px 56px 112px);
|
||||
#toolbar > .appbar-primary[checked] {
|
||||
-moz-image-region: rect(0 224px 56px 168px);
|
||||
}
|
||||
|
||||
#toolbar > .appbar-primary[checked]:hover:not(:active) {
|
||||
-moz-image-region: rect(0 224px 56px 168px);
|
||||
}
|
||||
|
||||
#toolbar > .appbar-primary:active {
|
||||
-moz-image-region: rect(0 168px 56px 112px);
|
||||
}
|
||||
}
|
||||
|
||||
/* Page-Specific */
|
||||
|
@ -205,158 +205,3 @@ richlistitem[type="download"]:hover > stack > .downloadButton.downloadRetry:hove
|
||||
richlistitem[type="download"]:hover > stack > .downloadButton.downloadRetry:active {
|
||||
-moz-image-region: rect(32px, 64px, 48px, 48px);
|
||||
}
|
||||
|
||||
/*** Status and progress indicator ***/
|
||||
|
||||
#downloads-indicator-anchor {
|
||||
/* Makes the outermost stack element positioned, so that its contents are
|
||||
rendered over the main browser window in the Z order. This is required by
|
||||
the animated event notification. */
|
||||
position: relative;
|
||||
}
|
||||
|
||||
toolbar[iconsize="small"] > #downloads-indicator > #downloads-indicator-anchor {
|
||||
min-width: 16px;
|
||||
min-height: 16px;
|
||||
}
|
||||
|
||||
toolbar[iconsize="large"] > #downloads-indicator > #downloads-indicator-anchor {
|
||||
min-width: 24px;
|
||||
min-height: 24px;
|
||||
}
|
||||
|
||||
/*** Main indicator icon ***/
|
||||
|
||||
toolbar[iconsize="small"] > #downloads-indicator > #downloads-indicator-anchor > #downloads-indicator-icon {
|
||||
background: -moz-image-rect(url("chrome://browser/skin/Toolbar-small.png"),
|
||||
0, 16, 16, 0) center no-repeat;
|
||||
}
|
||||
|
||||
toolbar[iconsize="large"] > #downloads-indicator > #downloads-indicator-anchor > #downloads-indicator-icon {
|
||||
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
|
||||
0, 24, 24, 0) center no-repeat;
|
||||
}
|
||||
|
||||
toolbar[iconsize="small"] > #downloads-indicator[attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
|
||||
background-image: url("chrome://browser/skin/downloads/download-glow-small.png");
|
||||
}
|
||||
|
||||
toolbar[iconsize="large"] > #downloads-indicator[attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
|
||||
background-image: url("chrome://browser/skin/downloads/download-glow.png");
|
||||
}
|
||||
|
||||
/* In the next few rules, we use :not([counter]) as a shortcut that is
|
||||
equivalent to -moz-any([progress], [paused]). */
|
||||
|
||||
#downloads-indicator:not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
|
||||
background: -moz-image-rect(url("chrome://browser/skin/Toolbar-small.png"),
|
||||
0, 16, 16, 0) center no-repeat;
|
||||
background-size: 12px;
|
||||
}
|
||||
|
||||
#downloads-indicator:not([counter])[attention] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
|
||||
background-image: url("chrome://browser/skin/downloads/download-glow.png");
|
||||
}
|
||||
|
||||
/*** Download notifications ***/
|
||||
|
||||
#downloads-indicator-notification {
|
||||
opacity: 0;
|
||||
background-size: 16px;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
@keyframes downloadsIndicatorNotificationStartRight {
|
||||
from { opacity: 0; transform: translate(-128px, 128px) scale(8); }
|
||||
20% { opacity: .85; animation-timing-function: ease-out; }
|
||||
to { opacity: 0; transform: translate(0) scale(1); }
|
||||
}
|
||||
|
||||
@keyframes downloadsIndicatorNotificationStartLeft {
|
||||
from { opacity: 0; transform: translate(128px, 128px) scale(8); }
|
||||
20% { opacity: .85; animation-timing-function: ease-out; }
|
||||
to { opacity: 0; transform: translate(0) scale(1); }
|
||||
}
|
||||
|
||||
#downloads-indicator[notification="start"] > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
background-image: url("chrome://browser/skin/downloads/download-notification-start.png");
|
||||
animation-name: downloadsIndicatorNotificationStartRight;
|
||||
animation-duration: 1s;
|
||||
}
|
||||
|
||||
#downloads-indicator[notification="start"]:-moz-locale-dir(rtl) > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
animation-name: downloadsIndicatorNotificationStartLeft;
|
||||
}
|
||||
|
||||
@keyframes downloadsIndicatorNotificationFinish {
|
||||
from { opacity: 0; transform: scale(1); }
|
||||
20% { opacity: .65; animation-timing-function: ease-in; }
|
||||
to { opacity: 0; transform: scale(8); }
|
||||
}
|
||||
|
||||
#downloads-indicator[notification="finish"] > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
background-image: url("chrome://browser/skin/downloads/download-notification-finish.png");
|
||||
animation-name: downloadsIndicatorNotificationFinish;
|
||||
animation-duration: 1s;
|
||||
}
|
||||
|
||||
/*** Progress bar and text ***/
|
||||
|
||||
#downloads-indicator-counter {
|
||||
height: 10px;
|
||||
margin: 0;
|
||||
color: hsl(0,0%,30%);
|
||||
text-shadow: 0 1px 0 hsla(0,0%,100%,.5);
|
||||
font-size: 10px;
|
||||
line-height: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#downloads-indicator-progress {
|
||||
width: 16px;
|
||||
height: 6px;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
margin-top: 1px;
|
||||
margin-bottom: 2px;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 1px 0 hsla(0,0%,100%,.4);
|
||||
}
|
||||
|
||||
#downloads-indicator-progress > .progress-bar {
|
||||
-moz-appearance: none;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
/* The background-clip: border-box; and background-image: none; are there to expand the background-color behind the border */
|
||||
background-clip: padding-box, border-box;
|
||||
background-color: rgb(255, 135, 94);
|
||||
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px), none;
|
||||
border: 1px solid;
|
||||
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
|
||||
border-radius: 2px 0 0 2px;
|
||||
}
|
||||
|
||||
#downloads-indicator-progress > .progress-remainder {
|
||||
-moz-appearance: none;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
background-image: linear-gradient(#505050, #575757);
|
||||
border: 1px solid;
|
||||
border-color: hsla(0,0%,0%,.6) hsla(0,0%,0%,.4) hsla(0,0%,0%,.4);
|
||||
-moz-border-start: none;
|
||||
border-radius: 0 2px 2px 0;
|
||||
}
|
||||
|
||||
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-bar {
|
||||
background-color: rgb(220, 230, 81);
|
||||
}
|
||||
|
||||
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-remainder {
|
||||
background-image: linear-gradient(#4b5000, #515700);
|
||||
}
|
||||
|
||||
toolbar[mode="full"] > #downloads-indicator > .toolbarbutton-text {
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
158
browser/themes/linux/downloads/indicator.css
Normal file
158
browser/themes/linux/downloads/indicator.css
Normal file
@ -0,0 +1,158 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*** Status and progress indicator ***/
|
||||
|
||||
#downloads-indicator-anchor {
|
||||
/* Makes the outermost stack element positioned, so that its contents are
|
||||
rendered over the main browser window in the Z order. This is required by
|
||||
the animated event notification. */
|
||||
position: relative;
|
||||
}
|
||||
|
||||
toolbar[iconsize="small"] > #downloads-indicator > #downloads-indicator-anchor {
|
||||
min-width: 16px;
|
||||
min-height: 16px;
|
||||
}
|
||||
|
||||
toolbar[iconsize="large"] > #downloads-indicator > #downloads-indicator-anchor {
|
||||
min-width: 24px;
|
||||
min-height: 24px;
|
||||
}
|
||||
|
||||
/*** Main indicator icon ***/
|
||||
|
||||
toolbar[iconsize="small"] > #downloads-indicator > #downloads-indicator-anchor > #downloads-indicator-icon {
|
||||
background: -moz-image-rect(url("chrome://browser/skin/Toolbar-small.png"),
|
||||
0, 16, 16, 0) center no-repeat;
|
||||
}
|
||||
|
||||
toolbar[iconsize="large"] > #downloads-indicator > #downloads-indicator-anchor > #downloads-indicator-icon {
|
||||
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
|
||||
0, 24, 24, 0) center no-repeat;
|
||||
}
|
||||
|
||||
toolbar[iconsize="small"] > #downloads-indicator[attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
|
||||
background-image: url("chrome://browser/skin/downloads/download-glow-small.png");
|
||||
}
|
||||
|
||||
toolbar[iconsize="large"] > #downloads-indicator[attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
|
||||
background-image: url("chrome://browser/skin/downloads/download-glow.png");
|
||||
}
|
||||
|
||||
/* In the next few rules, we use :not([counter]) as a shortcut that is
|
||||
equivalent to -moz-any([progress], [paused]). */
|
||||
|
||||
#downloads-indicator:not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
|
||||
background: -moz-image-rect(url("chrome://browser/skin/Toolbar-small.png"),
|
||||
0, 16, 16, 0) center no-repeat;
|
||||
background-size: 12px;
|
||||
}
|
||||
|
||||
#downloads-indicator:not([counter])[attention] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
|
||||
background-image: url("chrome://browser/skin/downloads/download-glow.png");
|
||||
}
|
||||
|
||||
/*** Download notifications ***/
|
||||
|
||||
#downloads-indicator-notification {
|
||||
opacity: 0;
|
||||
background-size: 16px;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
@keyframes downloadsIndicatorNotificationStartRight {
|
||||
from { opacity: 0; transform: translate(-128px, 128px) scale(8); }
|
||||
20% { opacity: .85; animation-timing-function: ease-out; }
|
||||
to { opacity: 0; transform: translate(0) scale(1); }
|
||||
}
|
||||
|
||||
@keyframes downloadsIndicatorNotificationStartLeft {
|
||||
from { opacity: 0; transform: translate(128px, 128px) scale(8); }
|
||||
20% { opacity: .85; animation-timing-function: ease-out; }
|
||||
to { opacity: 0; transform: translate(0) scale(1); }
|
||||
}
|
||||
|
||||
#downloads-indicator[notification="start"] > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
background-image: url("chrome://browser/skin/downloads/download-notification-start.png");
|
||||
animation-name: downloadsIndicatorNotificationStartRight;
|
||||
animation-duration: 1s;
|
||||
}
|
||||
|
||||
#downloads-indicator[notification="start"]:-moz-locale-dir(rtl) > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
animation-name: downloadsIndicatorNotificationStartLeft;
|
||||
}
|
||||
|
||||
@keyframes downloadsIndicatorNotificationFinish {
|
||||
from { opacity: 0; transform: scale(1); }
|
||||
20% { opacity: .65; animation-timing-function: ease-in; }
|
||||
to { opacity: 0; transform: scale(8); }
|
||||
}
|
||||
|
||||
#downloads-indicator[notification="finish"] > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
background-image: url("chrome://browser/skin/downloads/download-notification-finish.png");
|
||||
animation-name: downloadsIndicatorNotificationFinish;
|
||||
animation-duration: 1s;
|
||||
}
|
||||
|
||||
/*** Progress bar and text ***/
|
||||
|
||||
#downloads-indicator-counter {
|
||||
height: 10px;
|
||||
margin: 0;
|
||||
color: hsl(0,0%,30%);
|
||||
text-shadow: 0 1px 0 hsla(0,0%,100%,.5);
|
||||
font-size: 10px;
|
||||
line-height: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#downloads-indicator-progress {
|
||||
width: 16px;
|
||||
height: 6px;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
margin-top: 1px;
|
||||
margin-bottom: 2px;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 1px 0 hsla(0,0%,100%,.4);
|
||||
}
|
||||
|
||||
#downloads-indicator-progress > .progress-bar {
|
||||
-moz-appearance: none;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
/* The background-clip: border-box; and background-image: none; are there to expand the background-color behind the border */
|
||||
background-clip: padding-box, border-box;
|
||||
background-color: rgb(255, 135, 94);
|
||||
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px), none;
|
||||
border: 1px solid;
|
||||
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
|
||||
border-radius: 2px 0 0 2px;
|
||||
}
|
||||
|
||||
#downloads-indicator-progress > .progress-remainder {
|
||||
-moz-appearance: none;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
background-image: linear-gradient(#505050, #575757);
|
||||
border: 1px solid;
|
||||
border-color: hsla(0,0%,0%,.6) hsla(0,0%,0%,.4) hsla(0,0%,0%,.4);
|
||||
-moz-border-start: none;
|
||||
border-radius: 0 2px 2px 0;
|
||||
}
|
||||
|
||||
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-bar {
|
||||
background-color: rgb(220, 230, 81);
|
||||
}
|
||||
|
||||
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-remainder {
|
||||
background-image: linear-gradient(#4b5000, #515700);
|
||||
}
|
||||
|
||||
toolbar[mode="full"] > #downloads-indicator > .toolbarbutton-text {
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
}
|
@ -57,15 +57,16 @@ browser.jar:
|
||||
skin/classic/browser/webRTC-shareDevice-16.png
|
||||
skin/classic/browser/webRTC-shareDevice-64.png
|
||||
skin/classic/browser/webRTC-sharingDevice-16.png
|
||||
skin/classic/browser/downloads/allDownloadsViewOverlay.css (downloads/allDownloadsViewOverlay.css)
|
||||
skin/classic/browser/downloads/buttons.png (downloads/buttons.png)
|
||||
skin/classic/browser/downloads/contentAreaDownloadsView.css (downloads/contentAreaDownloadsView.css)
|
||||
skin/classic/browser/downloads/download-glow.png (downloads/download-glow.png)
|
||||
skin/classic/browser/downloads/download-glow-small.png (downloads/download-glow-small.png)
|
||||
skin/classic/browser/downloads/download-notification-finish.png (downloads/download-notification-finish.png)
|
||||
skin/classic/browser/downloads/download-notification-start.png (downloads/download-notification-start.png)
|
||||
skin/classic/browser/downloads/download-summary.png (downloads/download-summary.png)
|
||||
skin/classic/browser/downloads/downloads.css (downloads/downloads.css)
|
||||
skin/classic/browser/downloads/allDownloadsViewOverlay.css (downloads/allDownloadsViewOverlay.css)
|
||||
skin/classic/browser/downloads/contentAreaDownloadsView.css (downloads/contentAreaDownloadsView.css)
|
||||
skin/classic/browser/downloads/indicator.css (downloads/indicator.css)
|
||||
skin/classic/browser/feeds/feedIcon.png (feeds/feedIcon.png)
|
||||
skin/classic/browser/feeds/feedIcon16.png (feeds/feedIcon16.png)
|
||||
skin/classic/browser/feeds/videoFeedIcon.png (feeds/feedIcon.png)
|
||||
|
@ -356,182 +356,3 @@ richlistitem[type="download"]:hover > stack > .downloadButton.downloadRetry:acti
|
||||
-moz-image-region: rect(64px, 256px, 96px, 224px);
|
||||
}
|
||||
}
|
||||
|
||||
/*** Status and progress indicator ***/
|
||||
|
||||
#downloads-indicator-anchor {
|
||||
min-width: 20px;
|
||||
min-height: 20px;
|
||||
/* Makes the outermost stack element positioned, so that its contents are
|
||||
rendered over the main browser window in the Z order. This is required by
|
||||
the animated event notification. */
|
||||
position: relative;
|
||||
/* The selected tab may overlap #downloads-indicator-notification */
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/*** Main indicator icon ***/
|
||||
|
||||
#downloads-indicator-icon {
|
||||
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
|
||||
0, 140, 20, 120) center no-repeat;
|
||||
}
|
||||
|
||||
#downloads-indicator[attention]
|
||||
#downloads-indicator-icon {
|
||||
background-image: url("chrome://browser/skin/downloads/download-glow.png");
|
||||
}
|
||||
|
||||
/* In the next few rules, we use :not([counter]) as a shortcut that is
|
||||
equivalent to -moz-any([progress], [paused]). */
|
||||
|
||||
#downloads-indicator:not([counter])
|
||||
#downloads-indicator-counter {
|
||||
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
|
||||
0, 140, 20, 120) center no-repeat;
|
||||
background-size: 12px;
|
||||
}
|
||||
|
||||
#downloads-indicator:not([counter])[attention]
|
||||
#downloads-indicator-counter {
|
||||
background-image: url("chrome://browser/skin/downloads/download-glow.png");
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
#downloads-indicator-icon:not(:-moz-lwtheme-brighttext) {
|
||||
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar@2x.png"), 0, 280, 40, 240);
|
||||
background-size: 20px;
|
||||
}
|
||||
|
||||
#downloads-indicator:not([counter]) > #downloads-indicator-anchor >
|
||||
#downloads-indicator-progress-area > #downloads-indicator-counter {
|
||||
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar@2x.png"), 0, 280, 40, 240);
|
||||
}
|
||||
|
||||
#downloads-indicator[attention] > #downloads-indicator-anchor >
|
||||
#downloads-indicator-icon {
|
||||
background-image: url("chrome://browser/skin/downloads/download-glow@2x.png");
|
||||
}
|
||||
|
||||
#downloads-indicator:not([counter])[attention] > #downloads-indicator-anchor >
|
||||
#downloads-indicator-progress-area > #downloads-indicator-counter {
|
||||
background-image: url("chrome://browser/skin/downloads/download-glow@2x.png");
|
||||
}
|
||||
}
|
||||
|
||||
/*** Download notifications ***/
|
||||
|
||||
#downloads-indicator-notification {
|
||||
opacity: 0;
|
||||
background-size: 16px;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
@keyframes downloadsIndicatorNotificationStartRight {
|
||||
from { opacity: 0; transform: translate(-128px, 128px) scale(8); }
|
||||
20% { opacity: .85; animation-timing-function: ease-out; }
|
||||
to { opacity: 0; transform: translate(0) scale(1); }
|
||||
}
|
||||
|
||||
@keyframes downloadsIndicatorNotificationStartLeft {
|
||||
from { opacity: 0; transform: translate(128px, 128px) scale(8); }
|
||||
20% { opacity: .85; animation-timing-function: ease-out; }
|
||||
to { opacity: 0; transform: translate(0) scale(1); }
|
||||
}
|
||||
|
||||
#downloads-indicator[notification="start"] > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
background-image: url("chrome://browser/skin/downloads/download-notification-start.png");
|
||||
animation-name: downloadsIndicatorNotificationStartRight;
|
||||
animation-duration: 1s;
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
#downloads-indicator[notification="start"] > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
background-image: url("chrome://browser/skin/downloads/download-notification-start@2x.png");
|
||||
}
|
||||
}
|
||||
|
||||
#downloads-indicator[notification="start"]:-moz-locale-dir(rtl) > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
animation-name: downloadsIndicatorNotificationStartLeft;
|
||||
}
|
||||
|
||||
@keyframes downloadsIndicatorNotificationFinish {
|
||||
from { opacity: 0; transform: scale(1); }
|
||||
20% { opacity: .65; animation-timing-function: ease-in; }
|
||||
to { opacity: 0; transform: scale(8); }
|
||||
}
|
||||
|
||||
#downloads-indicator[notification="finish"] > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
background-image: url("chrome://browser/skin/downloads/download-notification-finish.png");
|
||||
animation-name: downloadsIndicatorNotificationFinish;
|
||||
animation-duration: 1s;
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
#downloads-indicator[notification="finish"] > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
background-image: url("chrome://browser/skin/downloads/download-notification-finish@2x.png");
|
||||
}
|
||||
}
|
||||
|
||||
/*** Progress bar and text ***/
|
||||
|
||||
#downloads-indicator-counter {
|
||||
height: 9px;
|
||||
margin: -3px 0 0;
|
||||
color: hsl(0,0%,30%);
|
||||
text-shadow: 0 1px 0 hsla(0,0%,100%,.5);
|
||||
font-size: 9px;
|
||||
line-height: 9px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#downloads-indicator-progress {
|
||||
width: 16px;
|
||||
height: 5px;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
margin-top: 1px;
|
||||
margin-bottom: 2px;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 1px 0 hsla(0,0%,100%,.4);
|
||||
}
|
||||
|
||||
#downloads-indicator-progress > .progress-bar {
|
||||
-moz-appearance: none;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
/* The background-clip: border-box; and background-image: none; are there to expand the background-color behind the border */
|
||||
background-clip: padding-box, border-box;
|
||||
background-color: rgb(90, 185, 255);
|
||||
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px), none;
|
||||
border: 1px solid;
|
||||
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
|
||||
border-radius: 2px 0 0 2px;
|
||||
}
|
||||
|
||||
#downloads-indicator-progress > .progress-remainder {
|
||||
-moz-appearance: none;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
background-image: linear-gradient(#505050, #575757);
|
||||
border: 1px solid;
|
||||
border-color: hsla(0,0%,0%,.6) hsla(0,0%,0%,.4) hsla(0,0%,0%,.4);
|
||||
-moz-border-start: none;
|
||||
border-radius: 0 2px 2px 0;
|
||||
}
|
||||
|
||||
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-bar {
|
||||
background-color: rgb(220, 230, 81);
|
||||
}
|
||||
|
||||
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-remainder {
|
||||
background-image: linear-gradient(#4b5000, #515700);
|
||||
}
|
||||
|
||||
toolbar[mode="full"] > #downloads-indicator > .toolbarbutton-text {
|
||||
margin: 2px 0 0;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
182
browser/themes/osx/downloads/indicator.css
Normal file
182
browser/themes/osx/downloads/indicator.css
Normal file
@ -0,0 +1,182 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*** Status and progress indicator ***/
|
||||
|
||||
#downloads-indicator-anchor {
|
||||
min-width: 20px;
|
||||
min-height: 20px;
|
||||
/* Makes the outermost stack element positioned, so that its contents are
|
||||
rendered over the main browser window in the Z order. This is required by
|
||||
the animated event notification. */
|
||||
position: relative;
|
||||
/* The selected tab may overlap #downloads-indicator-notification */
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/*** Main indicator icon ***/
|
||||
|
||||
#downloads-indicator-icon {
|
||||
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
|
||||
0, 140, 20, 120) center no-repeat;
|
||||
}
|
||||
|
||||
#downloads-indicator[attention]
|
||||
#downloads-indicator-icon {
|
||||
background-image: url("chrome://browser/skin/downloads/download-glow.png");
|
||||
}
|
||||
|
||||
/* In the next few rules, we use :not([counter]) as a shortcut that is
|
||||
equivalent to -moz-any([progress], [paused]). */
|
||||
|
||||
#downloads-indicator:not([counter])
|
||||
#downloads-indicator-counter {
|
||||
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
|
||||
0, 140, 20, 120) center no-repeat;
|
||||
background-size: 12px;
|
||||
}
|
||||
|
||||
#downloads-indicator:not([counter])[attention]
|
||||
#downloads-indicator-counter {
|
||||
background-image: url("chrome://browser/skin/downloads/download-glow.png");
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
#downloads-indicator-icon:not(:-moz-lwtheme-brighttext) {
|
||||
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar@2x.png"), 0, 280, 40, 240);
|
||||
background-size: 20px;
|
||||
}
|
||||
|
||||
#downloads-indicator:not([counter]) > #downloads-indicator-anchor >
|
||||
#downloads-indicator-progress-area > #downloads-indicator-counter {
|
||||
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar@2x.png"), 0, 280, 40, 240);
|
||||
}
|
||||
|
||||
#downloads-indicator[attention] > #downloads-indicator-anchor >
|
||||
#downloads-indicator-icon {
|
||||
background-image: url("chrome://browser/skin/downloads/download-glow@2x.png");
|
||||
}
|
||||
|
||||
#downloads-indicator:not([counter])[attention] > #downloads-indicator-anchor >
|
||||
#downloads-indicator-progress-area > #downloads-indicator-counter {
|
||||
background-image: url("chrome://browser/skin/downloads/download-glow@2x.png");
|
||||
}
|
||||
}
|
||||
|
||||
/*** Download notifications ***/
|
||||
|
||||
#downloads-indicator-notification {
|
||||
opacity: 0;
|
||||
background-size: 16px;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
@keyframes downloadsIndicatorNotificationStartRight {
|
||||
from { opacity: 0; transform: translate(-128px, 128px) scale(8); }
|
||||
20% { opacity: .85; animation-timing-function: ease-out; }
|
||||
to { opacity: 0; transform: translate(0) scale(1); }
|
||||
}
|
||||
|
||||
@keyframes downloadsIndicatorNotificationStartLeft {
|
||||
from { opacity: 0; transform: translate(128px, 128px) scale(8); }
|
||||
20% { opacity: .85; animation-timing-function: ease-out; }
|
||||
to { opacity: 0; transform: translate(0) scale(1); }
|
||||
}
|
||||
|
||||
#downloads-indicator[notification="start"] > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
background-image: url("chrome://browser/skin/downloads/download-notification-start.png");
|
||||
animation-name: downloadsIndicatorNotificationStartRight;
|
||||
animation-duration: 1s;
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
#downloads-indicator[notification="start"] > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
background-image: url("chrome://browser/skin/downloads/download-notification-start@2x.png");
|
||||
}
|
||||
}
|
||||
|
||||
#downloads-indicator[notification="start"]:-moz-locale-dir(rtl) > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
animation-name: downloadsIndicatorNotificationStartLeft;
|
||||
}
|
||||
|
||||
@keyframes downloadsIndicatorNotificationFinish {
|
||||
from { opacity: 0; transform: scale(1); }
|
||||
20% { opacity: .65; animation-timing-function: ease-in; }
|
||||
to { opacity: 0; transform: scale(8); }
|
||||
}
|
||||
|
||||
#downloads-indicator[notification="finish"] > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
background-image: url("chrome://browser/skin/downloads/download-notification-finish.png");
|
||||
animation-name: downloadsIndicatorNotificationFinish;
|
||||
animation-duration: 1s;
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
#downloads-indicator[notification="finish"] > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
background-image: url("chrome://browser/skin/downloads/download-notification-finish@2x.png");
|
||||
}
|
||||
}
|
||||
|
||||
/*** Progress bar and text ***/
|
||||
|
||||
#downloads-indicator-counter {
|
||||
height: 9px;
|
||||
margin: -3px 0 0;
|
||||
color: hsl(0,0%,30%);
|
||||
text-shadow: 0 1px 0 hsla(0,0%,100%,.5);
|
||||
font-size: 9px;
|
||||
line-height: 9px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#downloads-indicator-progress {
|
||||
width: 16px;
|
||||
height: 5px;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
margin-top: 1px;
|
||||
margin-bottom: 2px;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 1px 0 hsla(0,0%,100%,.4);
|
||||
}
|
||||
|
||||
#downloads-indicator-progress > .progress-bar {
|
||||
-moz-appearance: none;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
/* The background-clip: border-box; and background-image: none; are there to expand the background-color behind the border */
|
||||
background-clip: padding-box, border-box;
|
||||
background-color: rgb(90, 185, 255);
|
||||
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px), none;
|
||||
border: 1px solid;
|
||||
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
|
||||
border-radius: 2px 0 0 2px;
|
||||
}
|
||||
|
||||
#downloads-indicator-progress > .progress-remainder {
|
||||
-moz-appearance: none;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
background-image: linear-gradient(#505050, #575757);
|
||||
border: 1px solid;
|
||||
border-color: hsla(0,0%,0%,.6) hsla(0,0%,0%,.4) hsla(0,0%,0%,.4);
|
||||
-moz-border-start: none;
|
||||
border-radius: 0 2px 2px 0;
|
||||
}
|
||||
|
||||
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-bar {
|
||||
background-color: rgb(220, 230, 81);
|
||||
}
|
||||
|
||||
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-remainder {
|
||||
background-image: linear-gradient(#4b5000, #515700);
|
||||
}
|
||||
|
||||
toolbar[mode="full"] > #downloads-indicator > .toolbarbutton-text {
|
||||
margin: 2px 0 0;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
@ -94,8 +94,10 @@ browser.jar:
|
||||
skin/classic/browser/webRTC-shareDevice-64@2x.png
|
||||
skin/classic/browser/webRTC-sharingDevice-16.png
|
||||
skin/classic/browser/webRTC-sharingDevice-16@2x.png
|
||||
skin/classic/browser/downloads/allDownloadsViewOverlay.css (downloads/allDownloadsViewOverlay.css)
|
||||
skin/classic/browser/downloads/buttons.png (downloads/buttons.png)
|
||||
skin/classic/browser/downloads/buttons@2x.png (downloads/buttons@2x.png)
|
||||
skin/classic/browser/downloads/contentAreaDownloadsView.css (downloads/contentAreaDownloadsView.css)
|
||||
skin/classic/browser/downloads/download-glow.png (downloads/download-glow.png)
|
||||
skin/classic/browser/downloads/download-glow@2x.png (downloads/download-glow@2x.png)
|
||||
skin/classic/browser/downloads/download-notification-finish.png (downloads/download-notification-finish.png)
|
||||
@ -105,8 +107,7 @@ browser.jar:
|
||||
skin/classic/browser/downloads/download-summary.png (downloads/download-summary.png)
|
||||
skin/classic/browser/downloads/download-summary@2x.png (downloads/download-summary@2x.png)
|
||||
skin/classic/browser/downloads/downloads.css (downloads/downloads.css)
|
||||
skin/classic/browser/downloads/allDownloadsViewOverlay.css (downloads/allDownloadsViewOverlay.css)
|
||||
skin/classic/browser/downloads/contentAreaDownloadsView.css (downloads/contentAreaDownloadsView.css)
|
||||
skin/classic/browser/downloads/indicator.css (downloads/indicator.css)
|
||||
skin/classic/browser/feeds/subscribe.css (feeds/subscribe.css)
|
||||
skin/classic/browser/feeds/subscribe-ui.css (feeds/subscribe-ui.css)
|
||||
skin/classic/browser/feeds/feedIcon.png (feeds/feedIcon.png)
|
||||
|
@ -20,41 +20,3 @@
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
|
||||
@media (-moz-windows-compositor) {
|
||||
/* The following rules are for the downloads indicator when in its normal,
|
||||
non-downloading, non-paused state (ie, it's just showing the downloads
|
||||
button icon). */
|
||||
#toolbar-menubar #downloads-indicator:not([attention]) > #downloads-indicator-anchor > #downloads-indicator-icon:not(:-moz-lwtheme),
|
||||
#TabsToolbar[tabsontop=true] #downloads-indicator:not([attention]) > #downloads-indicator-anchor > #downloads-indicator-icon:not(:-moz-lwtheme),
|
||||
#navigator-toolbox[tabsontop=false] > #nav-bar #downloads-indicator:not([attention]) > #downloads-indicator-anchor > #downloads-indicator-icon:not(:-moz-lwtheme),
|
||||
#nav-bar + #customToolbars + #PersonalToolbar[collapsed=true] + #TabsToolbar[tabsontop=false]:last-child #downloads-indicator:not([attention]) > #downloads-indicator-anchor > #downloads-indicator-icon:not(:-moz-lwtheme),
|
||||
|
||||
/* The following rules are for the downloads indicator when in its paused
|
||||
or undetermined progress state. We use :not([counter]) as a shortcut for
|
||||
:-moz-any([progress], [paused]). */
|
||||
|
||||
/* This is the case where the downloads indicator has been moved next to the menubar */
|
||||
#toolbar-menubar #downloads-indicator:not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter,
|
||||
/* This is the case where the downloads indicator is in the tabstrip toolbar with tabs on top. */
|
||||
#TabsToolbar[tabsontop=true] #downloads-indicator:not(:-moz-lwtheme):not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter,
|
||||
/* This is the case where the downloads indicator is anywhere in the nav-bar with tabs on bottom. */
|
||||
#navigator-toolbox[tabsontop=false] > #nav-bar #downloads-indicator:not(:-moz-lwtheme):not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter,
|
||||
/* This is the case where the downloads indicator is in the tabstrip when the tabstrip is the last item in the toolbox (and is therefore over glass) */
|
||||
#nav-bar + #customToolbars + #PersonalToolbar[collapsed=true] + #TabsToolbar[tabsontop=false]:last-child #downloads-indicator:not(:-moz-lwtheme):not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
|
||||
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"), 0, 108, 18, 90);
|
||||
}
|
||||
|
||||
#toolbar-menubar #downloads-indicator-counter:not(:-moz-lwtheme),
|
||||
#TabsToolbar[tabsontop=true] #downloads-indicator-counter:not(:-moz-lwtheme),
|
||||
#navigator-toolbox[tabsontop=false] > #nav-bar #downloads-indicator-counter:not(:-moz-lwtheme),
|
||||
#nav-bar + #customToolbars + #PersonalToolbar[collapsed=true] + #TabsToolbar[tabsontop=false]:last-child #downloads-indicator-counter:not(:-moz-lwtheme) {
|
||||
color: white;
|
||||
text-shadow: 0 0 1px rgba(0,0,0,.7),
|
||||
0 1px 1.5px rgba(0,0,0,.5);
|
||||
}
|
||||
}
|
||||
|
||||
#downloads-indicator-counter {
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
@ -235,152 +235,3 @@ richlistitem[type="download"]:hover > stack > .downloadButton.downloadRetry:hove
|
||||
richlistitem[type="download"]:hover > stack > .downloadButton.downloadRetry:active {
|
||||
-moz-image-region: rect(32px, 64px, 48px, 48px);
|
||||
}
|
||||
|
||||
/*** Status and progress indicator ***/
|
||||
|
||||
#downloads-indicator-anchor {
|
||||
/* Makes the outermost stack element positioned, so that its contents are
|
||||
rendered over the main browser window in the Z order. This is required by
|
||||
the animated event notification. */
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/*** Main indicator icon ***/
|
||||
|
||||
#downloads-indicator-icon {
|
||||
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
|
||||
0, 108, 18, 90) center no-repeat;
|
||||
min-width: 18px;
|
||||
min-height: 18px;
|
||||
}
|
||||
|
||||
#downloads-indicator-icon:-moz-lwtheme-brighttext {
|
||||
background: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"),
|
||||
0, 108, 18, 90) center no-repeat;
|
||||
}
|
||||
|
||||
#downloads-indicator[attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
|
||||
background-image: url("chrome://browser/skin/downloads/download-glow.png");
|
||||
}
|
||||
|
||||
/* In the next few rules, we use :not([counter]) as a shortcut that is
|
||||
equivalent to -moz-any([progress], [paused]). */
|
||||
|
||||
#downloads-indicator:not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
|
||||
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
|
||||
0, 108, 18, 90) center no-repeat;
|
||||
background-size: 12px;
|
||||
}
|
||||
|
||||
#downloads-indicator:not([counter])[attention] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
|
||||
background-image: url("chrome://browser/skin/downloads/download-glow.png");
|
||||
}
|
||||
|
||||
/*** Download notifications ***/
|
||||
|
||||
#downloads-indicator-notification {
|
||||
opacity: 0;
|
||||
background-size: 16px;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
@keyframes downloadsIndicatorNotificationStartRight {
|
||||
from { opacity: 0; transform: translate(-128px, 128px) scale(8); }
|
||||
20% { opacity: .85; animation-timing-function: ease-out; }
|
||||
to { opacity: 0; transform: translate(0) scale(1); }
|
||||
}
|
||||
|
||||
@keyframes downloadsIndicatorNotificationStartLeft {
|
||||
from { opacity: 0; transform: translate(128px, 128px) scale(8); }
|
||||
20% { opacity: .85; animation-timing-function: ease-out; }
|
||||
to { opacity: 0; transform: translate(0) scale(1); }
|
||||
}
|
||||
|
||||
#downloads-indicator[notification="start"] > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
background-image: url("chrome://browser/skin/downloads/download-notification-start.png");
|
||||
animation-name: downloadsIndicatorNotificationStartRight;
|
||||
animation-duration: 1s;
|
||||
}
|
||||
|
||||
#downloads-indicator[notification="start"]:-moz-locale-dir(rtl) > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
animation-name: downloadsIndicatorNotificationStartLeft;
|
||||
}
|
||||
|
||||
@keyframes downloadsIndicatorNotificationFinish {
|
||||
from { opacity: 0; transform: scale(1); }
|
||||
20% { opacity: .65; animation-timing-function: ease-in; }
|
||||
to { opacity: 0; transform: scale(8); }
|
||||
}
|
||||
|
||||
#downloads-indicator[notification="finish"] > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
background-image: url("chrome://browser/skin/downloads/download-notification-finish.png");
|
||||
animation-name: downloadsIndicatorNotificationFinish;
|
||||
animation-duration: 1s;
|
||||
}
|
||||
|
||||
/*** Progress bar and text ***/
|
||||
|
||||
#downloads-indicator-counter {
|
||||
height: 9px;
|
||||
margin: -3px 0px 0px 0px;
|
||||
color: hsl(0,0%,30%);
|
||||
text-shadow: hsla(0,0%,100%,.5) 0 1px;
|
||||
font-size: 9px;
|
||||
line-height: 9px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#downloads-indicator-counter:-moz-lwtheme-brighttext {
|
||||
color: white;
|
||||
text-shadow: 0 0 1px rgba(0,0,0,.7),
|
||||
0 1px 1.5px rgba(0,0,0,.5);
|
||||
}
|
||||
|
||||
#downloads-indicator-progress {
|
||||
width: 16px;
|
||||
height: 5px;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
margin-top: 1px;
|
||||
margin-bottom: 2px;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 1px 0 hsla(0,0%,100%,.4);
|
||||
}
|
||||
|
||||
#downloads-indicator-progress > .progress-bar {
|
||||
-moz-appearance: none;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
/* The background-clip: border-box; and background-image: none; are there to expand the background-color behind the border */
|
||||
background-clip: padding-box, border-box;
|
||||
background-color: rgb(90, 201, 66);
|
||||
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px), none;
|
||||
border: 1px solid;
|
||||
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
|
||||
border-radius: 2px 0 0 2px;
|
||||
}
|
||||
|
||||
#downloads-indicator-progress > .progress-remainder {
|
||||
-moz-appearance: none;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
background-image: linear-gradient(#505050, #575757);
|
||||
border: 1px solid;
|
||||
border-color: hsla(0,0%,0%,.6) hsla(0,0%,0%,.4) hsla(0,0%,0%,.4);
|
||||
-moz-border-start: none;
|
||||
border-radius: 0 2px 2px 0;
|
||||
}
|
||||
|
||||
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-bar {
|
||||
background-color: rgb(220, 230, 81);
|
||||
}
|
||||
|
||||
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-remainder {
|
||||
background-image: linear-gradient(#4b5000, #515700);
|
||||
}
|
||||
|
||||
toolbar[mode="full"] > #downloads-indicator > .toolbarbutton-text {
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
45
browser/themes/windows/downloads/indicator-aero.css
Normal file
45
browser/themes/windows/downloads/indicator-aero.css
Normal file
@ -0,0 +1,45 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
%define WINDOWS_AERO
|
||||
%include indicator.css
|
||||
%undef WINDOWS_AERO
|
||||
|
||||
@media (-moz-windows-compositor) {
|
||||
/* The following rules are for the downloads indicator when in its normal,
|
||||
non-downloading, non-paused state (ie, it's just showing the downloads
|
||||
button icon). */
|
||||
#toolbar-menubar #downloads-indicator:not([attention]) > #downloads-indicator-anchor > #downloads-indicator-icon:not(:-moz-lwtheme),
|
||||
#TabsToolbar[tabsontop=true] #downloads-indicator:not([attention]) > #downloads-indicator-anchor > #downloads-indicator-icon:not(:-moz-lwtheme),
|
||||
#navigator-toolbox[tabsontop=false] > #nav-bar #downloads-indicator:not([attention]) > #downloads-indicator-anchor > #downloads-indicator-icon:not(:-moz-lwtheme),
|
||||
#nav-bar + #customToolbars + #PersonalToolbar[collapsed=true] + #TabsToolbar[tabsontop=false]:last-child #downloads-indicator:not([attention]) > #downloads-indicator-anchor > #downloads-indicator-icon:not(:-moz-lwtheme),
|
||||
|
||||
/* The following rules are for the downloads indicator when in its paused
|
||||
or undetermined progress state. We use :not([counter]) as a shortcut for
|
||||
:-moz-any([progress], [paused]). */
|
||||
|
||||
/* This is the case where the downloads indicator has been moved next to the menubar */
|
||||
#toolbar-menubar #downloads-indicator:not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter,
|
||||
/* This is the case where the downloads indicator is in the tabstrip toolbar with tabs on top. */
|
||||
#TabsToolbar[tabsontop=true] #downloads-indicator:not(:-moz-lwtheme):not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter,
|
||||
/* This is the case where the downloads indicator is anywhere in the nav-bar with tabs on bottom. */
|
||||
#navigator-toolbox[tabsontop=false] > #nav-bar #downloads-indicator:not(:-moz-lwtheme):not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter,
|
||||
/* This is the case where the downloads indicator is in the tabstrip when the tabstrip is the last item in the toolbox (and is therefore over glass) */
|
||||
#nav-bar + #customToolbars + #PersonalToolbar[collapsed=true] + #TabsToolbar[tabsontop=false]:last-child #downloads-indicator:not(:-moz-lwtheme):not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
|
||||
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"), 0, 108, 18, 90);
|
||||
}
|
||||
|
||||
#toolbar-menubar #downloads-indicator-counter:not(:-moz-lwtheme),
|
||||
#TabsToolbar[tabsontop=true] #downloads-indicator-counter:not(:-moz-lwtheme),
|
||||
#navigator-toolbox[tabsontop=false] > #nav-bar #downloads-indicator-counter:not(:-moz-lwtheme),
|
||||
#nav-bar + #customToolbars + #PersonalToolbar[collapsed=true] + #TabsToolbar[tabsontop=false]:last-child #downloads-indicator-counter:not(:-moz-lwtheme) {
|
||||
color: white;
|
||||
text-shadow: 0 0 1px rgba(0,0,0,.7),
|
||||
0 1px 1.5px rgba(0,0,0,.5);
|
||||
}
|
||||
}
|
||||
|
||||
#downloads-indicator-counter {
|
||||
margin-bottom: -1px;
|
||||
}
|
152
browser/themes/windows/downloads/indicator.css
Normal file
152
browser/themes/windows/downloads/indicator.css
Normal file
@ -0,0 +1,152 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*** Status and progress indicator ***/
|
||||
|
||||
#downloads-indicator-anchor {
|
||||
/* Makes the outermost stack element positioned, so that its contents are
|
||||
rendered over the main browser window in the Z order. This is required by
|
||||
the animated event notification. */
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/*** Main indicator icon ***/
|
||||
|
||||
#downloads-indicator-icon {
|
||||
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
|
||||
0, 108, 18, 90) center no-repeat;
|
||||
min-width: 18px;
|
||||
min-height: 18px;
|
||||
}
|
||||
|
||||
#downloads-indicator-icon:-moz-lwtheme-brighttext {
|
||||
background: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"),
|
||||
0, 108, 18, 90) center no-repeat;
|
||||
}
|
||||
|
||||
#downloads-indicator[attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
|
||||
background-image: url("chrome://browser/skin/downloads/download-glow.png");
|
||||
}
|
||||
|
||||
/* In the next few rules, we use :not([counter]) as a shortcut that is
|
||||
equivalent to -moz-any([progress], [paused]). */
|
||||
|
||||
#downloads-indicator:not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
|
||||
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
|
||||
0, 108, 18, 90) center no-repeat;
|
||||
background-size: 12px;
|
||||
}
|
||||
|
||||
#downloads-indicator:not([counter])[attention] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
|
||||
background-image: url("chrome://browser/skin/downloads/download-glow.png");
|
||||
}
|
||||
|
||||
/*** Download notifications ***/
|
||||
|
||||
#downloads-indicator-notification {
|
||||
opacity: 0;
|
||||
background-size: 16px;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
@keyframes downloadsIndicatorNotificationStartRight {
|
||||
from { opacity: 0; transform: translate(-128px, 128px) scale(8); }
|
||||
20% { opacity: .85; animation-timing-function: ease-out; }
|
||||
to { opacity: 0; transform: translate(0) scale(1); }
|
||||
}
|
||||
|
||||
@keyframes downloadsIndicatorNotificationStartLeft {
|
||||
from { opacity: 0; transform: translate(128px, 128px) scale(8); }
|
||||
20% { opacity: .85; animation-timing-function: ease-out; }
|
||||
to { opacity: 0; transform: translate(0) scale(1); }
|
||||
}
|
||||
|
||||
#downloads-indicator[notification="start"] > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
background-image: url("chrome://browser/skin/downloads/download-notification-start.png");
|
||||
animation-name: downloadsIndicatorNotificationStartRight;
|
||||
animation-duration: 1s;
|
||||
}
|
||||
|
||||
#downloads-indicator[notification="start"]:-moz-locale-dir(rtl) > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
animation-name: downloadsIndicatorNotificationStartLeft;
|
||||
}
|
||||
|
||||
@keyframes downloadsIndicatorNotificationFinish {
|
||||
from { opacity: 0; transform: scale(1); }
|
||||
20% { opacity: .65; animation-timing-function: ease-in; }
|
||||
to { opacity: 0; transform: scale(8); }
|
||||
}
|
||||
|
||||
#downloads-indicator[notification="finish"] > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
background-image: url("chrome://browser/skin/downloads/download-notification-finish.png");
|
||||
animation-name: downloadsIndicatorNotificationFinish;
|
||||
animation-duration: 1s;
|
||||
}
|
||||
|
||||
/*** Progress bar and text ***/
|
||||
|
||||
#downloads-indicator-counter {
|
||||
height: 9px;
|
||||
margin: -3px 0px 0px 0px;
|
||||
color: hsl(0,0%,30%);
|
||||
text-shadow: hsla(0,0%,100%,.5) 0 1px;
|
||||
font-size: 9px;
|
||||
line-height: 9px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#downloads-indicator-counter:-moz-lwtheme-brighttext {
|
||||
color: white;
|
||||
text-shadow: 0 0 1px rgba(0,0,0,.7),
|
||||
0 1px 1.5px rgba(0,0,0,.5);
|
||||
}
|
||||
|
||||
#downloads-indicator-progress {
|
||||
width: 16px;
|
||||
height: 5px;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
margin-top: 1px;
|
||||
margin-bottom: 2px;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 1px 0 hsla(0,0%,100%,.4);
|
||||
}
|
||||
|
||||
#downloads-indicator-progress > .progress-bar {
|
||||
-moz-appearance: none;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
/* The background-clip: border-box; and background-image: none; are there to expand the background-color behind the border */
|
||||
background-clip: padding-box, border-box;
|
||||
background-color: rgb(90, 201, 66);
|
||||
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px), none;
|
||||
border: 1px solid;
|
||||
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
|
||||
border-radius: 2px 0 0 2px;
|
||||
}
|
||||
|
||||
#downloads-indicator-progress > .progress-remainder {
|
||||
-moz-appearance: none;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
background-image: linear-gradient(#505050, #575757);
|
||||
border: 1px solid;
|
||||
border-color: hsla(0,0%,0%,.6) hsla(0,0%,0%,.4) hsla(0,0%,0%,.4);
|
||||
-moz-border-start: none;
|
||||
border-radius: 0 2px 2px 0;
|
||||
}
|
||||
|
||||
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-bar {
|
||||
background-color: rgb(220, 230, 81);
|
||||
}
|
||||
|
||||
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-remainder {
|
||||
background-image: linear-gradient(#4b5000, #515700);
|
||||
}
|
||||
|
||||
toolbar[mode="full"] > #downloads-indicator > .toolbarbutton-text {
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
}
|
@ -74,14 +74,15 @@ browser.jar:
|
||||
skin/classic/browser/webRTC-shareDevice-16.png
|
||||
skin/classic/browser/webRTC-shareDevice-64.png
|
||||
skin/classic/browser/webRTC-sharingDevice-16.png
|
||||
* skin/classic/browser/downloads/allDownloadsViewOverlay.css (downloads/allDownloadsViewOverlay.css)
|
||||
skin/classic/browser/downloads/buttons.png (downloads/buttons.png)
|
||||
skin/classic/browser/downloads/contentAreaDownloadsView.css (downloads/contentAreaDownloadsView.css)
|
||||
skin/classic/browser/downloads/download-glow.png (downloads/download-glow.png)
|
||||
skin/classic/browser/downloads/download-notification-finish.png (downloads/download-notification-finish.png)
|
||||
skin/classic/browser/downloads/download-notification-start.png (downloads/download-notification-start.png)
|
||||
skin/classic/browser/downloads/download-summary.png (downloads/download-summary.png)
|
||||
* skin/classic/browser/downloads/downloads.css (downloads/downloads.css)
|
||||
* skin/classic/browser/downloads/allDownloadsViewOverlay.css (downloads/allDownloadsViewOverlay.css)
|
||||
skin/classic/browser/downloads/contentAreaDownloadsView.css (downloads/contentAreaDownloadsView.css)
|
||||
* skin/classic/browser/downloads/indicator.css (downloads/indicator.css)
|
||||
skin/classic/browser/feeds/feedIcon.png (feeds/feedIcon.png)
|
||||
skin/classic/browser/feeds/feedIcon16.png (feeds/feedIcon16.png)
|
||||
skin/classic/browser/feeds/audioFeedIcon.png (feeds/feedIcon.png)
|
||||
@ -327,14 +328,15 @@ browser.jar:
|
||||
skin/classic/aero/browser/webRTC-shareDevice-16.png
|
||||
skin/classic/aero/browser/webRTC-shareDevice-64.png
|
||||
skin/classic/aero/browser/webRTC-sharingDevice-16.png
|
||||
* skin/classic/aero/browser/downloads/allDownloadsViewOverlay.css (downloads/allDownloadsViewOverlay-aero.css)
|
||||
skin/classic/aero/browser/downloads/buttons.png (downloads/buttons-aero.png)
|
||||
skin/classic/aero/browser/downloads/contentAreaDownloadsView.css (downloads/contentAreaDownloadsView.css)
|
||||
skin/classic/aero/browser/downloads/download-glow.png (downloads/download-glow.png)
|
||||
skin/classic/aero/browser/downloads/download-notification-finish.png (downloads/download-notification-finish.png)
|
||||
skin/classic/aero/browser/downloads/download-notification-start.png (downloads/download-notification-start.png)
|
||||
skin/classic/aero/browser/downloads/download-summary.png (downloads/download-summary.png)
|
||||
* skin/classic/aero/browser/downloads/downloads.css (downloads/downloads-aero.css)
|
||||
* skin/classic/aero/browser/downloads/allDownloadsViewOverlay.css (downloads/allDownloadsViewOverlay-aero.css)
|
||||
skin/classic/aero/browser/downloads/contentAreaDownloadsView.css (downloads/contentAreaDownloadsView.css)
|
||||
* skin/classic/aero/browser/downloads/indicator.css (downloads/indicator-aero.css)
|
||||
skin/classic/aero/browser/feeds/feedIcon.png (feeds/feedIcon-aero.png)
|
||||
skin/classic/aero/browser/feeds/feedIcon16.png (feeds/feedIcon16-aero.png)
|
||||
skin/classic/aero/browser/feeds/audioFeedIcon.png (feeds/feedIcon-aero.png)
|
||||
|
@ -25,7 +25,7 @@ interface nsIURI;
|
||||
* interface to mirror this interface when changing it.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(24a35de3-40e4-498e-9c1b-2fd0a2d4cae5)]
|
||||
[scriptable, uuid(070bfc7f-f8b8-4e84-aa31-a0bfaffa8e8e)]
|
||||
interface nsIObjectLoadingContent : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -87,6 +87,13 @@ interface nsIObjectLoadingContent : nsISupports
|
||||
*/
|
||||
unsigned long getContentTypeForMIMEType(in AUTF8String aMimeType);
|
||||
|
||||
/**
|
||||
* Returns the base URI of the object as seen by plugins. This differs from
|
||||
* the normal codebase in that it takes <param> tags and plugin-specific
|
||||
* quirks into account.
|
||||
*/
|
||||
[noscript] readonly attribute nsIURI baseURI;
|
||||
|
||||
/**
|
||||
* Returns the plugin instance if it has already been instantiated. This
|
||||
* will never instantiate the plugin and so is safe to call even when
|
||||
|
@ -548,7 +548,8 @@ CSPRep.fromStringSpecCompliant = function(aStr, self, docRequest, csp) {
|
||||
// Check for unsafe-inline and unsafe-eval in script-src
|
||||
if (dv._allowUnsafeInline) {
|
||||
aCSPR._allowInlineScripts = true;
|
||||
} else if (dv._allowUnsafeEval) {
|
||||
}
|
||||
if (dv._allowUnsafeEval) {
|
||||
aCSPR._allowEval = true;
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "plstr.h"
|
||||
#include "prprf.h"
|
||||
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsDocument.h"
|
||||
@ -1420,6 +1421,46 @@ nsDocument::~nsDocument()
|
||||
|
||||
NS_ASSERTION(!mIsShowing, "Destroying a currently-showing document");
|
||||
|
||||
if (IsTopLevelContentDocument()) {
|
||||
//don't report for about: pages
|
||||
nsCOMPtr<nsIPrincipal> principal = GetPrincipal();
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
principal->GetURI(getter_AddRefs(uri));
|
||||
bool isAboutScheme = true;
|
||||
if (uri) {
|
||||
uri->SchemeIs("about", &isAboutScheme);
|
||||
}
|
||||
|
||||
if (!isAboutScheme) {
|
||||
// Record the mixed content status of the docshell in Telemetry
|
||||
enum {
|
||||
NO_MIXED_CONTENT = 0, // There is no Mixed Content on the page
|
||||
MIXED_DISPLAY_CONTENT = 1, // The page attempted to load Mixed Display Content
|
||||
MIXED_ACTIVE_CONTENT = 2, // The page attempted to load Mixed Active Content
|
||||
MIXED_DISPLAY_AND_ACTIVE_CONTENT = 3 // The page attempted to load Mixed Display & Mixed Active Content
|
||||
};
|
||||
|
||||
bool mixedActiveLoaded = GetHasMixedActiveContentLoaded();
|
||||
bool mixedActiveBlocked = GetHasMixedActiveContentBlocked();
|
||||
|
||||
bool mixedDisplayLoaded = GetHasMixedDisplayContentLoaded();
|
||||
bool mixedDisplayBlocked = GetHasMixedDisplayContentBlocked();
|
||||
|
||||
bool hasMixedDisplay = (mixedDisplayBlocked || mixedDisplayLoaded);
|
||||
bool hasMixedActive = (mixedActiveBlocked || mixedActiveLoaded);
|
||||
|
||||
uint32_t mixedContentLevel = NO_MIXED_CONTENT;
|
||||
if (hasMixedDisplay && hasMixedActive) {
|
||||
mixedContentLevel = MIXED_DISPLAY_AND_ACTIVE_CONTENT;
|
||||
} else if (hasMixedActive){
|
||||
mixedContentLevel = MIXED_ACTIVE_CONTENT;
|
||||
} else if (hasMixedDisplay) {
|
||||
mixedContentLevel = MIXED_DISPLAY_CONTENT;
|
||||
}
|
||||
Accumulate(Telemetry::MIXED_CONTENT_PAGE_LOAD, mixedContentLevel);
|
||||
}
|
||||
}
|
||||
|
||||
mInDestructor = true;
|
||||
mInUnlinkOrDeletion = true;
|
||||
|
||||
@ -4113,6 +4154,23 @@ nsIDocument::SetContainer(nsISupports* aContainer)
|
||||
{
|
||||
mDocumentContainer = do_GetWeakReference(aContainer);
|
||||
EnumerateFreezableElements(NotifyActivityChanged, nullptr);
|
||||
// Get the Docshell
|
||||
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(aContainer);
|
||||
if (docShell) {
|
||||
int32_t itemType;
|
||||
docShell->GetItemType(&itemType);
|
||||
// check itemtype
|
||||
if (itemType == nsIDocShellTreeItem::typeContent) {
|
||||
// check if same type root
|
||||
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
|
||||
docShell->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
|
||||
NS_ASSERTION(sameTypeRoot, "No document shell root tree item from document shell tree item!");
|
||||
|
||||
if (sameTypeRoot == docShell) {
|
||||
static_cast<nsDocument*>(this)->SetIsTopLevelContentDocument(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -4243,6 +4301,18 @@ nsDocument::SetScriptHandlingObject(nsIScriptGlobalObject* aScriptObject)
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsDocument::IsTopLevelContentDocument()
|
||||
{
|
||||
return mIsTopLevelContentDocument;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::SetIsTopLevelContentDocument(bool aIsTopLevelContentDocument)
|
||||
{
|
||||
mIsTopLevelContentDocument = aIsTopLevelContentDocument;
|
||||
}
|
||||
|
||||
nsPIDOMWindow *
|
||||
nsDocument::GetWindowInternal() const
|
||||
{
|
||||
|
@ -1121,6 +1121,12 @@ public:
|
||||
|
||||
static void XPCOMShutdown();
|
||||
|
||||
bool mIsTopLevelContentDocument:1;
|
||||
|
||||
bool IsTopLevelContentDocument();
|
||||
|
||||
void SetIsTopLevelContentDocument(bool aIsTopLevelContentDocument);
|
||||
|
||||
js::ExpandoAndGeneration mExpandoAndGeneration;
|
||||
|
||||
protected:
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMDataContainerEvent.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMHTMLObjectElement.h"
|
||||
#include "nsIDOMHTMLAppletElement.h"
|
||||
#include "nsIExternalProtocolHandler.h"
|
||||
#include "nsEventStates.h"
|
||||
#include "nsIObjectFrame.h"
|
||||
@ -1065,6 +1067,13 @@ nsObjectLoadingContent::GetContentTypeForMIMEType(const nsACString& aMIMEType,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsObjectLoadingContent::GetBaseURI(nsIURI **aResult)
|
||||
{
|
||||
NS_IF_ADDREF(*aResult = mBaseURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIInterfaceRequestor
|
||||
// We use a shim class to implement this so that JS consumers still
|
||||
// see an interface requestor even though WebIDL bindings don't expose
|
||||
@ -1271,7 +1280,7 @@ nsObjectLoadingContent::CheckProcessPolicy(int16_t *aContentPolicy)
|
||||
}
|
||||
|
||||
nsObjectLoadingContent::ParameterUpdateFlags
|
||||
nsObjectLoadingContent::UpdateObjectParameters()
|
||||
nsObjectLoadingContent::UpdateObjectParameters(bool aJavaURI)
|
||||
{
|
||||
nsCOMPtr<nsIContent> thisContent =
|
||||
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
@ -1304,7 +1313,7 @@ nsObjectLoadingContent::UpdateObjectParameters()
|
||||
///
|
||||
/// Initial MIME Type
|
||||
///
|
||||
if (thisContent->NodeInfo()->Equals(nsGkAtoms::applet)) {
|
||||
if (aJavaURI || thisContent->NodeInfo()->Equals(nsGkAtoms::applet)) {
|
||||
newMime.AssignLiteral("application/x-java-vm");
|
||||
isJava = true;
|
||||
} else {
|
||||
@ -1345,17 +1354,76 @@ nsObjectLoadingContent::UpdateObjectParameters()
|
||||
|
||||
nsAutoString codebaseStr;
|
||||
nsCOMPtr<nsIURI> docBaseURI = thisContent->GetBaseURI();
|
||||
thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::codebase, codebaseStr);
|
||||
if (codebaseStr.IsEmpty() && thisContent->NodeInfo()->Equals(nsGkAtoms::applet)) {
|
||||
// bug 406541
|
||||
// NOTE we send the full absolute URI resolved here to java in
|
||||
// pluginInstanceOwner to avoid disagreements between parsing of
|
||||
// relative URIs. We need to mimic java's quirks here to make that
|
||||
// not break things.
|
||||
codebaseStr.AssignLiteral("/"); // Java resolves codebase="" as "/"
|
||||
// XXX(johns) This doesn't catch the case of "file:" which java would
|
||||
// interpret as "file:///" but we would interpret as this document's URI
|
||||
// but with a changed scheme.
|
||||
bool hasCodebase = thisContent->HasAttr(kNameSpaceID_None, nsGkAtoms::codebase);
|
||||
if (hasCodebase)
|
||||
thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::codebase, codebaseStr);
|
||||
|
||||
|
||||
// Java wants the codebase attribute even if it occurs in <param> tags
|
||||
// XXX(johns): This duplicates a chunk of code from nsInstanceOwner, see
|
||||
// bug 853995
|
||||
if (isJava) {
|
||||
// Find all <param> tags that are nested beneath us, but not beneath another
|
||||
// object/applet tag.
|
||||
nsCOMArray<nsIDOMElement> ourParams;
|
||||
nsCOMPtr<nsIDOMElement> mydomElement = do_QueryInterface(thisContent);
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLCollection> allParams;
|
||||
NS_NAMED_LITERAL_STRING(xhtml_ns, "http://www.w3.org/1999/xhtml");
|
||||
mydomElement->GetElementsByTagNameNS(xhtml_ns, NS_LITERAL_STRING("param"),
|
||||
getter_AddRefs(allParams));
|
||||
if (allParams) {
|
||||
uint32_t numAllParams;
|
||||
allParams->GetLength(&numAllParams);
|
||||
for (uint32_t i = 0; i < numAllParams; i++) {
|
||||
nsCOMPtr<nsIDOMNode> pnode;
|
||||
allParams->Item(i, getter_AddRefs(pnode));
|
||||
nsCOMPtr<nsIDOMElement> domelement = do_QueryInterface(pnode);
|
||||
if (domelement) {
|
||||
nsAutoString name;
|
||||
domelement->GetAttribute(NS_LITERAL_STRING("name"), name);
|
||||
name.Trim(" \n\r\t\b", true, true, false);
|
||||
if (name.EqualsIgnoreCase("codebase")) {
|
||||
// Find the first plugin element parent
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
nsCOMPtr<nsIDOMHTMLObjectElement> domobject;
|
||||
nsCOMPtr<nsIDOMHTMLAppletElement> domapplet;
|
||||
pnode->GetParentNode(getter_AddRefs(parent));
|
||||
while (!(domobject || domapplet) && parent) {
|
||||
domobject = do_QueryInterface(parent);
|
||||
domapplet = do_QueryInterface(parent);
|
||||
nsCOMPtr<nsIDOMNode> temp;
|
||||
parent->GetParentNode(getter_AddRefs(temp));
|
||||
parent = temp;
|
||||
}
|
||||
if (domapplet || domobject) {
|
||||
if (domapplet) {
|
||||
parent = domapplet;
|
||||
}
|
||||
else {
|
||||
parent = domobject;
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> mydomNode = do_QueryInterface(mydomElement);
|
||||
if (parent == mydomNode) {
|
||||
hasCodebase = true;
|
||||
domelement->GetAttribute(NS_LITERAL_STRING("value"),
|
||||
codebaseStr);
|
||||
codebaseStr.Trim(" \n\r\t\b", true, true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isJava && hasCodebase && codebaseStr.IsEmpty()) {
|
||||
// Java treats an empty codebase as the document codebase, but codebase=""
|
||||
// as "/"
|
||||
codebaseStr.AssignLiteral("/");
|
||||
// XXX(johns): This doesn't cover the case of "https:" which java would
|
||||
// interpret as "https:///" but we interpret as this document's
|
||||
// URI but with a changed scheme.
|
||||
}
|
||||
|
||||
if (!codebaseStr.IsEmpty()) {
|
||||
@ -1372,7 +1440,7 @@ nsObjectLoadingContent::UpdateObjectParameters()
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, use normal document baseURI
|
||||
// If we failed to build a valid URI, use the document's base URI
|
||||
if (!newBaseURI) {
|
||||
newBaseURI = docBaseURI;
|
||||
}
|
||||
@ -1384,9 +1452,11 @@ nsObjectLoadingContent::UpdateObjectParameters()
|
||||
nsAutoString uriStr;
|
||||
// Different elements keep this in various locations
|
||||
if (isJava) {
|
||||
// Applet tags and embed/object with explicit java MIMEs have
|
||||
// src/data attributes that are not parsed as URIs, so we will
|
||||
// act as if URI is null
|
||||
// Applet tags and embed/object with explicit java MIMEs have src/data
|
||||
// attributes that are not meant to be parsed as URIs or opened by the
|
||||
// browser -- act as if they are null. (Setting these attributes triggers a
|
||||
// force-load, so tracking the old value to determine if they have changed
|
||||
// is not necessary.)
|
||||
} else if (thisContent->NodeInfo()->Equals(nsGkAtoms::object)) {
|
||||
thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::data, uriStr);
|
||||
} else if (thisContent->NodeInfo()->Equals(nsGkAtoms::embed)) {
|
||||
@ -1416,6 +1486,9 @@ nsObjectLoadingContent::UpdateObjectParameters()
|
||||
(caps & eAllowPluginSkipChannel) &&
|
||||
IsPluginEnabledByExtension(newURI, newMime)) {
|
||||
LOG(("OBJLC [%p]: Using extension as type hint (%s)", this, newMime.get()));
|
||||
if (!isJava && nsPluginHost::IsJavaMIMEType(newMime.get())) {
|
||||
return UpdateObjectParameters(true);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
@ -1795,10 +1868,20 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
|
||||
//
|
||||
|
||||
if (mType != eType_Null) {
|
||||
int16_t contentPolicy = nsIContentPolicy::ACCEPT;
|
||||
bool allowLoad = true;
|
||||
if (nsPluginHost::IsJavaMIMEType(mContentType.get())) {
|
||||
nsCOMPtr<nsIScriptSecurityManager> secMan =
|
||||
nsContentUtils::GetSecurityManager();
|
||||
rv = secMan->CheckLoadURIWithPrincipal(thisContent->NodePrincipal(),
|
||||
mBaseURI, 0);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("OBJLC [%p]: Java codebase check failed", this));
|
||||
allowLoad = false;
|
||||
}
|
||||
}
|
||||
int16_t contentPolicy = nsIContentPolicy::ACCEPT;
|
||||
// If mChannelLoaded is set we presumably already passed load policy
|
||||
if (mURI && !mChannelLoaded) {
|
||||
if (allowLoad && mURI && !mChannelLoaded) {
|
||||
allowLoad = CheckLoadPolicy(&contentPolicy);
|
||||
}
|
||||
// If we're loading a type now, check ProcessPolicy. Note that we may check
|
||||
|
@ -344,10 +344,14 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
*
|
||||
* NOTE This function does not perform security checks, only determining the
|
||||
* requested type and parameters of the object.
|
||||
*
|
||||
*
|
||||
* @param aJavaURI Specify that the URI will be consumed by java, which
|
||||
* changes codebase parsing and URI construction. Used
|
||||
* internally.
|
||||
*
|
||||
* @return Returns a bitmask of ParameterUpdateFlags values
|
||||
*/
|
||||
ParameterUpdateFlags UpdateObjectParameters();
|
||||
ParameterUpdateFlags UpdateObjectParameters(bool aJavaURI = false);
|
||||
|
||||
/**
|
||||
* Queue a CheckPluginStopEvent and track it in mPendingCheckPluginStopEvent
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "WebGLVertexAttribData.h"
|
||||
#include "WebGLMemoryMultiReporterWrapper.h"
|
||||
#include "WebGLFramebuffer.h"
|
||||
#include "WebGLVertexArray.h"
|
||||
|
||||
#include "AccessCheck.h"
|
||||
#include "nsIConsoleService.h"
|
||||
@ -253,15 +254,16 @@ WebGLContext::DestroyResourcesAndContext()
|
||||
mBound2DTextures.Clear();
|
||||
mBoundCubeMapTextures.Clear();
|
||||
mBoundArrayBuffer = nullptr;
|
||||
mBoundElementArrayBuffer = nullptr;
|
||||
mCurrentProgram = nullptr;
|
||||
mBoundFramebuffer = nullptr;
|
||||
mBoundRenderbuffer = nullptr;
|
||||
|
||||
mAttribBuffers.Clear();
|
||||
mBoundVertexArray = nullptr;
|
||||
mDefaultVertexArray = nullptr;
|
||||
|
||||
while (!mTextures.isEmpty())
|
||||
mTextures.getLast()->DeleteOnce();
|
||||
while (!mVertexArrays.isEmpty())
|
||||
mVertexArrays.getLast()->DeleteOnce();
|
||||
while (!mBuffers.isEmpty())
|
||||
mBuffers.getLast()->DeleteOnce();
|
||||
while (!mRenderbuffers.isEmpty())
|
||||
@ -984,6 +986,8 @@ bool WebGLContext::IsExtensionSupported(JSContext *cx, WebGLExtensionID ext) con
|
||||
case OES_texture_float_linear:
|
||||
return gl->IsExtensionSupported(gl->IsGLES2() ? GLContext::OES_texture_float_linear
|
||||
: GLContext::ARB_texture_float);
|
||||
case OES_vertex_array_object:
|
||||
return WebGLExtensionVertexArray::IsSupported(this);
|
||||
case EXT_texture_filter_anisotropic:
|
||||
return gl->IsExtensionSupported(GLContext::EXT_texture_filter_anisotropic);
|
||||
case WEBGL_compressed_texture_s3tc:
|
||||
@ -1063,6 +1067,10 @@ WebGLContext::GetExtension(JSContext *cx, const nsAString& aName, ErrorResult& r
|
||||
{
|
||||
ext = OES_texture_float_linear;
|
||||
}
|
||||
else if (CompareWebGLExtensionName(name, "OES_vertex_array_object"))
|
||||
{
|
||||
ext = OES_vertex_array_object;
|
||||
}
|
||||
else if (CompareWebGLExtensionName(name, "OES_standard_derivatives"))
|
||||
{
|
||||
ext = OES_standard_derivatives;
|
||||
@ -1161,6 +1169,9 @@ WebGLContext::GetExtension(JSContext *cx, const nsAString& aName, ErrorResult& r
|
||||
case WEBGL_draw_buffers:
|
||||
obj = new WebGLExtensionDrawBuffers(this);
|
||||
break;
|
||||
case OES_vertex_array_object:
|
||||
obj = new WebGLExtensionVertexArray(this);
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false, "should not get there.");
|
||||
}
|
||||
@ -1564,6 +1575,8 @@ WebGLContext::GetSupportedExtensions(JSContext *cx, Nullable< nsTArray<nsString>
|
||||
arr.AppendElement(NS_LITERAL_STRING("WEBGL_depth_texture"));
|
||||
if (IsExtensionSupported(cx, WEBGL_draw_buffers))
|
||||
arr.AppendElement(NS_LITERAL_STRING("WEBGL_draw_buffers"));
|
||||
if (IsExtensionSupported(cx, OES_vertex_array_object))
|
||||
arr.AppendElement(NS_LITERAL_STRING("OES_vertex_array_object"));
|
||||
}
|
||||
|
||||
//
|
||||
@ -1573,17 +1586,16 @@ WebGLContext::GetSupportedExtensions(JSContext *cx, Nullable< nsTArray<nsString>
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(WebGLContext)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(WebGLContext)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_10(WebGLContext,
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_9(WebGLContext,
|
||||
mCanvasElement,
|
||||
mExtensions,
|
||||
mBound2DTextures,
|
||||
mBoundCubeMapTextures,
|
||||
mBoundArrayBuffer,
|
||||
mBoundElementArrayBuffer,
|
||||
mCurrentProgram,
|
||||
mBoundFramebuffer,
|
||||
mBoundRenderbuffer,
|
||||
mAttribBuffers)
|
||||
mBoundVertexArray)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebGLContext)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
|
@ -76,6 +76,7 @@ class WebGLFramebuffer;
|
||||
class WebGLRenderbuffer;
|
||||
class WebGLShaderPrecisionFormat;
|
||||
class WebGLTexture;
|
||||
class WebGLVertexArray;
|
||||
|
||||
namespace dom {
|
||||
struct WebGLContextAttributes;
|
||||
@ -128,6 +129,7 @@ class WebGLContext :
|
||||
friend class WebGLExtensionCompressedTexturePVRTC;
|
||||
friend class WebGLExtensionDepthTexture;
|
||||
friend class WebGLExtensionDrawBuffers;
|
||||
friend class WebGLExtensionVertexArray;
|
||||
|
||||
enum {
|
||||
UNPACK_FLIP_Y_WEBGL = 0x9240,
|
||||
@ -321,6 +323,7 @@ public:
|
||||
void BindFramebuffer(WebGLenum target, WebGLFramebuffer* wfb);
|
||||
void BindRenderbuffer(WebGLenum target, WebGLRenderbuffer* wrb);
|
||||
void BindTexture(WebGLenum target, WebGLTexture *tex);
|
||||
void BindVertexArray(WebGLVertexArray *vao);
|
||||
void BlendColor(WebGLclampf r, WebGLclampf g, WebGLclampf b, WebGLclampf a) {
|
||||
if (!IsContextStable())
|
||||
return;
|
||||
@ -367,12 +370,14 @@ public:
|
||||
already_AddRefed<WebGLRenderbuffer> CreateRenderbuffer();
|
||||
already_AddRefed<WebGLTexture> CreateTexture();
|
||||
already_AddRefed<WebGLShader> CreateShader(WebGLenum type);
|
||||
already_AddRefed<WebGLVertexArray> CreateVertexArray();
|
||||
void CullFace(WebGLenum face);
|
||||
void DeleteBuffer(WebGLBuffer *buf);
|
||||
void DeleteFramebuffer(WebGLFramebuffer *fbuf);
|
||||
void DeleteProgram(WebGLProgram *prog);
|
||||
void DeleteRenderbuffer(WebGLRenderbuffer *rbuf);
|
||||
void DeleteShader(WebGLShader *shader);
|
||||
void DeleteVertexArray(WebGLVertexArray *vao);
|
||||
void DeleteTexture(WebGLTexture *tex);
|
||||
void DepthFunc(WebGLenum func);
|
||||
void DepthMask(WebGLboolean b);
|
||||
@ -465,6 +470,7 @@ public:
|
||||
bool IsRenderbuffer(WebGLRenderbuffer *rb);
|
||||
bool IsShader(WebGLShader *shader);
|
||||
bool IsTexture(WebGLTexture *tex);
|
||||
bool IsVertexArray(WebGLVertexArray *vao);
|
||||
void LineWidth(WebGLfloat width) {
|
||||
if (!IsContextStable())
|
||||
return;
|
||||
@ -874,6 +880,7 @@ protected:
|
||||
OES_standard_derivatives,
|
||||
OES_texture_float,
|
||||
OES_texture_float_linear,
|
||||
OES_vertex_array_object,
|
||||
WEBGL_compressed_texture_atc,
|
||||
WEBGL_compressed_texture_pvrtc,
|
||||
WEBGL_compressed_texture_s3tc,
|
||||
@ -1031,14 +1038,10 @@ protected:
|
||||
void ForceLoseContext();
|
||||
void ForceRestoreContext();
|
||||
|
||||
// the buffers bound to the current program's attribs
|
||||
nsTArray<WebGLVertexAttribData> mAttribBuffers;
|
||||
|
||||
nsTArray<WebGLRefPtr<WebGLTexture> > mBound2DTextures;
|
||||
nsTArray<WebGLRefPtr<WebGLTexture> > mBoundCubeMapTextures;
|
||||
|
||||
WebGLRefPtr<WebGLBuffer> mBoundArrayBuffer;
|
||||
WebGLRefPtr<WebGLBuffer> mBoundElementArrayBuffer;
|
||||
|
||||
WebGLRefPtr<WebGLProgram> mCurrentProgram;
|
||||
|
||||
@ -1046,6 +1049,7 @@ protected:
|
||||
|
||||
WebGLRefPtr<WebGLFramebuffer> mBoundFramebuffer;
|
||||
WebGLRefPtr<WebGLRenderbuffer> mBoundRenderbuffer;
|
||||
WebGLRefPtr<WebGLVertexArray> mBoundVertexArray;
|
||||
|
||||
LinkedList<WebGLTexture> mTextures;
|
||||
LinkedList<WebGLBuffer> mBuffers;
|
||||
@ -1053,6 +1057,9 @@ protected:
|
||||
LinkedList<WebGLShader> mShaders;
|
||||
LinkedList<WebGLRenderbuffer> mRenderbuffers;
|
||||
LinkedList<WebGLFramebuffer> mFramebuffers;
|
||||
LinkedList<WebGLVertexArray> mVertexArrays;
|
||||
|
||||
WebGLRefPtr<WebGLVertexArray> mDefaultVertexArray;
|
||||
|
||||
// PixelStore parameters
|
||||
uint32_t mPixelStorePackAlignment, mPixelStoreUnpackAlignment, mPixelStoreColorspaceConversion;
|
||||
@ -1138,6 +1145,7 @@ public:
|
||||
friend class WebGLBuffer;
|
||||
friend class WebGLShader;
|
||||
friend class WebGLUniformLocation;
|
||||
friend class WebGLVertexArray;
|
||||
};
|
||||
|
||||
// used by DOM bindings in conjunction with GetParentObject
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "WebGLShaderPrecisionFormat.h"
|
||||
#include "WebGLTexture.h"
|
||||
#include "WebGLExtensions.h"
|
||||
#include "WebGLVertexArray.h"
|
||||
|
||||
#include "nsString.h"
|
||||
#include "nsDebug.h"
|
||||
@ -162,7 +163,7 @@ WebGLContext::BindBuffer(WebGLenum target, WebGLBuffer *buf)
|
||||
if (target == LOCAL_GL_ARRAY_BUFFER) {
|
||||
mBoundArrayBuffer = buf;
|
||||
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
|
||||
mBoundElementArrayBuffer = buf;
|
||||
mBoundVertexArray->mBoundElementArrayBuffer = buf;
|
||||
}
|
||||
|
||||
MakeContextCurrent();
|
||||
@ -226,6 +227,39 @@ WebGLContext::BindRenderbuffer(WebGLenum target, WebGLRenderbuffer *wrb)
|
||||
mBoundRenderbuffer = wrb;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::BindVertexArray(WebGLVertexArray *array)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return;
|
||||
|
||||
if (!ValidateObjectAllowDeletedOrNull("bindVertexArrayObject", array))
|
||||
return;
|
||||
|
||||
if (array && array->IsDeleted()) {
|
||||
/* http://www.khronos.org/registry/gles/extensions/OES/OES_vertex_array_object.txt
|
||||
* BindVertexArrayOES fails and an INVALID_OPERATION error is
|
||||
* generated if array is not a name returned from a previous call to
|
||||
* GenVertexArraysOES, or if such a name has since been deleted with
|
||||
* DeleteVertexArraysOES
|
||||
*/
|
||||
ErrorInvalidOperation("bindVertexArray: can't bind a deleted array!");
|
||||
return;
|
||||
}
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (array) {
|
||||
gl->fBindVertexArray(array->GLName());
|
||||
array->SetHasEverBeenBound(true);
|
||||
mBoundVertexArray = array;
|
||||
}
|
||||
else {
|
||||
gl->fBindVertexArray(0);
|
||||
mBoundVertexArray = mDefaultVertexArray;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::BindTexture(WebGLenum target, WebGLTexture *tex)
|
||||
{
|
||||
@ -337,7 +371,7 @@ GLenum WebGLContext::CheckedBufferData(GLenum target,
|
||||
if (target == LOCAL_GL_ARRAY_BUFFER) {
|
||||
boundBuffer = mBoundArrayBuffer;
|
||||
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
|
||||
boundBuffer = mBoundElementArrayBuffer;
|
||||
boundBuffer = mBoundVertexArray->mBoundElementArrayBuffer;
|
||||
}
|
||||
NS_ABORT_IF_FALSE(boundBuffer != nullptr, "no buffer bound for this target");
|
||||
|
||||
@ -366,7 +400,7 @@ WebGLContext::BufferData(WebGLenum target, WebGLsizeiptr size,
|
||||
if (target == LOCAL_GL_ARRAY_BUFFER) {
|
||||
boundBuffer = mBoundArrayBuffer;
|
||||
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
|
||||
boundBuffer = mBoundElementArrayBuffer;
|
||||
boundBuffer = mBoundVertexArray->mBoundElementArrayBuffer;
|
||||
} else {
|
||||
return ErrorInvalidEnumInfo("bufferData: target", target);
|
||||
}
|
||||
@ -411,7 +445,7 @@ WebGLContext::BufferData(WebGLenum target, ArrayBuffer *data, WebGLenum usage)
|
||||
if (target == LOCAL_GL_ARRAY_BUFFER) {
|
||||
boundBuffer = mBoundArrayBuffer;
|
||||
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
|
||||
boundBuffer = mBoundElementArrayBuffer;
|
||||
boundBuffer = mBoundVertexArray->mBoundElementArrayBuffer;
|
||||
} else {
|
||||
return ErrorInvalidEnumInfo("bufferData: target", target);
|
||||
}
|
||||
@ -449,7 +483,7 @@ WebGLContext::BufferData(WebGLenum target, ArrayBufferView& data, WebGLenum usag
|
||||
if (target == LOCAL_GL_ARRAY_BUFFER) {
|
||||
boundBuffer = mBoundArrayBuffer;
|
||||
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
|
||||
boundBuffer = mBoundElementArrayBuffer;
|
||||
boundBuffer = mBoundVertexArray->mBoundElementArrayBuffer;
|
||||
} else {
|
||||
return ErrorInvalidEnumInfo("bufferData: target", target);
|
||||
}
|
||||
@ -492,7 +526,7 @@ WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
|
||||
if (target == LOCAL_GL_ARRAY_BUFFER) {
|
||||
boundBuffer = mBoundArrayBuffer;
|
||||
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
|
||||
boundBuffer = mBoundElementArrayBuffer;
|
||||
boundBuffer = mBoundVertexArray->mBoundElementArrayBuffer;
|
||||
} else {
|
||||
return ErrorInvalidEnumInfo("bufferSubData: target", target);
|
||||
}
|
||||
@ -530,7 +564,7 @@ WebGLContext::BufferSubData(WebGLenum target, WebGLsizeiptr byteOffset,
|
||||
if (target == LOCAL_GL_ARRAY_BUFFER) {
|
||||
boundBuffer = mBoundArrayBuffer;
|
||||
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
|
||||
boundBuffer = mBoundElementArrayBuffer;
|
||||
boundBuffer = mBoundVertexArray->mBoundElementArrayBuffer;
|
||||
} else {
|
||||
return ErrorInvalidEnumInfo("bufferSubData: target", target);
|
||||
}
|
||||
@ -1071,13 +1105,14 @@ WebGLContext::DeleteBuffer(WebGLBuffer *buf)
|
||||
if (mBoundArrayBuffer == buf)
|
||||
BindBuffer(LOCAL_GL_ARRAY_BUFFER,
|
||||
static_cast<WebGLBuffer*>(nullptr));
|
||||
if (mBoundElementArrayBuffer == buf)
|
||||
|
||||
if (mBoundVertexArray->mBoundElementArrayBuffer == buf)
|
||||
BindBuffer(LOCAL_GL_ELEMENT_ARRAY_BUFFER,
|
||||
static_cast<WebGLBuffer*>(nullptr));
|
||||
|
||||
for (int32_t i = 0; i < mGLMaxVertexAttribs; i++) {
|
||||
if (mAttribBuffers[i].buf == buf)
|
||||
mAttribBuffers[i].buf = nullptr;
|
||||
if (mBoundVertexArray->mAttribBuffers[i].buf == buf)
|
||||
mBoundVertexArray->mAttribBuffers[i].buf = nullptr;
|
||||
}
|
||||
|
||||
buf->RequestDelete();
|
||||
@ -1124,6 +1159,24 @@ WebGLContext::DeleteRenderbuffer(WebGLRenderbuffer *rbuf)
|
||||
rbuf->RequestDelete();
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::DeleteVertexArray(WebGLVertexArray *array)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return;
|
||||
|
||||
if (array == nullptr)
|
||||
return;
|
||||
|
||||
if (array->IsDeleted())
|
||||
return;
|
||||
|
||||
if (mBoundVertexArray == array)
|
||||
BindVertexArray(static_cast<WebGLVertexArray*>(nullptr));
|
||||
|
||||
array->RequestDelete();
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::DeleteTexture(WebGLTexture *tex)
|
||||
{
|
||||
@ -1251,7 +1304,7 @@ WebGLContext::DisableVertexAttribArray(WebGLuint index)
|
||||
if (index || gl->IsGLES2())
|
||||
gl->fDisableVertexAttribArray(index);
|
||||
|
||||
mAttribBuffers[index].enabled = false;
|
||||
mBoundVertexArray->mAttribBuffers[index].enabled = false;
|
||||
}
|
||||
|
||||
int
|
||||
@ -1262,14 +1315,14 @@ WebGLContext::WhatDoesVertexAttrib0Need()
|
||||
// work around Mac OSX crash, see bug 631420
|
||||
#ifdef XP_MACOSX
|
||||
if (gl->WorkAroundDriverBugs() &&
|
||||
mAttribBuffers[0].enabled &&
|
||||
mBoundVertexArray->mAttribBuffers[0].enabled &&
|
||||
!mCurrentProgram->IsAttribInUse(0))
|
||||
{
|
||||
return VertexAttrib0Status::EmulatedUninitializedArray;
|
||||
}
|
||||
#endif
|
||||
|
||||
return (gl->IsGLES2() || mAttribBuffers[0].enabled) ? VertexAttrib0Status::Default
|
||||
return (gl->IsGLES2() || mBoundVertexArray->mAttribBuffers[0].enabled) ? VertexAttrib0Status::Default
|
||||
: mCurrentProgram->IsAttribInUse(0) ? VertexAttrib0Status::EmulatedInitializedArray
|
||||
: VertexAttrib0Status::EmulatedUninitializedArray;
|
||||
}
|
||||
@ -1369,13 +1422,13 @@ WebGLContext::UndoFakeVertexAttrib0()
|
||||
if (whatDoesAttrib0Need == VertexAttrib0Status::Default)
|
||||
return;
|
||||
|
||||
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mAttribBuffers[0].buf ? mAttribBuffers[0].buf->GLName() : 0);
|
||||
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundVertexArray->mAttribBuffers[0].buf ? mBoundVertexArray->mAttribBuffers[0].buf->GLName() : 0);
|
||||
gl->fVertexAttribPointer(0,
|
||||
mAttribBuffers[0].size,
|
||||
mAttribBuffers[0].type,
|
||||
mAttribBuffers[0].normalized,
|
||||
mAttribBuffers[0].stride,
|
||||
reinterpret_cast<const GLvoid *>(mAttribBuffers[0].byteOffset));
|
||||
mBoundVertexArray->mAttribBuffers[0].size,
|
||||
mBoundVertexArray->mAttribBuffers[0].type,
|
||||
mBoundVertexArray->mAttribBuffers[0].normalized,
|
||||
mBoundVertexArray->mAttribBuffers[0].stride,
|
||||
reinterpret_cast<const GLvoid *>(mBoundVertexArray->mAttribBuffers[0].byteOffset));
|
||||
|
||||
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundArrayBuffer ? mBoundArrayBuffer->GLName() : 0);
|
||||
}
|
||||
@ -1592,10 +1645,10 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type,
|
||||
if (!mCurrentProgram)
|
||||
return;
|
||||
|
||||
if (!mBoundElementArrayBuffer)
|
||||
if (!mBoundVertexArray->mBoundElementArrayBuffer)
|
||||
return ErrorInvalidOperation("drawElements: must have element array buffer binding");
|
||||
|
||||
if (!mBoundElementArrayBuffer->ByteLength())
|
||||
if (!mBoundVertexArray->mBoundElementArrayBuffer->ByteLength())
|
||||
return ErrorInvalidOperation("drawElements: bound element array buffer doesn't have any data");
|
||||
|
||||
CheckedUint32 checked_neededByteCount = checked_byteCount + byteOffset;
|
||||
@ -1603,7 +1656,7 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type,
|
||||
if (!checked_neededByteCount.isValid())
|
||||
return ErrorInvalidOperation("drawElements: overflow in byteOffset+byteCount");
|
||||
|
||||
if (checked_neededByteCount.value() > mBoundElementArrayBuffer->ByteLength())
|
||||
if (checked_neededByteCount.value() > mBoundVertexArray->mBoundElementArrayBuffer->ByteLength())
|
||||
return ErrorInvalidOperation("drawElements: bound element array buffer is too small for given count and offset");
|
||||
|
||||
uint32_t maxAllowedCount = 0;
|
||||
@ -1611,7 +1664,7 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type,
|
||||
return;
|
||||
|
||||
if (!maxAllowedCount ||
|
||||
!mBoundElementArrayBuffer->Validate(type, maxAllowedCount - 1, first, count))
|
||||
!mBoundVertexArray->mBoundElementArrayBuffer->Validate(type, maxAllowedCount - 1, first, count))
|
||||
{
|
||||
return ErrorInvalidOperation(
|
||||
"DrawElements: bound vertex attribute buffers do not have sufficient "
|
||||
@ -1710,7 +1763,7 @@ WebGLContext::EnableVertexAttribArray(WebGLuint index)
|
||||
InvalidateCachedMinInUseAttribArrayLength();
|
||||
|
||||
gl->fEnableVertexAttribArray(index);
|
||||
mAttribBuffers[index].enabled = true;
|
||||
mBoundVertexArray->mAttribBuffers[index].enabled = true;
|
||||
}
|
||||
|
||||
void
|
||||
@ -2030,6 +2083,21 @@ WebGLContext::GetParameter(JSContext* cx, WebGLenum pname, ErrorResult& rv)
|
||||
}
|
||||
}
|
||||
|
||||
if (IsExtensionEnabled(OES_vertex_array_object)) {
|
||||
switch (pname) {
|
||||
|
||||
case LOCAL_GL_VERTEX_ARRAY_BINDING:
|
||||
{
|
||||
if (mBoundVertexArray == mDefaultVertexArray){
|
||||
return WebGLObjectAsJSValue(cx, (WebGLVertexArray *) nullptr, rv);
|
||||
}
|
||||
|
||||
return WebGLObjectAsJSValue(cx, mBoundVertexArray.get(), rv);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
switch (pname) {
|
||||
//
|
||||
// String params
|
||||
@ -2291,7 +2359,7 @@ WebGLContext::GetParameter(JSContext* cx, WebGLenum pname, ErrorResult& rv)
|
||||
|
||||
case LOCAL_GL_ELEMENT_ARRAY_BUFFER_BINDING:
|
||||
{
|
||||
return WebGLObjectAsJSValue(cx, mBoundElementArrayBuffer.get(), rv);
|
||||
return WebGLObjectAsJSValue(cx, mBoundVertexArray->mBoundElementArrayBuffer.get(), rv);
|
||||
}
|
||||
|
||||
case LOCAL_GL_RENDERBUFFER_BINDING:
|
||||
@ -2955,7 +3023,7 @@ WebGLContext::GetVertexAttrib(JSContext* cx, WebGLuint index, WebGLenum pname,
|
||||
if (!IsContextStable())
|
||||
return JS::NullValue();
|
||||
|
||||
if (!ValidateAttribIndex(index, "getVertexAttrib"))
|
||||
if (!mBoundVertexArray->EnsureAttribIndex(index, "getVertexAttrib"))
|
||||
return JS::NullValue();
|
||||
|
||||
MakeContextCurrent();
|
||||
@ -2963,18 +3031,18 @@ WebGLContext::GetVertexAttrib(JSContext* cx, WebGLuint index, WebGLenum pname,
|
||||
switch (pname) {
|
||||
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
|
||||
{
|
||||
return WebGLObjectAsJSValue(cx, mAttribBuffers[index].buf.get(), rv);
|
||||
return WebGLObjectAsJSValue(cx, mBoundVertexArray->mAttribBuffers[index].buf.get(), rv);
|
||||
}
|
||||
|
||||
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_STRIDE:
|
||||
return JS::Int32Value(mAttribBuffers[index].stride);
|
||||
return JS::Int32Value(mBoundVertexArray->mAttribBuffers[index].stride);
|
||||
|
||||
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE:
|
||||
{
|
||||
if (!ValidateAttribIndex(index, "enableVertexAttribArray"))
|
||||
return JS::NullValue();
|
||||
|
||||
if (!mAttribBuffers[index].enabled)
|
||||
if (!mBoundVertexArray->mAttribBuffers[index].enabled)
|
||||
return JS::Int32Value(4);
|
||||
|
||||
// Don't break; fall through.
|
||||
@ -3009,14 +3077,12 @@ WebGLContext::GetVertexAttrib(JSContext* cx, WebGLuint index, WebGLenum pname,
|
||||
|
||||
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED:
|
||||
{
|
||||
return JS::BooleanValue(mAttribBuffers[index].enabled);
|
||||
return JS::BooleanValue(mBoundVertexArray->mAttribBuffers[index].enabled);
|
||||
}
|
||||
|
||||
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
|
||||
{
|
||||
GLint i = 0;
|
||||
gl->fGetVertexAttribiv(index, pname, &i);
|
||||
return JS::BooleanValue(bool(i));
|
||||
return JS::BooleanValue(mBoundVertexArray->mAttribBuffers[index].normalized);
|
||||
}
|
||||
|
||||
default:
|
||||
@ -3040,7 +3106,7 @@ WebGLContext::GetVertexAttribOffset(WebGLuint index, WebGLenum pname)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return mAttribBuffers[index].byteOffset;
|
||||
return mBoundVertexArray->mAttribBuffers[index].byteOffset;
|
||||
}
|
||||
|
||||
void
|
||||
@ -3109,6 +3175,20 @@ WebGLContext::IsRenderbuffer(WebGLRenderbuffer *rb)
|
||||
rb->HasEverBeenBound();
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLContext::IsVertexArray(WebGLVertexArray *array)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return false;
|
||||
|
||||
if (!array)
|
||||
return false;
|
||||
|
||||
return ValidateObjectAllowDeleted("isVertexArray", array) &&
|
||||
!array->IsDeleted() &&
|
||||
array->HasEverBeenBound();
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLContext::IsShader(WebGLShader *shader)
|
||||
{
|
||||
@ -4330,6 +4410,22 @@ WebGLContext::CreateRenderbuffer()
|
||||
return globj.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<WebGLVertexArray>
|
||||
WebGLContext::CreateVertexArray()
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return nullptr;
|
||||
|
||||
nsRefPtr<WebGLVertexArray> globj = new WebGLVertexArray(this);
|
||||
|
||||
MakeContextCurrent();
|
||||
gl->fGenVertexArrays(1, &globj->mGLName);
|
||||
|
||||
mVertexArrays.insertBack(globj);
|
||||
|
||||
return globj.forget();
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::Viewport(WebGLint x, WebGLint y, WebGLsizei width, WebGLsizei height)
|
||||
{
|
||||
@ -4889,8 +4985,9 @@ WebGLContext::VertexAttribPointer(WebGLuint index, WebGLint size, WebGLenum type
|
||||
// requiredAlignment should always be a power of two.
|
||||
WebGLsizei requiredAlignmentMask = requiredAlignment - 1;
|
||||
|
||||
if (!ValidateAttribIndex(index, "vertexAttribPointer"))
|
||||
if ( !mBoundVertexArray->EnsureAttribIndex(index, "vertexAttribPointer") ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (size < 1 || size > 4)
|
||||
return ErrorInvalidValue("vertexAttribPointer: invalid element size");
|
||||
@ -4919,7 +5016,7 @@ WebGLContext::VertexAttribPointer(WebGLuint index, WebGLint size, WebGLenum type
|
||||
return ErrorInvalidOperation("vertexAttribPointer: type must match bound VBO type: %d != %d", type, mBoundArrayBuffer->GLType());
|
||||
*/
|
||||
|
||||
WebGLVertexAttribData &vd = mAttribBuffers[index];
|
||||
WebGLVertexAttribData &vd = mBoundVertexArray->mAttribBuffers[index];
|
||||
|
||||
vd.buf = mBoundArrayBuffer;
|
||||
vd.stride = stride;
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "WebGLFramebuffer.h"
|
||||
#include "WebGLRenderbuffer.h"
|
||||
#include "WebGLTexture.h"
|
||||
#include "WebGLVertexArray.h"
|
||||
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
@ -112,9 +113,9 @@ WebGLContext::ValidateBuffers(uint32_t *maxAllowedCount, const char *info)
|
||||
}
|
||||
|
||||
uint32_t maxAllowed = UINT32_MAX;
|
||||
uint32_t attribs = mAttribBuffers.Length();
|
||||
uint32_t attribs = mBoundVertexArray->mAttribBuffers.Length();
|
||||
for (uint32_t i = 0; i < attribs; ++i) {
|
||||
const WebGLVertexAttribData& vd = mAttribBuffers[i];
|
||||
const WebGLVertexAttribData& vd = mBoundVertexArray->mAttribBuffers[i];
|
||||
|
||||
// If the attrib array isn't enabled, there's nothing to check;
|
||||
// it's a static value.
|
||||
@ -850,18 +851,7 @@ WebGLContext::ValidateUniformSetter(const char* name, WebGLUniformLocation *loca
|
||||
|
||||
bool WebGLContext::ValidateAttribIndex(WebGLuint index, const char *info)
|
||||
{
|
||||
if (index >= mAttribBuffers.Length()) {
|
||||
if (index == WebGLuint(-1)) {
|
||||
ErrorInvalidValue("%s: index -1 is invalid. That probably comes from a getAttribLocation() call, "
|
||||
"where this return value -1 means that the passed name didn't correspond to an active attribute in "
|
||||
"the specified program.", info);
|
||||
} else {
|
||||
ErrorInvalidValue("%s: index %d is out of range", info, index);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
return mBoundVertexArray->EnsureAttribIndex(index, info);
|
||||
}
|
||||
|
||||
bool WebGLContext::ValidateStencilParamsForDrawCall()
|
||||
@ -905,13 +895,10 @@ WebGLContext::InitAndValidateGL()
|
||||
mActiveTexture = 0;
|
||||
mWebGLError = LOCAL_GL_NO_ERROR;
|
||||
|
||||
mAttribBuffers.Clear();
|
||||
|
||||
mBound2DTextures.Clear();
|
||||
mBoundCubeMapTextures.Clear();
|
||||
|
||||
mBoundArrayBuffer = nullptr;
|
||||
mBoundElementArrayBuffer = nullptr;
|
||||
mCurrentProgram = nullptr;
|
||||
|
||||
mBoundFramebuffer = nullptr;
|
||||
@ -934,8 +921,6 @@ WebGLContext::InitAndValidateGL()
|
||||
return false;
|
||||
}
|
||||
|
||||
mAttribBuffers.SetLength(mGLMaxVertexAttribs);
|
||||
|
||||
// Note: GL_MAX_TEXTURE_UNITS is fixed at 4 for most desktop hardware,
|
||||
// even though the hardware supports much more. The
|
||||
// GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS value is the accurate value.
|
||||
@ -1084,5 +1069,9 @@ WebGLContext::InitAndValidateGL()
|
||||
false);
|
||||
}
|
||||
|
||||
mDefaultVertexArray = new WebGLVertexArray(this);
|
||||
mDefaultVertexArray->mAttribBuffers.SetLength(mGLMaxVertexAttribs);
|
||||
mBoundVertexArray = mDefaultVertexArray;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
57
content/canvas/src/WebGLExtensionVertexArray.cpp
Normal file
57
content/canvas/src/WebGLExtensionVertexArray.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "WebGLContext.h"
|
||||
#include "WebGLBuffer.h"
|
||||
#include "WebGLVertexArray.h"
|
||||
#include "WebGLExtensions.h"
|
||||
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
WebGLExtensionVertexArray::WebGLExtensionVertexArray(WebGLContext* context)
|
||||
: WebGLExtensionBase(context)
|
||||
{
|
||||
MOZ_ASSERT(IsSupported(context), "should not construct WebGLExtensionVertexArray :"
|
||||
"OES_vertex_array_object unsuported.");
|
||||
}
|
||||
|
||||
WebGLExtensionVertexArray::~WebGLExtensionVertexArray()
|
||||
{
|
||||
}
|
||||
|
||||
already_AddRefed<WebGLVertexArray> WebGLExtensionVertexArray::CreateVertexArrayOES()
|
||||
{
|
||||
return mContext->CreateVertexArray();
|
||||
}
|
||||
|
||||
void WebGLExtensionVertexArray::DeleteVertexArrayOES(WebGLVertexArray* array)
|
||||
{
|
||||
mContext->DeleteVertexArray(array);
|
||||
}
|
||||
|
||||
bool WebGLExtensionVertexArray::IsVertexArrayOES(WebGLVertexArray* array)
|
||||
{
|
||||
return mContext->IsVertexArray(array);
|
||||
}
|
||||
|
||||
void WebGLExtensionVertexArray::BindVertexArrayOES(WebGLVertexArray* array)
|
||||
{
|
||||
mContext->BindVertexArray(array);
|
||||
}
|
||||
|
||||
bool WebGLExtensionVertexArray::IsSupported(const WebGLContext* context)
|
||||
{
|
||||
gl::GLContext* gl = context->GL();
|
||||
|
||||
if (gl->IsGLES2()) {
|
||||
return gl->IsExtensionSupported(gl::GLContext::OES_vertex_array_object);
|
||||
}
|
||||
|
||||
return gl->IsExtensionSupported(gl::GLContext::ARB_vertex_array_object) ||
|
||||
gl->IsExtensionSupported(gl::GLContext::APPLE_vertex_array_object);
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionVertexArray)
|
@ -172,6 +172,23 @@ public:
|
||||
DECL_WEBGL_EXTENSION_GOOP
|
||||
};
|
||||
|
||||
class WebGLExtensionVertexArray
|
||||
: public WebGLExtensionBase
|
||||
{
|
||||
public:
|
||||
WebGLExtensionVertexArray(WebGLContext*);
|
||||
virtual ~WebGLExtensionVertexArray();
|
||||
|
||||
already_AddRefed<WebGLVertexArray> CreateVertexArrayOES();
|
||||
void DeleteVertexArrayOES(WebGLVertexArray* array);
|
||||
bool IsVertexArrayOES(WebGLVertexArray* array);
|
||||
void BindVertexArrayOES(WebGLVertexArray* array);
|
||||
|
||||
static bool IsSupported(const WebGLContext* context);
|
||||
|
||||
DECL_WEBGL_EXTENSION_GOOP
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // WEBGLEXTENSIONS_H_
|
||||
|
69
content/canvas/src/WebGLVertexArray.cpp
Normal file
69
content/canvas/src/WebGLVertexArray.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "WebGLContext.h"
|
||||
#include "WebGLBuffer.h"
|
||||
#include "WebGLVertexArray.h"
|
||||
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
JSObject*
|
||||
WebGLVertexArray::WrapObject(JSContext *cx, JS::Handle<JSObject*> scope) {
|
||||
return dom::WebGLVertexArrayBinding::Wrap(cx, scope, this);
|
||||
}
|
||||
|
||||
WebGLVertexArray::WebGLVertexArray(WebGLContext* context)
|
||||
: WebGLContextBoundObject(context)
|
||||
, mGLName(0)
|
||||
, mHasEverBeenBound(false)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
}
|
||||
|
||||
void WebGLVertexArray::Delete() {
|
||||
if (mGLName != 0) {
|
||||
mBoundElementArrayBuffer = nullptr;
|
||||
|
||||
mContext->MakeContextCurrent();
|
||||
mContext->gl->fDeleteVertexArrays(1, &mGLName);
|
||||
LinkedListElement<WebGLVertexArray>::removeFrom(mContext->mVertexArrays);
|
||||
}
|
||||
|
||||
mBoundElementArrayBuffer = nullptr;
|
||||
mAttribBuffers.Clear();
|
||||
}
|
||||
|
||||
bool WebGLVertexArray::EnsureAttribIndex(WebGLuint index, const char *info)
|
||||
{
|
||||
if (index >= WebGLuint(mContext->mGLMaxVertexAttribs)) {
|
||||
if (index == WebGLuint(-1)) {
|
||||
mContext->ErrorInvalidValue("%s: index -1 is invalid. That probably comes from a getAttribLocation() call, "
|
||||
"where this return value -1 means that the passed name didn't correspond to an active attribute in "
|
||||
"the specified program.", info);
|
||||
} else {
|
||||
mContext->ErrorInvalidValue("%s: index %d is out of range", info, index);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (index >= mAttribBuffers.Length()) {
|
||||
mAttribBuffers.SetLength(index + 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_2(WebGLVertexArray,
|
||||
mAttribBuffers,
|
||||
mBoundElementArrayBuffer)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(WebGLVertexArray)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(WebGLVertexArray)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebGLVertexArray)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
62
content/canvas/src/WebGLVertexArray.h
Normal file
62
content/canvas/src/WebGLVertexArray.h
Normal file
@ -0,0 +1,62 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef WEBGLVERTEXARRAY_H_
|
||||
#define WEBGLVERTEXARRAY_H_
|
||||
|
||||
#include "WebGLObjectModel.h"
|
||||
#include "WebGLVertexAttribData.h"
|
||||
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
#include "mozilla/LinkedList.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class WebGLVertexArray MOZ_FINAL
|
||||
: public nsISupports
|
||||
, public WebGLRefCountedObject<WebGLVertexArray>
|
||||
, public LinkedListElement<WebGLVertexArray>
|
||||
, public WebGLContextBoundObject
|
||||
, public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
WebGLVertexArray(WebGLContext *context);
|
||||
|
||||
~WebGLVertexArray() {
|
||||
DeleteOnce();
|
||||
};
|
||||
|
||||
void Delete();
|
||||
|
||||
bool HasEverBeenBound() { return mHasEverBeenBound; }
|
||||
void SetHasEverBeenBound(bool x) { mHasEverBeenBound = x; }
|
||||
WebGLuint GLName() const { return mGLName; }
|
||||
|
||||
WebGLContext* GetParentObject() const {
|
||||
return Context();
|
||||
}
|
||||
|
||||
bool EnsureAttribIndex(WebGLuint index, const char *info);
|
||||
|
||||
virtual JSObject* WrapObject(JSContext *cx,
|
||||
JS::Handle<JSObject*> scope) MOZ_OVERRIDE;
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(WebGLVertexArray)
|
||||
|
||||
WebGLuint mGLName;
|
||||
bool mHasEverBeenBound;
|
||||
|
||||
nsTArray<WebGLVertexAttribData> mAttribBuffers;
|
||||
WebGLRefPtr<WebGLBuffer> mBoundElementArrayBuffer;
|
||||
|
||||
friend class WebGLContext;
|
||||
friend class WebGLExtensionVertexArray;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
@ -47,6 +47,7 @@ if CONFIG['MOZ_WEBGL']:
|
||||
'WebGLExtensionTextureFilterAnisotropic.cpp',
|
||||
'WebGLExtensionTextureFloat.cpp',
|
||||
'WebGLExtensionTextureFloatLinear.cpp',
|
||||
'WebGLExtensionVertexArray.cpp',
|
||||
'WebGLFramebuffer.cpp',
|
||||
'WebGLObjectModel.cpp',
|
||||
'WebGLProgram.cpp',
|
||||
@ -56,6 +57,7 @@ if CONFIG['MOZ_WEBGL']:
|
||||
'WebGLTexelConversions.cpp',
|
||||
'WebGLTexture.cpp',
|
||||
'WebGLUniformLocation.cpp',
|
||||
'WebGLVertexArray.cpp',
|
||||
]
|
||||
else:
|
||||
CPP_SOURCES += [
|
||||
|
@ -148,7 +148,11 @@ function runObjectTest() {
|
||||
ext.bindVertexArrayOES(null);
|
||||
shouldBeTrue("ext.isVertexArrayOES(vao)");
|
||||
|
||||
shouldBeFalse("ext.isVertexArrayOES()");
|
||||
/*
|
||||
* Issue found in the conformance test. The public webgl mailing list has been notified about it.
|
||||
* The tests have already been fixed upstream.
|
||||
*/
|
||||
//shouldBeFalse("ext.isVertexArrayOES()");
|
||||
shouldBeFalse("ext.isVertexArrayOES(null)");
|
||||
|
||||
ext.deleteVertexArrayOES(vao);
|
||||
|
@ -1,4 +1,5 @@
|
||||
conformance/extensions/oes-texture-float.html
|
||||
conformance/extensions/oes-vertex-array-object.html
|
||||
conformance/glsl/functions/glsl-function-abs.html
|
||||
conformance/glsl/functions/glsl-function-ceil.html
|
||||
conformance/glsl/functions/glsl-function-clamp-float.html
|
||||
|
@ -138,6 +138,7 @@ MOCHITEST_FILES = \
|
||||
test_paused_after_removed.html \
|
||||
$(filter disabled-for-intermittent-failures--bug-608634, test_error_in_video_document.html) \
|
||||
test_texttrack.html \
|
||||
test_texttrackcue.html \
|
||||
test_timeupdate_small_files.html \
|
||||
test_unseekable.html \
|
||||
test_webvtt_disabled.html \
|
||||
@ -259,6 +260,7 @@ MOCHITEST_FILES += \
|
||||
detodos.opus \
|
||||
notags.mp3 \
|
||||
id3tags.mp3 \
|
||||
basic.vtt \
|
||||
$(NULL)
|
||||
|
||||
# Wave sample files
|
||||
|
17
content/media/test/basic.vtt
Normal file
17
content/media/test/basic.vtt
Normal file
@ -0,0 +1,17 @@
|
||||
WEBVTT
|
||||
|
||||
1
|
||||
00:00.500 --> 00:00.700
|
||||
This
|
||||
|
||||
2
|
||||
00:01.200 --> 00:02.400
|
||||
Is
|
||||
|
||||
3
|
||||
00:02.710 --> 00:02.910
|
||||
A
|
||||
|
||||
3
|
||||
00:03.217 --> 00:03.989
|
||||
Test
|
126
content/media/test/test_texttrackcue.html
Normal file
126
content/media/test/test_texttrackcue.html
Normal file
@ -0,0 +1,126 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=833386
|
||||
-->
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<title>Test for Bug 833386 - HTMLTrackElement</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.webvtt.enabled", true]]},
|
||||
function() {
|
||||
var video = document.createElement("video");
|
||||
video.src = "seek.webm";
|
||||
var trackElement = document.createElement("track");
|
||||
trackElement.src = "basic.vtt";
|
||||
trackElement.kind = "subtitles";
|
||||
document.getElementById("content").appendChild(video);
|
||||
video.appendChild(trackElement);
|
||||
run_tests();
|
||||
function run_tests() {
|
||||
// Re-que run_tests() at the end of the event loop until the track
|
||||
// element has loaded its data.
|
||||
if (trackElement.readyState == 1) {
|
||||
setTimeout(run_tests, 0);
|
||||
return;
|
||||
}
|
||||
is(trackElement.readyState, 2, "Track::ReadyState should be set to LOADED.");
|
||||
|
||||
var cueList = trackElement.track.cues;
|
||||
is(cueList.length, 4, "Cue list length should be 4.");
|
||||
|
||||
// Check if first cue was parsed correctly.
|
||||
var cue = cueList[0];
|
||||
is(cue.id, "1", "Cue's ID should be 1.");
|
||||
is(cue.startTime, 0.5, "Cue's start time should be 0.5.");
|
||||
is(cue.endTime, 0.7, "Cue's end time should be 0.7.");
|
||||
is(cue.pauseOnExit, false, "Cue's pause on exit flag should be false.");
|
||||
is(cue.text, "This", "Cue's text should be set correctly.");
|
||||
// TODO: https://bugzilla.mozilla.org/show_bug.cgi?id=879431
|
||||
// GetTrack() isn't implemented so this *is* returning undefined currently.
|
||||
todo_isnot(cue.track, undefined, "Cue's track should be defined.");
|
||||
|
||||
// Check that all cue times were not rounded
|
||||
is(cueList[1].startTime, 1.2, "Second cue's start time should be 1.2.");
|
||||
is(cueList[1].endTime, 2.4, "Second cue's end time should be 2.4.");
|
||||
is(cueList[2].startTime, 2.71, "Third cue's start time should be 2.71.");
|
||||
is(cueList[2].endTime, 2.91, "Third cue's end time should be 2.91.");
|
||||
is(cueList[3].startTime, 3.217, "Fourth cue's start time should be 3.217.");
|
||||
is(cueList[3].endTime, 3.989, "Fourth cue's end time should be 3.989.");
|
||||
|
||||
// Check that Cue setters are working correctly.
|
||||
cue.id = "Cue 01";
|
||||
is(cue.id, "Cue 01", "Cue's ID should be 'Cue 01'.");
|
||||
cue.startTime = 1.5;
|
||||
is(cue.startTime, 1.5, "Cue's start time should be 1.5.");
|
||||
cue.endTime = 2.5;
|
||||
is(cue.endTime, 2.5, "Cue's end time should be 2.5.");
|
||||
cue.pauseOnExit = true;
|
||||
is(cue.pauseOnExit, true, "Cue's pause on exit flag should be true.");
|
||||
|
||||
// Check that we can create and add new TextTrackCues
|
||||
var textTrackCue = new TextTrackCue(3.999, 4, "foo");
|
||||
trackElement.track.addCue(textTrackCue);
|
||||
is(cueList.length, 5, "Cue list length should now be 5.");
|
||||
|
||||
// Check that new TestTrackCue was added correctly
|
||||
cue = cueList[4];
|
||||
is(cue.startTime, 3.999, "Cue's start time should be 3.999.");
|
||||
is(cue.endTime, 4, "Cue's end time should be 4.");
|
||||
is(cue.text, "foo", "Cue's text should be foo.");
|
||||
|
||||
// Adding the same cue again should not increase the cue count.
|
||||
// TODO: https://bugzilla.mozilla.org/show_bug.cgi?id=867823
|
||||
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#dom-texttrack-addcue
|
||||
trackElement.track.addCue(textTrackCue);
|
||||
todo_is(cueList.length, 5, "Cue list length should be 5.");
|
||||
|
||||
// Check that we are able to remove cues.
|
||||
trackElement.track.removeCue(cue);
|
||||
// TODO: Marked as todo as incorrect addition up top increases cue count
|
||||
// to 4 -- https://bugzilla.mozilla.org/show_bug.cgi?id=867823
|
||||
todo_is(cueList.length, 4, "Cue list length should be 4.");
|
||||
|
||||
var exceptionHappened = false;
|
||||
try {
|
||||
// We should not be able to remove a cue that is not in the list.
|
||||
cue = new TextTrackCue(1, 2, "foo");
|
||||
trackElement.removeCue(cue);
|
||||
} catch (e) {
|
||||
// "NotFoundError" should be thrown when trying to remove a cue that is
|
||||
// not in the list.
|
||||
// TODO: https://bugzilla.mozilla.org/show_bug.cgi?id=867823
|
||||
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#dom-texttrack-removecue
|
||||
todo_is(e.name, "NotFoundError", "We should have caught an error.");
|
||||
exceptionHappened = true;
|
||||
}
|
||||
// If this is false then we did not throw an error and probably removed a cue
|
||||
// when we shouln't have.
|
||||
ok(exceptionHappened, "Exception should have happened.");
|
||||
|
||||
// We should not have removed a cue so the cue list length should not
|
||||
// have changed.
|
||||
// TODO: Marked as todo as incorrect addition of cue up top increases
|
||||
// count erroneously.
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=867823
|
||||
todo_is(cueList.length, 4, "Cue list length should be 4.");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -41,6 +41,12 @@ NS_INTERFACE_MAP_END_INHERITING(AudioNode)
|
||||
NS_IMPL_ADDREF_INHERITED(AudioBufferSourceNode, AudioNode)
|
||||
NS_IMPL_RELEASE_INHERITED(AudioBufferSourceNode, AudioNode)
|
||||
|
||||
/**
|
||||
* Media-thread playback engine for AudioBufferSourceNode.
|
||||
* Nothing is played until a non-null buffer has been set (via
|
||||
* AudioNodeStream::SetBuffer) and a non-zero duration has been set (via
|
||||
* AudioNodeStream::SetInt32Parameter).
|
||||
*/
|
||||
class AudioBufferSourceNodeEngine : public AudioNodeEngine
|
||||
{
|
||||
public:
|
||||
@ -353,8 +359,9 @@ public:
|
||||
AudioChunk* aOutput,
|
||||
bool* aFinished)
|
||||
{
|
||||
if (!mBuffer)
|
||||
if (!mBuffer || !mDuration) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t channels = mBuffer->GetChannels();
|
||||
if (!channels) {
|
||||
@ -484,7 +491,9 @@ AudioBufferSourceNode::Start(double aWhen, double aOffset,
|
||||
std::numeric_limits<double>::min();
|
||||
SendOffsetAndDurationParametersToStream(ns, aOffset, duration);
|
||||
} else {
|
||||
// Remember our arguments so that we can use them once we have a buffer
|
||||
// Remember our arguments so that we can use them once we have a buffer.
|
||||
// We can't send these parameters now because we don't know the buffer
|
||||
// sample rate.
|
||||
mOffset = aOffset;
|
||||
mDuration = aDuration.WasPassed() ?
|
||||
aDuration.Value() :
|
||||
@ -512,11 +521,13 @@ AudioBufferSourceNode::SendBufferParameterToStream(JSContext* aCx)
|
||||
mBuffer->GetThreadSharedChannelsForRate(aCx);
|
||||
ns->SetBuffer(data.forget());
|
||||
ns->SetInt32Parameter(SAMPLE_RATE, rate);
|
||||
|
||||
if (mStartCalled) {
|
||||
SendOffsetAndDurationParametersToStream(ns, mOffset, mDuration);
|
||||
}
|
||||
} else {
|
||||
ns->SetBuffer(nullptr);
|
||||
}
|
||||
|
||||
SendOffsetAndDurationParametersToStream(ns, mOffset, mDuration);
|
||||
}
|
||||
|
||||
void
|
||||
@ -524,8 +535,11 @@ AudioBufferSourceNode::SendOffsetAndDurationParametersToStream(AudioNodeStream*
|
||||
double aOffset,
|
||||
double aDuration)
|
||||
{
|
||||
float rate = mBuffer ? mBuffer->SampleRate() : Context()->SampleRate();
|
||||
int32_t lengthSamples = mBuffer ? mBuffer->Length() : 0;
|
||||
NS_ASSERTION(mBuffer && mStartCalled,
|
||||
"Only call this when we have a buffer and start() has been called");
|
||||
|
||||
float rate = mBuffer->SampleRate();
|
||||
int32_t lengthSamples = mBuffer->Length();
|
||||
double length = double(lengthSamples) / rate;
|
||||
double offset = std::max(0.0, aOffset);
|
||||
double endOffset = aDuration == std::numeric_limits<double>::min() ?
|
||||
|
@ -44,6 +44,7 @@ MOCHITEST_FILES := \
|
||||
test_audioBufferSourceNodeLoop.html \
|
||||
test_audioBufferSourceNodeLoopStartEnd.html \
|
||||
test_audioBufferSourceNodeLoopStartEndSame.html \
|
||||
test_audioBufferSourceNodeNoStart.html \
|
||||
test_audioBufferSourceNodeNullBuffer.html \
|
||||
test_badConnect.html \
|
||||
test_biquadFilterNode.html \
|
||||
|
@ -0,0 +1,33 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test AudioBufferSourceNode when start() is not called</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="webaudio.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
var gTest = {
|
||||
length: 2048,
|
||||
numberOfChannels: 1,
|
||||
createGraph: function(context) {
|
||||
var buffer = context.createBuffer(1, 2048, context.sampleRate);
|
||||
var data = buffer.getChannelData(0);
|
||||
for (var i = 0; i < data.length; ++i) {
|
||||
data[i] = (i%100)/100 - 0.5;
|
||||
}
|
||||
var source = context.createBufferSource();
|
||||
source.buffer = buffer;
|
||||
return source;
|
||||
},
|
||||
};
|
||||
|
||||
runTest();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -18,7 +18,6 @@
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StartupTimeline.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "mozilla/Util.h"
|
||||
#include "mozilla/VisualEventTracer.h"
|
||||
|
@ -1196,6 +1196,11 @@ DOMInterfaces = {
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionVertexArray': {
|
||||
'nativeType': 'mozilla::WebGLExtensionVertexArray',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLFramebuffer': {
|
||||
'nativeType': 'mozilla::WebGLFramebuffer',
|
||||
'headerFile': 'WebGLFramebuffer.h'
|
||||
@ -1241,6 +1246,11 @@ DOMInterfaces = {
|
||||
'wrapperCache': False
|
||||
},
|
||||
|
||||
'WebGLVertexArray': {
|
||||
'nativeType': 'mozilla::WebGLVertexArray',
|
||||
'headerFile': 'WebGLVertexArray.h'
|
||||
},
|
||||
|
||||
'WebSocket': {
|
||||
'headerFile': 'WebSocket.h',
|
||||
'implicitJSContext': [ 'constructor' ]
|
||||
|
@ -80,6 +80,20 @@ listStart = First item
|
||||
listEnd = Last item
|
||||
listItemCount = %S items
|
||||
|
||||
# Description of a table or grid:
|
||||
# 1 is a dynamically retrieved localized role of either 'table' or 'grid'.
|
||||
# 2 is the number of columns within the table.
|
||||
# 3 is the number of rows within the table or grid.
|
||||
tableInfo = %S with %S and %S
|
||||
tableColumnInfo = 1 column;#1 columns
|
||||
tableRowInfo = 1 row;#1 rows
|
||||
|
||||
# table or grid cell information
|
||||
columnInfo = Column %S
|
||||
rowInfo = Row %S
|
||||
spansColumns = spans %S columns
|
||||
spansRows = spans %S rows
|
||||
|
||||
# Invoked actions
|
||||
jumpAction = jumped
|
||||
pressAction = pressed
|
||||
@ -141,3 +155,8 @@ passwordtextAbbr = passwdtxt
|
||||
imagemapAbbr = imgmap
|
||||
figureAbbr = fig
|
||||
textareaAbbr = txtarea
|
||||
tableAbbr = tbl
|
||||
tableInfoAbbr = %S %S %S
|
||||
tableColumnInfoAbbr = #1c;#1c
|
||||
tableRowInfoAbbr = #1r;#1r
|
||||
cellInfoAbbr = c%Sr%S
|
||||
|
@ -49,6 +49,7 @@ using mozilla::DefaultXDisplay;
|
||||
#include "nsIDOMHTMLObjectElement.h"
|
||||
#include "nsIAppShell.h"
|
||||
#include "nsIDOMHTMLAppletElement.h"
|
||||
#include "nsIObjectLoadingContent.h"
|
||||
#include "nsAttrName.h"
|
||||
#include "nsIFocusManager.h"
|
||||
#include "nsFocusManager.h"
|
||||
@ -1047,6 +1048,11 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
|
||||
mNumCachedAttrs = 0xFFFD;
|
||||
}
|
||||
|
||||
// Check if we are java for special codebase handling
|
||||
const char* mime = nullptr;
|
||||
bool isJava = NS_SUCCEEDED(mInstance->GetMIMEType(&mime)) && mime &&
|
||||
nsPluginHost::IsJavaMIMEType(mime);
|
||||
|
||||
// now, we need to find all the PARAM tags that are children of us
|
||||
// however, be careful not to include any PARAMs that don't have us
|
||||
// as a direct parent. For nested object (or applet) tags, be sure
|
||||
@ -1139,6 +1145,23 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
|
||||
mNumCachedAttrs++;
|
||||
}
|
||||
|
||||
// (Bug 738396) java has quirks in its codebase parsing, pass the
|
||||
// absolute codebase URI as content sees it.
|
||||
bool addCodebase = false;
|
||||
nsAutoCString codebaseStr;
|
||||
if (isJava) {
|
||||
nsCOMPtr<nsIObjectLoadingContent> objlc = do_QueryInterface(mContent);
|
||||
NS_ENSURE_TRUE(objlc, NS_ERROR_UNEXPECTED);
|
||||
nsCOMPtr<nsIURI> codebaseURI;
|
||||
nsresult rv = objlc->GetBaseURI(getter_AddRefs(codebaseURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
codebaseURI->GetSpec(codebaseStr);
|
||||
if (!mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::codebase)) {
|
||||
mNumCachedAttrs++;
|
||||
addCodebase = true;
|
||||
}
|
||||
}
|
||||
|
||||
mCachedAttrParamNames = (char**)NS_Alloc(sizeof(char*) * (mNumCachedAttrs + 1 + mNumCachedParams));
|
||||
NS_ENSURE_TRUE(mCachedAttrParamNames, NS_ERROR_OUT_OF_MEMORY);
|
||||
mCachedAttrParamValues = (char**)NS_Alloc(sizeof(char*) * (mNumCachedAttrs + 1 + mNumCachedParams));
|
||||
@ -1183,7 +1206,7 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
|
||||
FixUpURLS(name, value);
|
||||
|
||||
mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(name);
|
||||
if (!wmodeType.IsEmpty() &&
|
||||
if (!wmodeType.IsEmpty() &&
|
||||
0 == PL_strcasecmp(mCachedAttrParamNames[nextAttrParamIndex], "wmode")) {
|
||||
mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_ConvertUTF8toUTF16(wmodeType));
|
||||
|
||||
@ -1192,12 +1215,21 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
|
||||
mNumCachedAttrs--;
|
||||
wmodeSet = true;
|
||||
}
|
||||
} else if (isJava && 0 == PL_strcasecmp(mCachedAttrParamNames[nextAttrParamIndex], "codebase")) {
|
||||
mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_ConvertUTF8toUTF16(codebaseStr));
|
||||
} else {
|
||||
mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(value);
|
||||
}
|
||||
nextAttrParamIndex++;
|
||||
}
|
||||
|
||||
// Potentially add CODEBASE attribute
|
||||
if (addCodebase) {
|
||||
mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("codebase"));
|
||||
mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_ConvertUTF8toUTF16(codebaseStr));
|
||||
nextAttrParamIndex++;
|
||||
}
|
||||
|
||||
// Potentially add WMODE attribute.
|
||||
if (!wmodeType.IsEmpty() && !wmodeSet) {
|
||||
mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("wmode"));
|
||||
@ -1223,7 +1255,10 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
|
||||
nextAttrParamIndex++;
|
||||
|
||||
// Add PARAM name/value pairs.
|
||||
for (uint16_t i = 0; i < mNumCachedParams; i++) {
|
||||
|
||||
// We may decrement mNumCachedParams below
|
||||
uint16_t totalParams = mNumCachedParams;
|
||||
for (uint16_t i = 0; i < totalParams; i++) {
|
||||
nsIDOMElement* param = ourParams.ObjectAt(i);
|
||||
if (!param) {
|
||||
continue;
|
||||
@ -1233,7 +1268,7 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
|
||||
nsAutoString value;
|
||||
param->GetAttribute(NS_LITERAL_STRING("name"), name); // check for empty done above
|
||||
param->GetAttribute(NS_LITERAL_STRING("value"), value);
|
||||
|
||||
|
||||
FixUpURLS(name, value);
|
||||
|
||||
/*
|
||||
@ -1248,6 +1283,12 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
|
||||
*/
|
||||
name.Trim(" \n\r\t\b", true, true, false);
|
||||
value.Trim(" \n\r\t\b", true, true, false);
|
||||
if (isJava && name.EqualsIgnoreCase("codebase")) {
|
||||
// We inserted normalized codebase above, don't include other versions in
|
||||
// params
|
||||
mNumCachedParams--;
|
||||
continue;
|
||||
}
|
||||
mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(name);
|
||||
mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(value);
|
||||
nextAttrParamIndex++;
|
||||
|
@ -64,6 +64,9 @@ interface WebGLTexture {
|
||||
interface WebGLUniformLocation {
|
||||
};
|
||||
|
||||
interface WebGLVertexArray {
|
||||
};
|
||||
|
||||
interface WebGLActiveInfo {
|
||||
readonly attribute GLint size;
|
||||
readonly attribute GLenum type;
|
||||
@ -883,3 +886,13 @@ interface WebGLExtensionDrawBuffers {
|
||||
interface WebGLExtensionTextureFloatLinear
|
||||
{
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface WebGLExtensionVertexArray {
|
||||
const GLenum VERTEX_ARRAY_BINDING_OES = 0x85B5;
|
||||
|
||||
WebGLVertexArray? createVertexArrayOES();
|
||||
void deleteVertexArrayOES(WebGLVertexArray? arrayObject);
|
||||
[WebGLHandlesContextLoss] GLboolean isVertexArrayOES(WebGLVertexArray? arrayObject);
|
||||
void bindVertexArrayOES(WebGLVertexArray? arrayObject);
|
||||
};
|
||||
|
@ -719,7 +719,7 @@ public:
|
||||
virtual void MaskSurface(const Pattern &aSource,
|
||||
SourceSurface *aMask,
|
||||
Point aOffset,
|
||||
const DrawOptions &aOptions = DrawOptions()) { MOZ_ASSERT(0); };
|
||||
const DrawOptions &aOptions = DrawOptions()) = 0;
|
||||
|
||||
/*
|
||||
* Push a clip to the DrawTarget.
|
||||
|
@ -107,6 +107,10 @@ public:
|
||||
virtual void Mask(const Pattern &aSource,
|
||||
const Pattern &aMask,
|
||||
const DrawOptions &aOptions = DrawOptions());
|
||||
virtual void MaskSurface(const Pattern &aSource,
|
||||
SourceSurface *aMask,
|
||||
Point aOffset,
|
||||
const DrawOptions &aOptions = DrawOptions()) { MOZ_ASSERT(0); };
|
||||
|
||||
virtual void PushClip(const Path *aPath);
|
||||
virtual void PushClipRect(const Rect &aRect);
|
||||
|
@ -248,6 +248,16 @@ DrawTargetRecording::Mask(const Pattern &aSource,
|
||||
mFinalDT->Mask(*AdjustedPattern(aSource), *AdjustedPattern(aMask), aOptions);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetRecording::MaskSurface(const Pattern &aSource,
|
||||
SourceSurface *aMask,
|
||||
Point aOffset,
|
||||
const DrawOptions &aOptions)
|
||||
{
|
||||
mRecorder->RecordEvent(RecordedMaskSurface(this, aSource, aMask, aOffset, aOptions));
|
||||
mFinalDT->MaskSurface(*AdjustedPattern(aSource), GetSourceSurface(aMask), aOffset, aOptions);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetRecording::Stroke(const Path *aPath,
|
||||
const Pattern &aPattern,
|
||||
|
@ -172,6 +172,11 @@ public:
|
||||
const Pattern &aMask,
|
||||
const DrawOptions &aOptions = DrawOptions());
|
||||
|
||||
virtual void MaskSurface(const Pattern &aSource,
|
||||
SourceSurface *aMask,
|
||||
Point aOffset,
|
||||
const DrawOptions &aOptions = DrawOptions());
|
||||
|
||||
/*
|
||||
* Push a clip to the DrawTarget.
|
||||
*
|
||||
|
@ -75,6 +75,10 @@ public:
|
||||
virtual void Mask(const Pattern &aSource,
|
||||
const Pattern &aMask,
|
||||
const DrawOptions &aOptions = DrawOptions());
|
||||
virtual void MaskSurface(const Pattern &aSource,
|
||||
SourceSurface *aMask,
|
||||
Point aOffset,
|
||||
const DrawOptions &aOptions = DrawOptions()) { MOZ_ASSERT(0); };
|
||||
virtual void PushClip(const Path *aPath);
|
||||
virtual void PushClipRect(const Rect& aRect);
|
||||
virtual void PopClip();
|
||||
|
@ -58,6 +58,7 @@ RecordedEvent::LoadEventFromStream(std::istream &aStream, EventType aType)
|
||||
LOAD_EVENT_TYPE(SNAPSHOT, RecordedSnapshot);
|
||||
LOAD_EVENT_TYPE(SCALEDFONTCREATION, RecordedScaledFontCreation);
|
||||
LOAD_EVENT_TYPE(SCALEDFONTDESTRUCTION, RecordedScaledFontDestruction);
|
||||
LOAD_EVENT_TYPE(MASKSURFACE, RecordedMaskSurface);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
@ -1216,5 +1217,40 @@ RecordedScaledFontDestruction::OutputSimpleEventInfo(stringstream &aStringStream
|
||||
aStringStream << "[" << mRefPtr << "] ScaledFont Destroyed";
|
||||
}
|
||||
|
||||
void
|
||||
RecordedMaskSurface::PlayEvent(Translator *aTranslator) const
|
||||
{
|
||||
aTranslator->LookupDrawTarget(mDT)->
|
||||
MaskSurface(*GenericPattern(mPattern, aTranslator),
|
||||
aTranslator->LookupSourceSurface(mRefMask),
|
||||
mOffset, mOptions);
|
||||
}
|
||||
|
||||
void
|
||||
RecordedMaskSurface::RecordToStream(ostream &aStream) const
|
||||
{
|
||||
RecordedDrawingEvent::RecordToStream(aStream);
|
||||
RecordPatternData(aStream, mPattern);
|
||||
WriteElement(aStream, mRefMask);
|
||||
WriteElement(aStream, mOffset);
|
||||
WriteElement(aStream, mOptions);
|
||||
}
|
||||
|
||||
RecordedMaskSurface::RecordedMaskSurface(istream &aStream)
|
||||
: RecordedDrawingEvent(MASKSURFACE, aStream)
|
||||
{
|
||||
ReadPatternData(aStream, mPattern);
|
||||
ReadElement(aStream, mRefMask);
|
||||
ReadElement(aStream, mOffset);
|
||||
ReadElement(aStream, mOptions);
|
||||
}
|
||||
|
||||
void
|
||||
RecordedMaskSurface::OutputSimpleEventInfo(stringstream &aStringStream) const
|
||||
{
|
||||
aStringStream << "[" << mDT << "] MaskSurface (" << mRefMask << ") Offset: (" << mOffset.x << "x" << mOffset.y << ") Pattern: ";
|
||||
OutputSimplePatternInfo(mPattern, aStringStream);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ namespace gfx {
|
||||
const uint16_t kMajorRevision = 2;
|
||||
// A change in minor revision means additions of new events. New streams will
|
||||
// not play in older players.
|
||||
const uint16_t kMinorRevision = 0;
|
||||
const uint16_t kMinorRevision = 1;
|
||||
|
||||
struct ReferencePtr
|
||||
{
|
||||
@ -160,7 +160,8 @@ public:
|
||||
GRADIENTSTOPSDESTRUCTION,
|
||||
SNAPSHOT,
|
||||
SCALEDFONTCREATION,
|
||||
SCALEDFONTDESTRUCTION
|
||||
SCALEDFONTDESTRUCTION,
|
||||
MASKSURFACE
|
||||
};
|
||||
|
||||
virtual void PlayEvent(Translator *aTranslator) const {}
|
||||
@ -865,6 +866,33 @@ private:
|
||||
RecordedScaledFontDestruction(std::istream &aStream);
|
||||
};
|
||||
|
||||
class RecordedMaskSurface : public RecordedDrawingEvent {
|
||||
public:
|
||||
RecordedMaskSurface(DrawTarget *aDT, const Pattern &aPattern, ReferencePtr aRefMask,
|
||||
const Point &aOffset, const DrawOptions &aOptions)
|
||||
: RecordedDrawingEvent(MASKSURFACE, aDT), mRefMask(aRefMask), mOffset(aOffset)
|
||||
, mOptions(aOptions)
|
||||
{
|
||||
StorePattern(mPattern, aPattern);
|
||||
}
|
||||
|
||||
virtual void PlayEvent(Translator *aTranslator) const;
|
||||
|
||||
virtual void RecordToStream(std::ostream &aStream) const;
|
||||
virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
|
||||
|
||||
virtual std::string GetName() const { return "MaskSurface"; }
|
||||
private:
|
||||
friend class RecordedEvent;
|
||||
|
||||
RecordedMaskSurface(std::istream &aStream);
|
||||
|
||||
PatternStorage mPattern;
|
||||
ReferencePtr mRefMask;
|
||||
Point mOffset;
|
||||
DrawOptions mOptions;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,6 +88,7 @@ static const char *sExtensionNames[] = {
|
||||
"GL_OES_element_index_uint",
|
||||
"GL_OES_vertex_array_object",
|
||||
"GL_ARB_vertex_array_object",
|
||||
"GL_APPLE_vertex_array_object",
|
||||
"GL_ARB_draw_buffers",
|
||||
"GL_EXT_draw_buffers",
|
||||
nullptr
|
||||
@ -552,11 +553,12 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
|
||||
}
|
||||
}
|
||||
|
||||
if (IsExtensionSupported(OES_vertex_array_object)) {
|
||||
if (IsExtensionSupported(ARB_vertex_array_object) ||
|
||||
IsExtensionSupported(OES_vertex_array_object)) {
|
||||
SymLoadStruct vaoSymbols[] = {
|
||||
{ (PRFuncPtr*) &mSymbols.fIsVertexArray, { "IsVertexArray", "IsVertexArrayOES", nullptr } },
|
||||
{ (PRFuncPtr*) &mSymbols.fGenVertexArrays, { "GenVertexArrays", "GenVertexArraysOES", nullptr } },
|
||||
{ (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArrays", "BindVertexArrayOES", nullptr } },
|
||||
{ (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArray", "BindVertexArrayOES", nullptr } },
|
||||
{ (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, { "DeleteVertexArrays", "DeleteVertexArraysOES", nullptr } },
|
||||
{ nullptr, { nullptr } },
|
||||
};
|
||||
@ -564,7 +566,32 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
|
||||
if (!LoadSymbols(&vaoSymbols[0], trygl, prefix)) {
|
||||
NS_ERROR("GL supports Vertex Array Object without supplying its functions.");
|
||||
|
||||
MarkExtensionUnsupported(ARB_vertex_array_object);
|
||||
MarkExtensionUnsupported(OES_vertex_array_object);
|
||||
MarkExtensionUnsupported(APPLE_vertex_array_object);
|
||||
mSymbols.fIsVertexArray = nullptr;
|
||||
mSymbols.fGenVertexArrays = nullptr;
|
||||
mSymbols.fBindVertexArray = nullptr;
|
||||
mSymbols.fDeleteVertexArrays = nullptr;
|
||||
}
|
||||
}
|
||||
else if (IsExtensionSupported(APPLE_vertex_array_object)) {
|
||||
/*
|
||||
* separate call to LoadSymbols with APPLE_vertex_array_object to work around
|
||||
* a driver bug : the IsVertexArray symbol (without suffix) can be present but unusable.
|
||||
*/
|
||||
SymLoadStruct vaoSymbols[] = {
|
||||
{ (PRFuncPtr*) &mSymbols.fIsVertexArray, { "IsVertexArrayAPPLE", nullptr } },
|
||||
{ (PRFuncPtr*) &mSymbols.fGenVertexArrays, { "GenVertexArraysAPPLE", nullptr } },
|
||||
{ (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArrayAPPLE", nullptr } },
|
||||
{ (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, { "DeleteVertexArraysAPPLE", nullptr } },
|
||||
{ nullptr, { nullptr } },
|
||||
};
|
||||
|
||||
if (!LoadSymbols(&vaoSymbols[0], trygl, prefix)) {
|
||||
NS_ERROR("GL supports Vertex Array Object without supplying its functions.");
|
||||
|
||||
MarkExtensionUnsupported(APPLE_vertex_array_object);
|
||||
mSymbols.fIsVertexArray = nullptr;
|
||||
mSymbols.fGenVertexArrays = nullptr;
|
||||
mSymbols.fBindVertexArray = nullptr;
|
||||
|
@ -1026,6 +1026,7 @@ public:
|
||||
OES_element_index_uint,
|
||||
OES_vertex_array_object,
|
||||
ARB_vertex_array_object,
|
||||
APPLE_vertex_array_object,
|
||||
ARB_draw_buffers,
|
||||
EXT_draw_buffers,
|
||||
Extensions_Max
|
||||
|
@ -3029,6 +3029,9 @@ typedef uint64_t EGLTime;
|
||||
#define LOCAL_GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC
|
||||
#define LOCAL_GL_WIN_swap_hint 1
|
||||
|
||||
// ARB_vertex_array_object
|
||||
#define LOCAL_GL_VERTEX_ARRAY_BINDING 0x85B5
|
||||
|
||||
// ARB_sync
|
||||
#define LOCAL_GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
|
||||
#define LOCAL_GL_OBJECT_TYPE 0x9112
|
||||
|
@ -7,7 +7,7 @@
|
||||
#ifndef js_GCAPI_h
|
||||
#define js_GCAPI_h
|
||||
|
||||
#include "HeapAPI.h"
|
||||
#include "js/HeapAPI.h"
|
||||
|
||||
namespace JS {
|
||||
|
||||
|
@ -11,8 +11,8 @@
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
#include "TemplateLib.h"
|
||||
#include "Utility.h"
|
||||
#include "js/TemplateLib.h"
|
||||
#include "js/Utility.h"
|
||||
|
||||
/* Silence dire "bugs in previous versions of MSVC have been fixed" warnings */
|
||||
#ifdef _MSC_VER
|
||||
|
@ -117,11 +117,6 @@ else
|
||||
LOCAL_INCLUDES = -Ictypes/libffi/include
|
||||
endif
|
||||
|
||||
LOCAL_INCLUDES += \
|
||||
-I. \
|
||||
$(NULL)
|
||||
|
||||
|
||||
ifdef MOZ_NATIVE_FFI
|
||||
EXTRA_DSO_LDOPTS += $(MOZ_FFI_LIBS)
|
||||
else
|
||||
@ -682,8 +677,6 @@ ifneq (,$(ENABLE_YARR_JIT))
|
||||
CXXFLAGS += -DENABLE_JIT=1
|
||||
endif
|
||||
|
||||
INCLUDES += -I$(srcdir)/assembler -I$(srcdir)/yarr
|
||||
|
||||
#
|
||||
# END kludges for the Nitro assembler
|
||||
###############################################
|
||||
|
@ -17,12 +17,12 @@
|
||||
#define USE_SYSTEM_MALLOC 1
|
||||
// leads to FORCE_SYSTEM_MALLOC in wtf/FastMalloc.cpp
|
||||
|
||||
#include <jit/ExecutableAllocator.h>
|
||||
#include <assembler/LinkBuffer.h>
|
||||
#include <assembler/CodeLocation.h>
|
||||
#include <assembler/RepatchBuffer.h>
|
||||
#include "assembler/jit/ExecutableAllocator.h"
|
||||
#include "assembler/assembler/LinkBuffer.h"
|
||||
#include "assembler/assembler/CodeLocation.h"
|
||||
#include "assembler/assembler/RepatchBuffer.h"
|
||||
|
||||
#include <assembler/MacroAssembler.h>
|
||||
#include "assembler/assembler/MacroAssembler.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#if ENABLE_ASSEMBLER && WTF_CPU_ARM_TRADITIONAL
|
||||
|
||||
#include "ARMAssembler.h"
|
||||
#include "assembler/assembler/ARMAssembler.h"
|
||||
|
||||
namespace JSC {
|
||||
|
||||
|
@ -38,7 +38,7 @@
|
||||
|
||||
#if ENABLE_ASSEMBLER && WTF_CPU_ARM_TRADITIONAL
|
||||
|
||||
#include "AssemblerBufferWithConstantPool.h"
|
||||
#include "assembler/assembler/AssemblerBufferWithConstantPool.h"
|
||||
#include "assembler/wtf/Assertions.h"
|
||||
|
||||
// TODO: We don't print the condition code in our spew lines. Doing this
|
||||
|
@ -35,9 +35,8 @@
|
||||
|
||||
#if ENABLE(ASSEMBLER) && CPU(ARM_THUMB2)
|
||||
|
||||
#include "AssemblerBuffer.h"
|
||||
#include "assembler/assembler/AssemblerBuffer.h"
|
||||
#include "assembler/wtf/Assertions.h"
|
||||
#include "assembler/wtf/Vector.h"
|
||||
#include <stdint.h>
|
||||
|
||||
namespace JSC {
|
||||
|
@ -35,7 +35,7 @@
|
||||
|
||||
#if ENABLE_ASSEMBLER
|
||||
|
||||
#include "AssemblerBuffer.h"
|
||||
#include "assembler/assembler/AssemblerBuffer.h"
|
||||
#include "assembler/wtf/SegmentedVector.h"
|
||||
#include "assembler/wtf/Assertions.h"
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
#if ENABLE_ASSEMBLER
|
||||
|
||||
#include <assembler/MacroAssembler.h>
|
||||
#include "assembler/assembler/MacroAssembler.h"
|
||||
|
||||
namespace JSC {
|
||||
|
||||
|
@ -31,11 +31,10 @@
|
||||
|
||||
#if ENABLE(ASSEMBLER) && CPU(MIPS)
|
||||
|
||||
#include "AssemblerBuffer.h"
|
||||
#include "assembler/assembler/AssemblerBuffer.h"
|
||||
#include "assembler/wtf/Assertions.h"
|
||||
#include "assembler/wtf/SegmentedVector.h"
|
||||
|
||||
#include "methodjit/Logging.h"
|
||||
#define IPFX " %s"
|
||||
#define ISPFX " "
|
||||
#ifdef JS_METHODJIT_SPEW
|
||||
|
@ -35,27 +35,27 @@
|
||||
#if ENABLE_ASSEMBLER
|
||||
|
||||
#if WTF_CPU_ARM_THUMB2
|
||||
#include "MacroAssemblerARMv7.h"
|
||||
#include "assembler/assembler/MacroAssemblerARMv7.h"
|
||||
namespace JSC { typedef MacroAssemblerARMv7 MacroAssemblerBase; }
|
||||
|
||||
#elif WTF_CPU_ARM_TRADITIONAL
|
||||
#include "MacroAssemblerARM.h"
|
||||
#include "assembler/assembler/MacroAssemblerARM.h"
|
||||
namespace JSC { typedef MacroAssemblerARM MacroAssemblerBase; }
|
||||
|
||||
#elif WTF_CPU_MIPS
|
||||
#include "MacroAssemblerMIPS.h"
|
||||
#include "assembler/assembler/MacroAssemblerMIPS.h"
|
||||
namespace JSC { typedef MacroAssemblerMIPS MacroAssemblerBase; }
|
||||
|
||||
#elif WTF_CPU_X86
|
||||
#include "MacroAssemblerX86.h"
|
||||
#include "assembler/assembler/MacroAssemblerX86.h"
|
||||
namespace JSC { typedef MacroAssemblerX86 MacroAssemblerBase; }
|
||||
|
||||
#elif WTF_CPU_X86_64
|
||||
#include "MacroAssemblerX86_64.h"
|
||||
#include "assembler/assembler/MacroAssemblerX86_64.h"
|
||||
namespace JSC { typedef MacroAssemblerX86_64 MacroAssemblerBase; }
|
||||
|
||||
#elif WTF_CPU_SPARC
|
||||
#include "MacroAssemblerSparc.h"
|
||||
#include "assembler/assembler/MacroAssemblerSparc.h"
|
||||
namespace JSC { typedef MacroAssemblerSparc MacroAssemblerBase; }
|
||||
|
||||
#else
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#if ENABLE_ASSEMBLER && WTF_CPU_ARM_TRADITIONAL
|
||||
|
||||
#include "MacroAssemblerARM.h"
|
||||
#include "assembler/assembler/MacroAssemblerARM.h"
|
||||
|
||||
#if WTF_OS_LINUX || WTF_OS_ANDROID
|
||||
#include <sys/types.h>
|
||||
|
@ -36,8 +36,8 @@
|
||||
|
||||
#if ENABLE_ASSEMBLER && WTF_CPU_ARM_TRADITIONAL
|
||||
|
||||
#include "ARMAssembler.h"
|
||||
#include "AbstractMacroAssembler.h"
|
||||
#include "assembler/assembler/ARMAssembler.h"
|
||||
#include "assembler/assembler/AbstractMacroAssembler.h"
|
||||
|
||||
namespace JSC {
|
||||
|
||||
|
@ -35,8 +35,8 @@
|
||||
|
||||
#if ENABLE(ASSEMBLER)
|
||||
|
||||
#include "ARMv7Assembler.h"
|
||||
#include "AbstractMacroAssembler.h"
|
||||
#include "assembler/assembler/ARMv7Assembler.h"
|
||||
#include "assembler/assembler/AbstractMacroAssembler.h"
|
||||
|
||||
namespace JSC {
|
||||
|
||||
|
@ -29,8 +29,8 @@
|
||||
|
||||
#if ENABLE(ASSEMBLER) && CPU(MIPS)
|
||||
|
||||
#include "AbstractMacroAssembler.h"
|
||||
#include "MIPSAssembler.h"
|
||||
#include "assembler/assembler/AbstractMacroAssembler.h"
|
||||
#include "assembler/assembler/MIPSAssembler.h"
|
||||
|
||||
namespace JSC {
|
||||
|
||||
|
@ -7,12 +7,12 @@
|
||||
#ifndef assembler_assembler_MacroAssemblerSparc_h
|
||||
#define assembler_assembler_MacroAssemblerSparc_h
|
||||
|
||||
#include <assembler/wtf/Platform.h>
|
||||
#include "assembler/wtf/Platform.h"
|
||||
|
||||
#if ENABLE_ASSEMBLER && WTF_CPU_SPARC
|
||||
|
||||
#include "SparcAssembler.h"
|
||||
#include "AbstractMacroAssembler.h"
|
||||
#include "assembler/assembler/SparcAssembler.h"
|
||||
#include "assembler/assembler/AbstractMacroAssembler.h"
|
||||
|
||||
namespace JSC {
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user