зеркало из https://github.com/mozilla/pjs.git
Merge central to inbound
This commit is contained in:
Коммит
ffb7928663
|
@ -1028,6 +1028,9 @@ pref("devtools.errorconsole.enabled", false);
|
|||
// Enable the Inspector
|
||||
pref("devtools.inspector.enabled", true);
|
||||
pref("devtools.inspector.htmlHeight", 112);
|
||||
pref("devtools.inspector.htmlPanelOpen", false);
|
||||
pref("devtools.inspector.sidebarOpen", false);
|
||||
pref("devtools.inspector.activeSidebar", "ruleview");
|
||||
|
||||
// Enable the Debugger
|
||||
pref("devtools.debugger.enabled", false);
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
# Shawn Wilsher <me@shawnwilsher.com>
|
||||
# Ehsan Akhgari <ehsan.akhgari@gmail.com>
|
||||
# Rob Campbell <rcampbell@mozilla.com>
|
||||
# Paul Rouget <paul@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -153,6 +154,14 @@
|
|||
oncommand="InspectorUI.toggleSidebar();"/>
|
||||
<command id="Inspector:Tilt"
|
||||
oncommand="Tilt.initialize();"/>
|
||||
<command id="Inspector:HTMLPanel"
|
||||
oncommand="InspectorUI.toggleHTMLPanel();"/>
|
||||
<command id="Inspector:CopyInner"
|
||||
oncommand="InspectorUI.copyInnerHTML();"/>
|
||||
<command id="Inspector:CopyOuter"
|
||||
oncommand="InspectorUI.copyOuterHTML();"/>
|
||||
<command id="Inspector:DeleteNode"
|
||||
oncommand="InspectorUI.deleteNode();"/>
|
||||
</commandset>
|
||||
|
||||
<broadcasterset id="mainBroadcasterSet">
|
||||
|
@ -167,7 +176,7 @@
|
|||
type="checkbox" group="sidebar"
|
||||
sidebarurl="chrome://browser/content/history/history-panel.xul"
|
||||
oncommand="toggleSidebar('viewHistorySidebar');"/>
|
||||
|
||||
|
||||
<broadcaster id="viewWebPanelsSidebar" autoCheck="false"
|
||||
type="checkbox" group="sidebar" sidebarurl="chrome://browser/content/web-panels.xul"
|
||||
oncommand="toggleSidebar('viewWebPanelsSidebar');"/>
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
# David Dahl <ddahl@mozilla.com>
|
||||
# Frank Yan <fyan@mozilla.com>
|
||||
# Victor Porof <vporof@mozilla.com>
|
||||
# Paul Rouget <paul@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -227,20 +228,21 @@
|
|||
</hbox>
|
||||
</panel>
|
||||
|
||||
<panel id="inspector-tree-panel"
|
||||
orient="vertical"
|
||||
hidden="true"
|
||||
ignorekeys="true"
|
||||
noautofocus="true"
|
||||
noautohide="true"
|
||||
titlebar="normal"
|
||||
close="true"
|
||||
label="&inspectPanelTitle.label;">
|
||||
<hbox id="tree-panel-resizer-box" align="end">
|
||||
<spacer flex="1" />
|
||||
<resizer dir="bottomend" />
|
||||
</hbox>
|
||||
</panel>
|
||||
<menupopup id="inspector-node-popup">
|
||||
<menuitem id="inspectorHTMLCopyInner"
|
||||
label="&inspectorHTMLCopyInner.label;"
|
||||
accesskey="&inspectorHTMLCopyInner.accesskey;"
|
||||
command="Inspector:CopyInner"/>
|
||||
<menuitem id="inspectorHTMLCopyOuter"
|
||||
label="&inspectorHTMLCopyOuter.label;"
|
||||
accesskey="&inspectorHTMLCopyOuter.accesskey;"
|
||||
command="Inspector:CopyOuter"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="inspectorHTMLDelete"
|
||||
label="&inspectorHTMLDelete.label;"
|
||||
accesskey="&inspectorHTMLDelete.accesskey;"
|
||||
command="Inspector:DeleteNode"/>
|
||||
</menupopup>
|
||||
|
||||
<menupopup id="toolbar-context-menu"
|
||||
onpopupshowing="onViewToolbarsPopupShowing(event);">
|
||||
|
@ -994,45 +996,44 @@
|
|||
class="devtools-toolbar"
|
||||
nowindowdrag="true"
|
||||
hidden="true">
|
||||
<vbox flex="1">
|
||||
<resizer id="inspector-top-resizer" flex="1"
|
||||
dir="top" disabled="true"
|
||||
element="inspector-tree-box"/>
|
||||
<hbox>
|
||||
#ifdef XP_MACOSX
|
||||
<toolbarbutton id="highlighter-closebutton"
|
||||
oncommand="InspectorUI.closeInspectorUI(false);"
|
||||
tooltiptext="&inspectCloseButton.tooltiptext;"/>
|
||||
<toolbarbutton id="highlighter-closebutton"
|
||||
oncommand="InspectorUI.closeInspectorUI(false);"
|
||||
tooltiptext="&inspectCloseButton.tooltiptext;"/>
|
||||
#endif
|
||||
<toolbarbutton id="inspector-inspect-toolbutton"
|
||||
class="devtools-toolbarbutton"
|
||||
label="&inspectButton.label;"
|
||||
accesskey="&inspectButton.accesskey;"
|
||||
command="Inspector:Inspect"/>
|
||||
<arrowscrollbox id="inspector-breadcrumbs"
|
||||
flex="1" orient="horizontal"
|
||||
clicktoscroll="true"/>
|
||||
<hbox id="inspector-tools">
|
||||
<toolbarbutton id="inspector-3D-button"
|
||||
class="devtools-toolbarbutton"
|
||||
hidden="true"
|
||||
label="&inspect3DViewButton.label;"
|
||||
accesskey="&inspect3DViewButton.accesskey;"
|
||||
command="Inspector:Tilt"/>
|
||||
<toolbarbutton id="inspector-style-button"
|
||||
class="devtools-toolbarbutton"
|
||||
label="&inspectStyleButton.label;"
|
||||
accesskey="&inspectStyleButton.accesskey;"
|
||||
command="Inspector:Sidebar"/>
|
||||
<!-- registered tools go here -->
|
||||
</hbox>
|
||||
<toolbarbutton id="inspector-inspect-toolbutton"
|
||||
class="devtools-toolbarbutton"
|
||||
label="&inspectButton.label;"
|
||||
accesskey="&inspectButton.accesskey;"
|
||||
command="Inspector:Inspect"/>
|
||||
<toolbarbutton id="inspector-treepanel-toolbutton"
|
||||
class="devtools-toolbarbutton"
|
||||
label="&htmlPanel.label;"
|
||||
accesskey="&htmlPanel.accesskey;"
|
||||
tooltiptext="&htmlPanel.tooltiptext;"
|
||||
command="Inspector:HTMLPanel"/>
|
||||
<arrowscrollbox id="inspector-breadcrumbs"
|
||||
flex="1" orient="horizontal"
|
||||
clicktoscroll="true"/>
|
||||
<hbox id="inspector-tools">
|
||||
<toolbarbutton id="inspector-3D-button"
|
||||
class="devtools-toolbarbutton"
|
||||
hidden="true"
|
||||
label="&inspect3DViewButton.label;"
|
||||
accesskey="&inspect3DViewButton.accesskey;"
|
||||
command="Inspector:Tilt"/>
|
||||
<toolbarbutton id="inspector-style-button"
|
||||
class="devtools-toolbarbutton"
|
||||
label="&inspectStyleButton.label;"
|
||||
accesskey="&inspectStyleButton.accesskey;"
|
||||
command="Inspector:Sidebar"/>
|
||||
<!-- registered tools go here -->
|
||||
</hbox>
|
||||
#ifndef XP_MACOSX
|
||||
<toolbarbutton id="highlighter-closebutton"
|
||||
oncommand="InspectorUI.closeInspectorUI(false);"
|
||||
tooltiptext="&inspectCloseButton.tooltiptext;"/>
|
||||
<toolbarbutton id="highlighter-closebutton"
|
||||
oncommand="InspectorUI.closeInspectorUI(false);"
|
||||
tooltiptext="&inspectCloseButton.tooltiptext;"/>
|
||||
#endif
|
||||
</hbox>
|
||||
</vbox>
|
||||
</toolbar>
|
||||
<toolbar id="addon-bar"
|
||||
toolbarname="&addonBarCmd.label;" accesskey="&addonBarCmd.accesskey;"
|
||||
|
|
|
@ -34,14 +34,6 @@
|
|||
direction: ltr;
|
||||
}
|
||||
|
||||
#inspector-top-resizer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#inspector-toolbar[treepanel-open] > vbox > #inspector-top-resizer {
|
||||
display: -moz-box;
|
||||
}
|
||||
|
||||
/*
|
||||
* Node Infobar
|
||||
*/
|
||||
|
|
|
@ -349,7 +349,7 @@ DebuggerView.Properties = {
|
|||
}
|
||||
|
||||
// compute the id of the element if not specified
|
||||
aId = aId || (aName + "-scope");
|
||||
aId = aId || (aName.toLowerCase().trim().replace(" ", "-") + "-scope");
|
||||
|
||||
// contains generic nodes and functionality
|
||||
let element = this._createPropertyElement(aName, aId, "scope", this._vars);
|
||||
|
@ -541,12 +541,12 @@ DebuggerView.Properties = {
|
|||
* An array containing the key and grip properties, specifying
|
||||
* the value and/or type & class of the variable (if the type
|
||||
* is not specified, it will be inferred from the value).
|
||||
* e.g. ["someProp0": 42]
|
||||
* ["someProp1": true]
|
||||
* ["someProp2": "nasu"]
|
||||
* ["someProp3": { type: "undefined" }]
|
||||
* ["someProp4": { type: "null" }]
|
||||
* ["someProp5": { type: "object", class: "Object" }]
|
||||
* e.g. ["someProp0", 42]
|
||||
* ["someProp1", true]
|
||||
* ["someProp2", "nasu"]
|
||||
* ["someProp3", { type: "undefined" }]
|
||||
* ["someProp4", { type: "null" }]
|
||||
* ["someProp5", { type: "object", class: "Object" }]
|
||||
* @param string aName
|
||||
* Optional, the property name.
|
||||
* @paarm string aId
|
||||
|
|
|
@ -34,7 +34,8 @@ function test_early_debugger_statement(aActor)
|
|||
gClient.addListener("paused", paused);
|
||||
// This should continue without nesting an event loop and calling
|
||||
// the onPaused hook, because we haven't attached yet.
|
||||
gTab.linkedBrowser.contentWindow.wrappedJSObject.runDebuggerStatement();
|
||||
// TODO: uncomment this when bug 723563 is fixed.
|
||||
//gTab.linkedBrowser.contentWindow.wrappedJSObject.runDebuggerStatement();
|
||||
|
||||
gClient.removeListener("paused", paused);
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ function test_attach_removed_tab()
|
|||
});
|
||||
|
||||
gClient.request({ to: gTab2Actor, type: "attach" }, function(aResponse) {
|
||||
is(aResponse.type, "exited", "Tab should consider itself exited.");
|
||||
is(aResponse.error, "noSuchActor", "Tab should be gone.");
|
||||
finish_test();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ function TreePanel(aContext, aIUI) {
|
|||
TreePanel.prototype = {
|
||||
showTextNodesWithWhitespace: false,
|
||||
id: "treepanel", // DO NOT LOCALIZE
|
||||
openInDock: true,
|
||||
_open: false,
|
||||
|
||||
/**
|
||||
* The tree panel container element.
|
||||
|
@ -75,11 +75,7 @@ TreePanel.prototype = {
|
|||
*/
|
||||
get container()
|
||||
{
|
||||
if (this.openInDock) {
|
||||
return this.document.getElementById("inspector-tree-box");
|
||||
}
|
||||
|
||||
return this.document.getElementById("inspector-tree-panel");
|
||||
return this.document.getElementById("inspector-tree-box");
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -93,6 +89,8 @@ TreePanel.prototype = {
|
|||
this.IUI = aIUI;
|
||||
this.window = aContext;
|
||||
this.document = this.window.document;
|
||||
this.button =
|
||||
this.IUI.chromeDoc.getElementById("inspector-treepanel-toolbutton");
|
||||
|
||||
domplateUtils.setDOM(this.window);
|
||||
|
||||
|
@ -100,28 +98,7 @@ TreePanel.prototype = {
|
|||
|
||||
let isOpen = this.isOpen.bind(this);
|
||||
|
||||
this.registrationObject = {
|
||||
id: this.id,
|
||||
label: this.IUI.strings.GetStringFromName("htmlPanel.label"),
|
||||
tooltiptext: this.IUI.strings.GetStringFromName("htmlPanel.tooltiptext"),
|
||||
accesskey: this.IUI.strings.GetStringFromName("htmlPanel.accesskey"),
|
||||
context: this,
|
||||
get isOpen() isOpen(),
|
||||
show: this.open,
|
||||
hide: this.close,
|
||||
onSelect: this.select,
|
||||
panel: this.openInDock ? null : this.container,
|
||||
unregister: this.destroy,
|
||||
};
|
||||
this.editingEvents = {};
|
||||
|
||||
if (!this.openInDock) {
|
||||
this._boundClose = this.close.bind(this);
|
||||
this.container.addEventListener("popuphiding", this._boundClose, false);
|
||||
}
|
||||
|
||||
// Register the HTML panel with the highlighter
|
||||
this.IUI.registerTool(this.registrationObject);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -154,13 +131,14 @@ TreePanel.prototype = {
|
|||
*/
|
||||
open: function TP_open()
|
||||
{
|
||||
if (this.initializingTreePanel && !this.treeLoaded) {
|
||||
if (this._open) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._open = true;
|
||||
|
||||
this.button.setAttribute("checked", true);
|
||||
this.initializingTreePanel = true;
|
||||
if (!this.openInDock)
|
||||
this.container.hidden = false;
|
||||
|
||||
this.treeIFrame = this.document.getElementById("inspector-tree-iframe");
|
||||
if (!this.treeIFrame) {
|
||||
|
@ -168,65 +146,13 @@ TreePanel.prototype = {
|
|||
this.treeIFrame.setAttribute("id", "inspector-tree-iframe");
|
||||
this.treeIFrame.flex = 1;
|
||||
this.treeIFrame.setAttribute("type", "content");
|
||||
this.treeIFrame.setAttribute("context", "inspector-node-popup");
|
||||
}
|
||||
|
||||
if (this.openInDock) { // Create vbox
|
||||
this.openDocked();
|
||||
return;
|
||||
}
|
||||
|
||||
let resizerBox = this.document.getElementById("tree-panel-resizer-box");
|
||||
this.treeIFrame = this.container.insertBefore(this.treeIFrame, resizerBox);
|
||||
|
||||
let boundLoadedInitializeTreePanel = function loadedInitializeTreePanel()
|
||||
{
|
||||
this.treeIFrame.removeEventListener("load",
|
||||
boundLoadedInitializeTreePanel, true);
|
||||
this.initializeIFrame();
|
||||
}.bind(this);
|
||||
|
||||
let boundTreePanelShown = function treePanelShown()
|
||||
{
|
||||
this.container.removeEventListener("popupshown",
|
||||
boundTreePanelShown, false);
|
||||
|
||||
this.treeIFrame.addEventListener("load",
|
||||
boundLoadedInitializeTreePanel, true);
|
||||
|
||||
let src = this.treeIFrame.getAttribute("src");
|
||||
if (src != INSPECTOR_URI) {
|
||||
this.treeIFrame.setAttribute("src", INSPECTOR_URI);
|
||||
} else {
|
||||
this.treeIFrame.contentWindow.location.reload();
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
this.container.addEventListener("popupshown", boundTreePanelShown, false);
|
||||
|
||||
const panelWidthRatio = 7 / 8;
|
||||
const panelHeightRatio = 1 / 5;
|
||||
|
||||
let width = parseInt(this.IUI.win.outerWidth * panelWidthRatio);
|
||||
let height = parseInt(this.IUI.win.outerHeight * panelHeightRatio);
|
||||
let y = Math.min(this.document.defaultView.screen.availHeight - height,
|
||||
this.IUI.win.innerHeight);
|
||||
|
||||
this.container.openPopup(this.browser, "overlap", 0, 0,
|
||||
false, false);
|
||||
|
||||
this.container.moveTo(80, y);
|
||||
this.container.sizeTo(width, height);
|
||||
},
|
||||
|
||||
openDocked: function TP_openDocked()
|
||||
{
|
||||
let treeBox = null;
|
||||
let toolbar = this.IUI.toolbar.nextSibling; // Addons bar, typically
|
||||
let toolbarParent =
|
||||
this.IUI.browser.ownerDocument.getElementById("browser-bottombox");
|
||||
treeBox = this.document.createElement("vbox");
|
||||
treeBox.id = "inspector-tree-box";
|
||||
treeBox.state = "open"; // for the registerTools API.
|
||||
treeBox.state = "open";
|
||||
try {
|
||||
treeBox.height =
|
||||
Services.prefs.getIntPref("devtools.inspector.htmlHeight");
|
||||
|
@ -235,22 +161,26 @@ TreePanel.prototype = {
|
|||
}
|
||||
|
||||
treeBox.minHeight = 64;
|
||||
treeBox.flex = 1;
|
||||
toolbarParent.insertBefore(treeBox, toolbar);
|
||||
|
||||
this.IUI.toolbar.setAttribute("treepanel-open", "true");
|
||||
this.splitter = this.document.createElement("splitter");
|
||||
this.splitter.id = "inspector-tree-splitter";
|
||||
|
||||
let container = this.document.getElementById("appcontent");
|
||||
container.appendChild(this.splitter);
|
||||
container.appendChild(treeBox);
|
||||
|
||||
treeBox.appendChild(this.treeIFrame);
|
||||
|
||||
let boundLoadedInitializeTreePanel = function loadedInitializeTreePanel()
|
||||
this._boundLoadedInitializeTreePanel = function loadedInitializeTreePanel()
|
||||
{
|
||||
this.treeIFrame.removeEventListener("load",
|
||||
boundLoadedInitializeTreePanel, true);
|
||||
this._boundLoadedInitializeTreePanel, true);
|
||||
delete this._boundLoadedInitializeTreePanel;
|
||||
this.initializeIFrame();
|
||||
}.bind(this);
|
||||
|
||||
this.treeIFrame.addEventListener("load",
|
||||
boundLoadedInitializeTreePanel, true);
|
||||
this._boundLoadedInitializeTreePanel, true);
|
||||
|
||||
let src = this.treeIFrame.getAttribute("src");
|
||||
if (src != INSPECTOR_URI) {
|
||||
|
@ -265,17 +195,22 @@ TreePanel.prototype = {
|
|||
*/
|
||||
close: function TP_close()
|
||||
{
|
||||
if (this.openInDock) {
|
||||
this.IUI.toolbar.removeAttribute("treepanel-open");
|
||||
this._open = false;
|
||||
|
||||
let treeBox = this.container;
|
||||
Services.prefs.setIntPref("devtools.inspector.htmlHeight", treeBox.height);
|
||||
let treeBoxParent = treeBox.parentNode;
|
||||
treeBoxParent.removeChild(treeBox);
|
||||
} else {
|
||||
this.container.hidePopup();
|
||||
// Stop caring about the tree iframe load if it's in progress.
|
||||
if (this._boundLoadedInitializeTreePanel) {
|
||||
this.treeIFrame.removeEventListener("load",
|
||||
this._boundLoadedInitializeTreePanel, true);
|
||||
delete this._boundLoadedInitializeTreePanel;
|
||||
}
|
||||
|
||||
this.button.removeAttribute("checked");
|
||||
let treeBox = this.container;
|
||||
Services.prefs.setIntPref("devtools.inspector.htmlHeight", treeBox.height);
|
||||
let treeBoxParent = treeBox.parentNode;
|
||||
treeBoxParent.removeChild(this.splitter);
|
||||
treeBoxParent.removeChild(treeBox);
|
||||
|
||||
if (this.treePanelDiv) {
|
||||
this.treePanelDiv.ownerPanel = null;
|
||||
let parent = this.treePanelDiv.parentNode;
|
||||
|
@ -293,10 +228,15 @@ TreePanel.prototype = {
|
|||
*/
|
||||
isOpen: function TP_isOpen()
|
||||
{
|
||||
if (this.openInDock)
|
||||
return this.treeLoaded && this.container;
|
||||
return this._open;
|
||||
},
|
||||
|
||||
return this.treeLoaded && this.container.state == "open";
|
||||
/**
|
||||
* Toggle the TreePanel.
|
||||
*/
|
||||
toggle: function TP_toggle()
|
||||
{
|
||||
this.isOpen() ? this.close() : this.open();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -669,6 +609,20 @@ TreePanel.prototype = {
|
|||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove a node box from the tree view.
|
||||
* @param aElement
|
||||
* The DOM node to remove from the HTML IOBox.
|
||||
*/
|
||||
deleteChildBox: function TP_deleteChildBox(aElement)
|
||||
{
|
||||
let childBox = this.ioBox.findObjectBox(aElement);
|
||||
if (!childBox) {
|
||||
return;
|
||||
}
|
||||
childBox.parentNode.removeChild(childBox);
|
||||
},
|
||||
|
||||
/**
|
||||
* Destructor function. Cleanup.
|
||||
*/
|
||||
|
@ -705,11 +659,6 @@ TreePanel.prototype = {
|
|||
this.ioBox.destroy();
|
||||
delete this.ioBox;
|
||||
}
|
||||
|
||||
if (!this.openInDock) {
|
||||
this.container.removeEventListener("popuphiding", this._boundClose, false);
|
||||
delete this._boundClose;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -43,7 +43,11 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
var EXPORTED_SYMBOLS = ["Highlighter"];
|
||||
|
||||
|
@ -59,6 +63,9 @@ const INSPECTOR_INVISIBLE_ELEMENTS = {
|
|||
"title": true,
|
||||
};
|
||||
|
||||
const PSEUDO_CLASSES = [":hover", ":active", ":focus"];
|
||||
// add ":visited" and ":link" after bug 713106 is fixed
|
||||
|
||||
/**
|
||||
* A highlighter mechanism.
|
||||
*
|
||||
|
@ -109,6 +116,8 @@ const INSPECTOR_INVISIBLE_ELEMENTS = {
|
|||
* "highlighting" - Highlighter is highlighting
|
||||
* "locked" - The selected node has been locked
|
||||
* "unlocked" - The selected ndoe has been unlocked
|
||||
* "pseudoclasstoggled" - A pseudo-class lock has changed on the selected node
|
||||
|
||||
*
|
||||
* Structure:
|
||||
*
|
||||
|
@ -238,6 +247,17 @@ Highlighter.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Notify that a pseudo-class lock was toggled on the highlighted element
|
||||
*
|
||||
* @param aPseudo - The pseudo-class to toggle, e.g. ":hover".
|
||||
*/
|
||||
pseudoClassLockToggled: function Highlighter_pseudoClassLockToggled(aPseudo)
|
||||
{
|
||||
this.emitEvent("pseudoclasstoggled", [aPseudo]);
|
||||
this.updateInfobar();
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the highlighter size and position.
|
||||
*/
|
||||
|
@ -446,29 +466,80 @@ Highlighter.prototype = {
|
|||
|
||||
let classesBox = this.chromeDoc.createElementNS("http://www.w3.org/1999/xhtml", "span");
|
||||
classesBox.id = "highlighter-nodeinfobar-classes";
|
||||
|
||||
let pseudoClassesBox = this.chromeDoc.createElementNS("http://www.w3.org/1999/xhtml", "span");
|
||||
pseudoClassesBox.id = "highlighter-nodeinfobar-pseudo-classes";
|
||||
|
||||
// Add some content to force a better boundingClientRect down below.
|
||||
classesBox.textContent = " ";
|
||||
pseudoClassesBox.textContent = " ";
|
||||
|
||||
nodeInfobar.appendChild(tagNameLabel);
|
||||
nodeInfobar.appendChild(idLabel);
|
||||
nodeInfobar.appendChild(classesBox);
|
||||
nodeInfobar.appendChild(pseudoClassesBox);
|
||||
container.appendChild(arrowBoxTop);
|
||||
container.appendChild(nodeInfobar);
|
||||
container.appendChild(arrowBoxBottom);
|
||||
|
||||
aParent.appendChild(container);
|
||||
|
||||
nodeInfobar.onclick = (function _onInfobarRightClick(aEvent) {
|
||||
if (aEvent.button == 2) {
|
||||
this.openPseudoClassMenu();
|
||||
}
|
||||
}).bind(this);
|
||||
|
||||
let barHeight = container.getBoundingClientRect().height;
|
||||
|
||||
this.nodeInfo = {
|
||||
tagNameLabel: tagNameLabel,
|
||||
idLabel: idLabel,
|
||||
classesBox: classesBox,
|
||||
pseudoClassesBox: pseudoClassesBox,
|
||||
container: container,
|
||||
barHeight: barHeight,
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Open the infobar's pseudo-class context menu.
|
||||
*/
|
||||
openPseudoClassMenu: function Highlighter_openPseudoClassMenu()
|
||||
{
|
||||
let menu = this.chromeDoc.createElement("menupopup");
|
||||
menu.id = "infobar-context-menu";
|
||||
|
||||
let popupSet = this.chromeDoc.getElementById("mainPopupSet");
|
||||
popupSet.appendChild(menu);
|
||||
|
||||
let fragment = this.buildPseudoClassMenu();
|
||||
menu.appendChild(fragment);
|
||||
|
||||
menu.openPopup(this.nodeInfo.pseudoClassesBox, "end_before", 0, 0, true, false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Create the menuitems for toggling the selection's pseudo-class state
|
||||
*
|
||||
* @returns DocumentFragment. The menuitems for toggling pseudo-classes.
|
||||
*/
|
||||
buildPseudoClassMenu: function IUI_buildPseudoClassesMenu()
|
||||
{
|
||||
let fragment = this.chromeDoc.createDocumentFragment();
|
||||
for (let i = 0; i < PSEUDO_CLASSES.length; i++) {
|
||||
let pseudo = PSEUDO_CLASSES[i];
|
||||
let item = this.chromeDoc.createElement("menuitem");
|
||||
item.setAttribute("type", "checkbox");
|
||||
item.setAttribute("label", pseudo);
|
||||
item.addEventListener("command",
|
||||
this.pseudoClassLockToggled.bind(this, pseudo), false);
|
||||
item.setAttribute("checked", DOMUtils.hasPseudoClassLock(this.node,
|
||||
pseudo));
|
||||
fragment.appendChild(item);
|
||||
}
|
||||
return fragment;
|
||||
},
|
||||
|
||||
/**
|
||||
* Highlight a rectangular region.
|
||||
*
|
||||
|
@ -543,6 +614,14 @@ Highlighter.prototype = {
|
|||
|
||||
classes.textContent = this.node.classList.length ?
|
||||
"." + Array.join(this.node.classList, ".") : "";
|
||||
|
||||
// Pseudo-classes
|
||||
let pseudos = PSEUDO_CLASSES.filter(function(pseudo) {
|
||||
return DOMUtils.hasPseudoClassLock(this.node, pseudo);
|
||||
}, this);
|
||||
|
||||
let pseudoBox = this.nodeInfo.pseudoClassesBox;
|
||||
pseudoBox.textContent = pseudos.join("");
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -617,8 +696,8 @@ Highlighter.prototype = {
|
|||
*/
|
||||
computeZoomFactor: function Highlighter_computeZoomFactor() {
|
||||
this.zoom =
|
||||
this.win.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils)
|
||||
this.win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.screenPixelsPerCSSPixel;
|
||||
},
|
||||
|
||||
|
@ -805,3 +884,6 @@ Highlighter.prototype = {
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "DOMUtils", function () {
|
||||
return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils)
|
||||
});
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Cu = Components.utils;
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
|
@ -82,6 +83,8 @@ const INSPECTOR_NOTIFICATIONS = {
|
|||
EDITOR_SAVED: "inspector-editor-saved",
|
||||
};
|
||||
|
||||
const PSEUDO_CLASSES = [":hover", ":active", ":focus"];
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//// InspectorUI
|
||||
|
||||
|
@ -108,7 +111,6 @@ InspectorUI.prototype = {
|
|||
tools: null,
|
||||
toolEvents: null,
|
||||
inspecting: false,
|
||||
treePanelEnabled: true,
|
||||
ruleViewEnabled: true,
|
||||
isDirty: false,
|
||||
store: null,
|
||||
|
@ -137,25 +139,44 @@ InspectorUI.prototype = {
|
|||
this.sidebarSplitter.removeAttribute("hidden");
|
||||
this.stylingButton.checked = true;
|
||||
|
||||
// Activate the first tool in the sidebar, only if none previously-
|
||||
// selected. We'll want to do a followup to remember selected tool-states.
|
||||
// If no tool is already selected, show the last-used sidebar if available,
|
||||
// otherwise just show the first.
|
||||
|
||||
if (!Array.some(this.sidebarToolbar.children,
|
||||
function(btn) btn.hasAttribute("checked"))) {
|
||||
let firstButtonId = this.getToolbarButtonId(this.sidebarTools[0].id);
|
||||
this.chromeDoc.getElementById(firstButtonId).click();
|
||||
|
||||
let activePanel = this.sidebarTools[0];
|
||||
let activeId = this.store.getValue(this.winID, "activeSidebar");
|
||||
if (activeId && this.tools[activeId]) {
|
||||
activePanel = this.tools[activeId];
|
||||
}
|
||||
this.activateSidebarPanel(activePanel.id);
|
||||
}
|
||||
|
||||
this.store.setValue(this.winID, "sidebarOpen", true);
|
||||
Services.prefs.setBoolPref("devtools.inspector.sidebarOpen", true);
|
||||
},
|
||||
|
||||
/**
|
||||
* Hide the Sidebar.
|
||||
* Tear down the sidebar.
|
||||
*/
|
||||
hideSidebar: function IUI_hideSidebar()
|
||||
_destroySidebar: function IUI_destroySidebar()
|
||||
{
|
||||
this.sidebarBox.setAttribute("hidden", "true");
|
||||
this.sidebarSplitter.setAttribute("hidden", "true");
|
||||
this.stylingButton.checked = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Hide the sidebar.
|
||||
*/
|
||||
hideSidebar: function IUI_hideSidebar()
|
||||
{
|
||||
this._destroySidebar();
|
||||
this.store.setValue(this.winID, "sidebarOpen", false);
|
||||
Services.prefs.setBoolPref("devtools.inspector.sidebarOpen", false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Show or hide the sidebar. Called from the Styling button on the
|
||||
* highlighter toolbar.
|
||||
|
@ -169,6 +190,25 @@ InspectorUI.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Activate a sidebar panel by id.
|
||||
*/
|
||||
activateSidebarPanel: function IUI_activateSidebarPanel(aID)
|
||||
{
|
||||
let buttonId = this.getToolbarButtonId(aID);
|
||||
this.chromeDoc.getElementById(buttonId).click();
|
||||
},
|
||||
|
||||
get activeSidebarPanel()
|
||||
{
|
||||
for each (let tool in this.sidebarTools) {
|
||||
if (this.sidebarDeck.selectedPanel == this.getToolIframe(tool)) {
|
||||
return tool.id;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Getter to test if the Sidebar is open or not.
|
||||
*/
|
||||
|
@ -192,6 +232,22 @@ InspectorUI.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggle the TreePanel.
|
||||
*/
|
||||
toggleHTMLPanel: function TP_toggle()
|
||||
{
|
||||
if (this.treePanel.isOpen()) {
|
||||
this.treePanel.close();
|
||||
Services.prefs.setBoolPref("devtools.inspector.htmlPanelOpen", false);
|
||||
this.store.setValue(this.winID, "htmlPanelOpen", false);
|
||||
} else {
|
||||
this.treePanel.open();
|
||||
Services.prefs.setBoolPref("devtools.inspector.htmlPanelOpen", true);
|
||||
this.store.setValue(this.winID, "htmlPanelOpen", true);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Is the inspector UI open? Simply check if the toolbar is visible or not.
|
||||
*
|
||||
|
@ -260,9 +316,7 @@ InspectorUI.prototype = {
|
|||
this.initTools();
|
||||
this.chromeWin.Tilt.setup();
|
||||
|
||||
if (this.treePanelEnabled) {
|
||||
this.treePanel = new TreePanel(this.chromeWin, this);
|
||||
}
|
||||
this.treePanel = new TreePanel(this.chromeWin, this);
|
||||
|
||||
if (Services.prefs.getBoolPref("devtools.ruleview.enabled") &&
|
||||
!this.toolRegistered("ruleview")) {
|
||||
|
@ -310,6 +364,7 @@ InspectorUI.prototype = {
|
|||
show: this.openRuleView,
|
||||
hide: this.closeRuleView,
|
||||
onSelect: this.selectInRuleView,
|
||||
onChanged: this.changeInRuleView,
|
||||
panel: null,
|
||||
unregister: this.destroyRuleView,
|
||||
sidebar: true,
|
||||
|
@ -349,6 +404,16 @@ InspectorUI.prototype = {
|
|||
this.store.setValue(this.winID, "selectedNode", null);
|
||||
this.store.setValue(this.winID, "inspecting", true);
|
||||
this.store.setValue(this.winID, "isDirty", this.isDirty);
|
||||
|
||||
this.store.setValue(this.winID, "htmlPanelOpen",
|
||||
Services.prefs.getBoolPref("devtools.inspector.htmlPanelOpen"));
|
||||
|
||||
this.store.setValue(this.winID, "sidebarOpen",
|
||||
Services.prefs.getBoolPref("devtools.inspector.sidebarOpen"));
|
||||
|
||||
this.store.setValue(this.winID, "activeSidebar",
|
||||
Services.prefs.getCharPref("devtools.inspector.activeSidebar"));
|
||||
|
||||
this.win.addEventListener("pagehide", this, true);
|
||||
}
|
||||
},
|
||||
|
@ -400,6 +465,8 @@ InspectorUI.prototype = {
|
|||
if (this.treePanel && this.treePanel.editingContext)
|
||||
this.treePanel.closeEditor();
|
||||
|
||||
this.treePanel.destroy();
|
||||
|
||||
if (this.closing || !this.win || !this.browser) {
|
||||
return;
|
||||
}
|
||||
|
@ -417,6 +484,7 @@ InspectorUI.prototype = {
|
|||
if (!aKeepStore) {
|
||||
this.store.deleteStore(this.winID);
|
||||
this.win.removeEventListener("pagehide", this, true);
|
||||
this.clearPseudoClassLocks();
|
||||
} else {
|
||||
// Update the store before closing.
|
||||
if (this.selection) {
|
||||
|
@ -435,13 +503,12 @@ InspectorUI.prototype = {
|
|||
|
||||
this.stopInspecting();
|
||||
|
||||
this.saveToolState(this.winID);
|
||||
this.toolsDo(function IUI_toolsHide(aTool) {
|
||||
this.unregisterTool(aTool);
|
||||
}.bind(this));
|
||||
|
||||
// close the sidebar
|
||||
this.hideSidebar();
|
||||
this._destroySidebar();
|
||||
|
||||
if (this.highlighter) {
|
||||
this.highlighter.destroy();
|
||||
|
@ -503,7 +570,7 @@ InspectorUI.prototype = {
|
|||
this.inspecting = false;
|
||||
this.toolsDim(false);
|
||||
if (this.highlighter.getNode()) {
|
||||
this.select(this.highlighter.getNode(), true, true, !aPreventScroll);
|
||||
this.select(this.highlighter.getNode(), true, !aPreventScroll);
|
||||
} else {
|
||||
this.select(null, true, true);
|
||||
}
|
||||
|
@ -511,15 +578,17 @@ InspectorUI.prototype = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Select an object in the tree view.
|
||||
* Select an object in the inspector.
|
||||
* @param aNode
|
||||
* node to inspect
|
||||
* @param forceUpdate
|
||||
* force an update?
|
||||
* @param aScroll boolean
|
||||
* scroll the tree panel?
|
||||
* @param aFrom [optional] string
|
||||
* which part of the UI the selection occured from
|
||||
*/
|
||||
select: function IUI_select(aNode, forceUpdate, aScroll)
|
||||
select: function IUI_select(aNode, forceUpdate, aScroll, aFrom)
|
||||
{
|
||||
// if currently editing an attribute value, using the
|
||||
// highlighter dismisses the editor
|
||||
|
@ -530,6 +599,10 @@ InspectorUI.prototype = {
|
|||
aNode = this.defaultSelection;
|
||||
|
||||
if (forceUpdate || aNode != this.selection) {
|
||||
if (aFrom != "breadcrumbs") {
|
||||
this.clearPseudoClassLocks();
|
||||
}
|
||||
|
||||
this.selection = aNode;
|
||||
if (!this.inspecting) {
|
||||
this.highlighter.highlight(this.selection);
|
||||
|
@ -538,9 +611,45 @@ InspectorUI.prototype = {
|
|||
|
||||
this.breadcrumbs.update();
|
||||
this.chromeWin.Tilt.update(aNode);
|
||||
this.treePanel.select(aNode, aScroll);
|
||||
|
||||
this.toolsSelect(aScroll);
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggle the pseudo-class lock on the currently inspected element. If the
|
||||
* pseudo-class is :hover or :active, that pseudo-class will also be toggled
|
||||
* on every ancestor of the element, mirroring real :hover and :active
|
||||
* behavior.
|
||||
*
|
||||
* @param aPseudo the pseudo-class lock to toggle, e.g. ":hover"
|
||||
*/
|
||||
togglePseudoClassLock: function IUI_togglePseudoClassLock(aPseudo)
|
||||
{
|
||||
if (DOMUtils.hasPseudoClassLock(this.selection, aPseudo)) {
|
||||
this.breadcrumbs.nodeHierarchy.forEach(function(crumb) {
|
||||
DOMUtils.removePseudoClassLock(crumb.node, aPseudo);
|
||||
});
|
||||
} else {
|
||||
let hierarchical = aPseudo == ":hover" || aPseudo == ":active";
|
||||
let node = this.selection;
|
||||
do {
|
||||
DOMUtils.addPseudoClassLock(node, aPseudo);
|
||||
node = node.parentNode;
|
||||
} while (hierarchical && node.parentNode)
|
||||
}
|
||||
this.nodeChanged();
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear all pseudo-class locks applied to elements in the node hierarchy
|
||||
*/
|
||||
clearPseudoClassLocks: function IUI_clearPseudoClassLocks()
|
||||
{
|
||||
this.breadcrumbs.nodeHierarchy.forEach(function(crumb) {
|
||||
DOMUtils.clearPseudoClassLocks(crumb.node);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the highlighted node is changed by a tool.
|
||||
|
@ -552,6 +661,7 @@ InspectorUI.prototype = {
|
|||
nodeChanged: function IUI_nodeChanged(aUpdater)
|
||||
{
|
||||
this.highlighter.invalidateSize();
|
||||
this.breadcrumbs.updateSelectors();
|
||||
this.toolsOnChanged(aUpdater);
|
||||
},
|
||||
|
||||
|
@ -577,17 +687,32 @@ InspectorUI.prototype = {
|
|||
self.select(self.highlighter.getNode(), false, false);
|
||||
});
|
||||
|
||||
this.highlighter.addListener("pseudoclasstoggled", function(aPseudo) {
|
||||
self.togglePseudoClassLock(aPseudo);
|
||||
});
|
||||
|
||||
if (this.store.getValue(this.winID, "inspecting")) {
|
||||
this.startInspecting();
|
||||
this.highlighter.unlock();
|
||||
} else {
|
||||
this.highlighter.lock();
|
||||
}
|
||||
|
||||
this.restoreToolState(this.winID);
|
||||
Services.obs.notifyObservers(null, INSPECTOR_NOTIFICATIONS.STATE_RESTORED, null);
|
||||
|
||||
this.win.focus();
|
||||
this.highlighter.highlight();
|
||||
|
||||
if (this.store.getValue(this.winID, "htmlPanelOpen")) {
|
||||
this.treePanel.open();
|
||||
}
|
||||
|
||||
if (this.store.getValue(this.winID, "sidebarOpen")) {
|
||||
this.showSidebar();
|
||||
}
|
||||
|
||||
Services.obs.notifyObservers({wrappedJSObject: this},
|
||||
INSPECTOR_NOTIFICATIONS.OPENED, null);
|
||||
|
||||
this.highlighter.highlight();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -714,6 +839,46 @@ InspectorUI.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy the innerHTML of the selected Node to the clipboard. Called via the
|
||||
* Inspector:CopyInner command.
|
||||
*/
|
||||
copyInnerHTML: function IUI_copyInnerHTML()
|
||||
{
|
||||
let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].
|
||||
getService(Ci.nsIClipboardHelper);
|
||||
clipboard.copyString(this.selection.innerHTML);
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy the outerHTML of the selected Node to the clipboard. Called via the
|
||||
* Inspector:CopyOuter command.
|
||||
*/
|
||||
copyOuterHTML: function IUI_copyOuterHTML()
|
||||
{
|
||||
let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].
|
||||
getService(Ci.nsIClipboardHelper);
|
||||
clipboard.copyString(this.selection.outerHTML);
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete the selected node. Called via the Inspector:DeleteNode command.
|
||||
*/
|
||||
deleteNode: function IUI_deleteNode()
|
||||
{
|
||||
let selection = this.selection;
|
||||
let parent = this.selection.parentNode;
|
||||
|
||||
// remove the node from the treepanel
|
||||
this.treePanel.deleteChildBox(selection);
|
||||
|
||||
// remove the node from content
|
||||
parent.removeChild(selection);
|
||||
this.breadcrumbs.invalidateHierarchy();
|
||||
|
||||
// select the parent node in the highlighter, treepanel, breadcrumbs
|
||||
this.inspectNode(parent);
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//// CssRuleView methods
|
||||
|
@ -796,6 +961,15 @@ InspectorUI.prototype = {
|
|||
if (this.ruleView)
|
||||
this.ruleView.highlight(aNode);
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the rules for the current node in the Css Rule View.
|
||||
*/
|
||||
changeInRuleView: function IUI_selectInRuleView()
|
||||
{
|
||||
if (this.ruleView)
|
||||
this.ruleView.nodeChanged();
|
||||
},
|
||||
|
||||
ruleViewChanged: function IUI_ruleViewChanged()
|
||||
{
|
||||
|
@ -1087,6 +1261,8 @@ InspectorUI.prototype = {
|
|||
let btn = this.chromeDoc.getElementById(this.getToolbarButtonId(aTool.id));
|
||||
btn.setAttribute("checked", "true");
|
||||
if (aTool.sidebar) {
|
||||
Services.prefs.setCharPref("devtools.inspector.activeSidebar", aTool.id);
|
||||
this.store.setValue(this.winID, "activeSidebar", aTool.id);
|
||||
this.sidebarDeck.selectedPanel = this.getToolIframe(aTool);
|
||||
this.sidebarTools.forEach(function(other) {
|
||||
if (other != aTool)
|
||||
|
@ -1180,57 +1356,6 @@ InspectorUI.prototype = {
|
|||
delete this.tools[aRegObj.id];
|
||||
},
|
||||
|
||||
/**
|
||||
* Save a list of open tools to the inspector store.
|
||||
*
|
||||
* @param aWinID The ID of the window used to save the associated tools
|
||||
*/
|
||||
saveToolState: function IUI_saveToolState(aWinID)
|
||||
{
|
||||
let openTools = {};
|
||||
this.toolsDo(function IUI_toolsSetId(aTool) {
|
||||
if (aTool.isOpen) {
|
||||
openTools[aTool.id] = true;
|
||||
}
|
||||
});
|
||||
this.store.setValue(aWinID, "openTools", openTools);
|
||||
},
|
||||
|
||||
/**
|
||||
* Restore tools previously save using saveToolState().
|
||||
*
|
||||
* @param aWinID The ID of the window to which the associated tools are to be
|
||||
* restored.
|
||||
*/
|
||||
restoreToolState: function IUI_restoreToolState(aWinID)
|
||||
{
|
||||
let openTools = this.store.getValue(aWinID, "openTools");
|
||||
let activeSidebarTool;
|
||||
if (openTools) {
|
||||
this.toolsDo(function IUI_toolsOnShow(aTool) {
|
||||
if (aTool.id in openTools) {
|
||||
if (aTool.sidebar && !this.isSidebarOpen) {
|
||||
this.showSidebar();
|
||||
activeSidebarTool = aTool;
|
||||
}
|
||||
this.toolShow(aTool);
|
||||
}
|
||||
}.bind(this));
|
||||
this.sidebarTools.forEach(function(tool) {
|
||||
if (tool != activeSidebarTool)
|
||||
this.chromeDoc.getElementById(
|
||||
this.getToolbarButtonId(tool.id)).removeAttribute("checked");
|
||||
}.bind(this));
|
||||
}
|
||||
if (this.store.getValue(this.winID, "inspecting")) {
|
||||
this.highlighter.unlock();
|
||||
} else {
|
||||
this.highlighter.lock();
|
||||
}
|
||||
|
||||
Services.obs.notifyObservers(null, INSPECTOR_NOTIFICATIONS.STATE_RESTORED, null);
|
||||
},
|
||||
|
||||
/**
|
||||
* For each tool in the tools collection select the current node that is
|
||||
* selected in the highlighter
|
||||
|
@ -1254,7 +1379,7 @@ InspectorUI.prototype = {
|
|||
toolsDim: function IUI_toolsDim(aState)
|
||||
{
|
||||
this.toolsDo(function IUI_toolsDim(aTool) {
|
||||
if (aTool.isOpen && "dim" in aTool) {
|
||||
if ("dim" in aTool) {
|
||||
aTool.dim.call(aTool.context, aState);
|
||||
}
|
||||
});
|
||||
|
@ -1270,7 +1395,7 @@ InspectorUI.prototype = {
|
|||
toolsOnChanged: function IUI_toolsChanged(aUpdater)
|
||||
{
|
||||
this.toolsDo(function IUI_toolsOnChanged(aTool) {
|
||||
if (aTool.isOpen && ("onChanged" in aTool) && aTool != aUpdater) {
|
||||
if (("onChanged" in aTool) && aTool != aUpdater) {
|
||||
aTool.onChanged.call(aTool.context);
|
||||
}
|
||||
});
|
||||
|
@ -1664,6 +1789,13 @@ HTMLBreadcrumbs.prototype = {
|
|||
for (let i = 0; i < aNode.classList.length; i++) {
|
||||
text += "." + aNode.classList[i];
|
||||
}
|
||||
for (let i = 0; i < PSEUDO_CLASSES.length; i++) {
|
||||
let pseudo = PSEUDO_CLASSES[i];
|
||||
if (DOMUtils.hasPseudoClassLock(aNode, pseudo)) {
|
||||
text += pseudo;
|
||||
}
|
||||
}
|
||||
|
||||
return text;
|
||||
},
|
||||
|
||||
|
@ -1689,6 +1821,9 @@ HTMLBreadcrumbs.prototype = {
|
|||
|
||||
let classesLabel = this.IUI.chromeDoc.createElement("label");
|
||||
classesLabel.className = "inspector-breadcrumbs-classes plain";
|
||||
|
||||
let pseudosLabel = this.IUI.chromeDoc.createElement("label");
|
||||
pseudosLabel.className = "inspector-breadcrumbs-pseudo-classes plain";
|
||||
|
||||
tagLabel.textContent = aNode.tagName.toLowerCase();
|
||||
idLabel.textContent = aNode.id ? ("#" + aNode.id) : "";
|
||||
|
@ -1699,9 +1834,15 @@ HTMLBreadcrumbs.prototype = {
|
|||
}
|
||||
classesLabel.textContent = classesText;
|
||||
|
||||
let pseudos = PSEUDO_CLASSES.filter(function(pseudo) {
|
||||
return DOMUtils.hasPseudoClassLock(aNode, pseudo);
|
||||
}, this);
|
||||
pseudosLabel.textContent = pseudos.join("");
|
||||
|
||||
fragment.appendChild(tagLabel);
|
||||
fragment.appendChild(idLabel);
|
||||
fragment.appendChild(classesLabel);
|
||||
fragment.appendChild(pseudosLabel);
|
||||
|
||||
return fragment;
|
||||
},
|
||||
|
@ -1741,7 +1882,7 @@ HTMLBreadcrumbs.prototype = {
|
|||
|
||||
item.onmouseup = (function(aNode) {
|
||||
return function() {
|
||||
inspector.select(aNode, true, true);
|
||||
inspector.select(aNode, true, true, "breadcrumbs");
|
||||
}
|
||||
})(nodes[i]);
|
||||
|
||||
|
@ -1895,7 +2036,7 @@ HTMLBreadcrumbs.prototype = {
|
|||
|
||||
button.onBreadcrumbsClick = function onBreadcrumbsClick() {
|
||||
inspector.stopInspecting();
|
||||
inspector.select(aNode, true, true);
|
||||
inspector.select(aNode, true, true, "breadcrumbs");
|
||||
};
|
||||
|
||||
button.onclick = (function _onBreadcrumbsRightClick(aEvent) {
|
||||
|
@ -2010,6 +2151,20 @@ HTMLBreadcrumbs.prototype = {
|
|||
let element = this.nodeHierarchy[this.currentIndex].button;
|
||||
scrollbox.ensureElementIsVisible(element);
|
||||
},
|
||||
|
||||
updateSelectors: function BC_updateSelectors()
|
||||
{
|
||||
for (let i = this.nodeHierarchy.length - 1; i >= 0; i--) {
|
||||
let crumb = this.nodeHierarchy[i];
|
||||
let button = crumb.button;
|
||||
|
||||
while(button.hasChildNodes()) {
|
||||
button.removeChild(button.firstChild);
|
||||
}
|
||||
button.appendChild(this.prettyPrintNodeAsXUL(crumb.node));
|
||||
button.setAttribute("tooltiptext", this.prettyPrintNodeAsText(crumb.node));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the breadcrumbs display when a new node is selected.
|
||||
|
@ -2051,6 +2206,8 @@ HTMLBreadcrumbs.prototype = {
|
|||
|
||||
// Make sure the selected node and its neighbours are visible.
|
||||
this.scroll();
|
||||
|
||||
this.updateSelectors();
|
||||
},
|
||||
|
||||
}
|
||||
|
@ -2070,3 +2227,6 @@ XPCOMUtils.defineLazyGetter(this, "StyleInspector", function () {
|
|||
return obj.StyleInspector;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "DOMUtils", function () {
|
||||
return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
|
||||
});
|
||||
|
|
|
@ -70,6 +70,9 @@ _BROWSER_FILES = \
|
|||
browser_inspector_ruleviewstore.js \
|
||||
browser_inspector_duplicate_ruleview.js \
|
||||
browser_inspector_invalidate.js \
|
||||
browser_inspector_sidebarstate.js \
|
||||
browser_inspector_treePanel_menu.js \
|
||||
browser_inspector_pseudoclass_lock.js \
|
||||
head.js \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ function setupHTMLPanel()
|
|||
{
|
||||
Services.obs.removeObserver(setupHTMLPanel, InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED);
|
||||
Services.obs.addObserver(runEditorTests, InspectorUI.INSPECTOR_NOTIFICATIONS.TREEPANELREADY, false);
|
||||
InspectorUI.toolShow(InspectorUI.treePanel.registrationObject);
|
||||
InspectorUI.toggleHTMLPanel();
|
||||
}
|
||||
|
||||
function runEditorTests()
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let DOMUtils = Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
|
||||
|
||||
let doc;
|
||||
let div;
|
||||
|
||||
let pseudo = ":hover";
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
ignoreAllUncaughtExceptions();
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
doc = content.document;
|
||||
waitForFocus(createDocument, content);
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html,pseudo-class lock tests";
|
||||
}
|
||||
|
||||
function createDocument()
|
||||
{
|
||||
div = doc.createElement("div");
|
||||
div.textContent = "test div";
|
||||
|
||||
let head = doc.getElementsByTagName('head')[0];
|
||||
let style = doc.createElement('style');
|
||||
let rules = doc.createTextNode('div { color: red; } div:hover { color: blue; }');
|
||||
|
||||
style.appendChild(rules);
|
||||
head.appendChild(style);
|
||||
doc.body.appendChild(div);
|
||||
|
||||
setupTests();
|
||||
}
|
||||
|
||||
function setupTests()
|
||||
{
|
||||
Services.obs.addObserver(selectNode,
|
||||
InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
|
||||
InspectorUI.openInspectorUI();
|
||||
}
|
||||
|
||||
function selectNode()
|
||||
{
|
||||
Services.obs.removeObserver(selectNode,
|
||||
InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED);
|
||||
|
||||
executeSoon(function() {
|
||||
InspectorUI.highlighter.addListener("nodeselected", openRuleView);
|
||||
InspectorUI.inspectNode(div);
|
||||
});
|
||||
}
|
||||
|
||||
function openRuleView()
|
||||
{
|
||||
Services.obs.addObserver(performTests,
|
||||
InspectorUI.INSPECTOR_NOTIFICATIONS.RULEVIEWREADY, false);
|
||||
|
||||
InspectorUI.showSidebar();
|
||||
InspectorUI.openRuleView();
|
||||
}
|
||||
|
||||
function performTests()
|
||||
{
|
||||
Services.obs.removeObserver(performTests,
|
||||
InspectorUI.INSPECTOR_NOTIFICATIONS.RULEVIEWREADY);
|
||||
|
||||
InspectorUI.highlighter.removeListener("nodeselected", performTests);
|
||||
|
||||
// toggle the class
|
||||
InspectorUI.highlighter.pseudoClassLockToggled(pseudo);
|
||||
|
||||
testAdded();
|
||||
|
||||
// toggle the lock off
|
||||
InspectorUI.highlighter.pseudoClassLockToggled(pseudo);
|
||||
|
||||
testRemoved();
|
||||
testRemovedFromUI();
|
||||
|
||||
// toggle it back on
|
||||
InspectorUI.highlighter.pseudoClassLockToggled(pseudo);
|
||||
|
||||
// close the inspector
|
||||
Services.obs.addObserver(testInspectorClosed,
|
||||
InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED, false);
|
||||
InspectorUI.closeInspectorUI();
|
||||
}
|
||||
|
||||
function testAdded()
|
||||
{
|
||||
// lock is applied to it and ancestors
|
||||
let node = div;
|
||||
do {
|
||||
is(DOMUtils.hasPseudoClassLock(node, pseudo), true,
|
||||
"pseudo-class lock has been applied");
|
||||
node = node.parentNode;
|
||||
} while (node.parentNode)
|
||||
|
||||
// infobar selector contains pseudo-class
|
||||
let pseudoClassesBox = document.getElementById("highlighter-nodeinfobar-pseudo-classes");
|
||||
is(pseudoClassesBox.textContent, pseudo, "pseudo-class in infobar selector");
|
||||
|
||||
// ruleview contains pseudo-class rule
|
||||
is(InspectorUI.ruleView.element.children.length, 3,
|
||||
"rule view is showing 3 rules for pseudo-class locked div");
|
||||
|
||||
is(InspectorUI.ruleView.element.children[1]._ruleEditor.rule.selectorText,
|
||||
"div:hover", "rule view is showing " + pseudo + " rule");
|
||||
}
|
||||
|
||||
function testRemoved()
|
||||
{
|
||||
// lock removed from node and ancestors
|
||||
let node = div;
|
||||
do {
|
||||
is(DOMUtils.hasPseudoClassLock(node, pseudo), false,
|
||||
"pseudo-class lock has been removed");
|
||||
node = node.parentNode;
|
||||
} while (node.parentNode)
|
||||
}
|
||||
|
||||
function testRemovedFromUI()
|
||||
{
|
||||
// infobar selector doesn't contain pseudo-class
|
||||
let pseudoClassesBox = document.getElementById("highlighter-nodeinfobar-pseudo-classes");
|
||||
is(pseudoClassesBox.textContent, "", "pseudo-class removed from infobar selector");
|
||||
|
||||
// ruleview no longer contains pseudo-class rule
|
||||
is(InspectorUI.ruleView.element.children.length, 2,
|
||||
"rule view is showing 2 rules after removing lock");
|
||||
}
|
||||
|
||||
function testInspectorClosed()
|
||||
{
|
||||
Services.obs.removeObserver(testInspectorClosed,
|
||||
InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED);
|
||||
|
||||
testRemoved();
|
||||
|
||||
finishUp();
|
||||
}
|
||||
|
||||
function finishUp()
|
||||
{
|
||||
doc = div = null;
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
|
@ -148,45 +148,6 @@ function startToolTests(evt)
|
|||
ok(!tool2.isOpen, "Panel 2 is closed");
|
||||
ok(tool3.isOpen, "Panel 3 is open");
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
waitForFocus(testSecondTab, content);
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html,registertool new tab test for inspector";
|
||||
}
|
||||
|
||||
function testSecondTab()
|
||||
{
|
||||
info("Opened second tab");
|
||||
info("Checking panel states 5");
|
||||
|
||||
let tools = InspectorUI.tools;
|
||||
ok(!(tool1 in tools), "Panel 1 not in tools");
|
||||
ok(!(tool2 in tools), "Panel 2 not in tools");
|
||||
ok(!(tool3 in tools), "Panel 3 not in tools");
|
||||
|
||||
info("Closing current tab");
|
||||
Services.obs.addObserver(testOriginalTab, InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
|
||||
gBrowser.removeCurrentTab();
|
||||
}
|
||||
|
||||
function testOriginalTab()
|
||||
{
|
||||
Services.obs.removeObserver(testOriginalTab, InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED);
|
||||
info("Checking panel states 6");
|
||||
|
||||
info("Tools: " + InspectorUI.tools);
|
||||
// reacquaint ourselves with our tools
|
||||
tool1 = InspectorUI.tools["tool_1"];
|
||||
tool2 = InspectorUI.tools["tool_2"];
|
||||
tool3 = InspectorUI.tools["tool_3"];
|
||||
|
||||
ok(tool1.isOpen, "Panel 1 is open after reactivation");
|
||||
ok(!tool2.isOpen, "Panel 2 is closed after reactivation");
|
||||
ok(tool3.isOpen, "Panel 3 is open after reactivation");
|
||||
|
||||
Services.obs.addObserver(unregisterTools, InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED, false);
|
||||
InspectorUI.closeInspectorUI(true);
|
||||
}
|
||||
|
|
|
@ -128,8 +128,8 @@ function ruleViewOpened2()
|
|||
is(prop.name, "background-color", "First prop is the background color prop.");
|
||||
ok(!prop.enabled, "First prop should be disabled.");
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
InspectorUI.closeInspectorUI();
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let doc;
|
||||
|
||||
function createDocument()
|
||||
{
|
||||
doc.body.innerHTML = '<h1>Sidebar state test</h1>';
|
||||
doc.title = "Sidebar State Test";
|
||||
|
||||
// Open the sidebar and wait for the default view (the rule view) to show.
|
||||
Services.obs.addObserver(inspectorRuleViewOpened,
|
||||
InspectorUI.INSPECTOR_NOTIFICATIONS.RULEVIEWREADY, false);
|
||||
|
||||
InspectorUI.openInspectorUI();
|
||||
InspectorUI.showSidebar();
|
||||
}
|
||||
|
||||
function inspectorRuleViewOpened()
|
||||
{
|
||||
Services.obs.removeObserver(inspectorRuleViewOpened,
|
||||
InspectorUI.INSPECTOR_NOTIFICATIONS.RULEVIEWREADY);
|
||||
is(InspectorUI.activeSidebarPanel, "ruleview", "Rule View is selected by default");
|
||||
|
||||
// Select the computed view and turn off the inspector.
|
||||
InspectorUI.activateSidebarPanel("styleinspector");
|
||||
|
||||
Services.obs.addObserver(inspectorClosed,
|
||||
InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED, false);
|
||||
InspectorUI.closeInspectorUI();
|
||||
}
|
||||
|
||||
function inspectorClosed()
|
||||
{
|
||||
// Reopen the inspector, expect the computed view to be loaded.
|
||||
Services.obs.removeObserver(inspectorClosed,
|
||||
InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED);
|
||||
|
||||
Services.obs.addObserver(computedViewPopulated,
|
||||
"StyleInspector-populated", false);
|
||||
|
||||
InspectorUI.openInspectorUI();
|
||||
}
|
||||
|
||||
function computedViewPopulated()
|
||||
{
|
||||
Services.obs.removeObserver(computedViewPopulated,
|
||||
"StyleInspector-populated");
|
||||
is(InspectorUI.activeSidebarPanel, "styleinspector", "Computed view is selected by default.");
|
||||
|
||||
finishTest();
|
||||
}
|
||||
|
||||
|
||||
function finishTest()
|
||||
{
|
||||
InspectorUI.closeInspectorUI();
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
doc = content.document;
|
||||
waitForFocus(createDocument, content);
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html,basic tests for inspector";
|
||||
}
|
||||
|
|
@ -96,6 +96,7 @@ function inspectorTabOpen2()
|
|||
executeSoon(function() {
|
||||
Services.obs.addObserver(inspectorUIOpen2,
|
||||
InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
|
||||
clearUserPrefs();
|
||||
InspectorUI.openInspectorUI();
|
||||
});
|
||||
}
|
||||
|
@ -136,7 +137,7 @@ function inspectorFocusTab1()
|
|||
Services.obs.addObserver(inspectorOpenTreePanelTab1,
|
||||
InspectorUI.INSPECTOR_NOTIFICATIONS.TREEPANELREADY, false);
|
||||
|
||||
InspectorUI.treePanel.open();
|
||||
InspectorUI.toggleHTMLPanel();
|
||||
}
|
||||
|
||||
function inspectorOpenTreePanelTab1()
|
||||
|
@ -153,7 +154,7 @@ function inspectorOpenTreePanelTab1()
|
|||
|
||||
executeSoon(function() {
|
||||
InspectorUI.showSidebar();
|
||||
InspectorUI.toolShow(InspectorUI.stylePanel.registrationObject);
|
||||
InspectorUI.activateSidebarPanel("styleinspector");
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
|
||||
function test() {
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
let doc;
|
||||
let node1;
|
||||
let div;
|
||||
|
||||
function createDocument() {
|
||||
div = doc.createElement("div");
|
||||
let h1 = doc.createElement("h1");
|
||||
let p1 = doc.createElement("p");
|
||||
let p2 = doc.createElement("p");
|
||||
doc.title = "Inspector Tree Menu Test";
|
||||
h1.textContent = "Inspector Tree Menu Test";
|
||||
p1.textContent = "This is some example text";
|
||||
div.appendChild(h1);
|
||||
div.appendChild(p1);
|
||||
doc.body.appendChild(div);
|
||||
node1 = p1;
|
||||
setupTest();
|
||||
}
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onload() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
|
||||
doc = content.document;
|
||||
waitForFocus(createDocument, content);
|
||||
}, true);
|
||||
|
||||
content.location = content.location = "data:text/html,basic tests for inspector";;
|
||||
|
||||
function setupTest() {
|
||||
Services.obs.addObserver(runTests, InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
|
||||
InspectorUI.toggleInspectorUI();
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
Services.obs.removeObserver(runTests, InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED);
|
||||
Services.obs.addObserver(testCopyInnerMenu, InspectorUI.INSPECTOR_NOTIFICATIONS.TREEPANELREADY, false);
|
||||
InspectorUI.stopInspecting();
|
||||
InspectorUI.inspectNode(node1, true);
|
||||
InspectorUI.treePanel.open();
|
||||
}
|
||||
|
||||
function testCopyInnerMenu() {
|
||||
let copyInner = document.getElementById("inspectorHTMLCopyInner");
|
||||
ok(copyInner, "the popup menu has a copy inner html menu item");
|
||||
|
||||
waitForClipboard("This is some example text",
|
||||
function() { copyInner.doCommand(); },
|
||||
testCopyOuterMenu, testCopyOuterMenu);
|
||||
}
|
||||
|
||||
function testCopyOuterMenu() {
|
||||
let copyOuter = document.getElementById("inspectorHTMLCopyOuter");
|
||||
ok(copyOuter, "the popup menu has a copy outer html menu item");
|
||||
|
||||
waitForClipboard("<p>This is some example text</p>",
|
||||
function() { copyOuter.doCommand(); },
|
||||
testDeleteNode, testDeleteNode);
|
||||
}
|
||||
|
||||
function testDeleteNode() {
|
||||
let deleteNode = document.getElementById("inspectorHTMLDelete");
|
||||
ok(deleteNode, "the popup menu has a delete menu item");
|
||||
|
||||
InspectorUI.highlighter.addListener("nodeselected", deleteTest);
|
||||
|
||||
let commandEvent = document.createEvent("XULCommandEvent");
|
||||
commandEvent.initCommandEvent("command", true, true, window, 0, false, false,
|
||||
false, false, null);
|
||||
deleteNode.dispatchEvent(commandEvent);
|
||||
}
|
||||
|
||||
function deleteTest() {
|
||||
InspectorUI.highlighter.removeListener("nodeSelected", deleteTest);
|
||||
Services.obs.addObserver(finishUp, InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED, false);
|
||||
is(InspectorUI.selection, div, "parent node selected");
|
||||
let p = doc.querySelector("P");
|
||||
is(p, null, "node deleted");
|
||||
executeSoon(function() {
|
||||
InspectorUI.closeInspectorUI();
|
||||
});
|
||||
}
|
||||
|
||||
function finishUp() {
|
||||
Services.obs.removeObserver(finishUp, InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED);
|
||||
doc = node1 = div = null;
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
}
|
|
@ -41,6 +41,16 @@ let tempScope = {};
|
|||
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm", tempScope);
|
||||
let LayoutHelpers = tempScope.LayoutHelpers;
|
||||
|
||||
// Clear preferences that may be set during the course of tests.
|
||||
function clearUserPrefs()
|
||||
{
|
||||
Services.prefs.clearUserPref("devtools.inspector.htmlPanelOpen");
|
||||
Services.prefs.clearUserPref("devtools.inspector.sidebarOpen");
|
||||
Services.prefs.clearUserPref("devtools.inspector.activeSidebar");
|
||||
}
|
||||
|
||||
registerCleanupFunction(clearUserPrefs);
|
||||
|
||||
function isHighlighting()
|
||||
{
|
||||
let veil = InspectorUI.highlighter.veilTransparentBox;
|
||||
|
@ -78,3 +88,4 @@ function midPoint(aPointA, aPointB)
|
|||
pointC.y = (aPointB.y - aPointA.y) / 2 + aPointA.y;
|
||||
return pointC;
|
||||
}
|
||||
|
||||
|
|
|
@ -441,7 +441,8 @@ var Scratchpad = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Write out a value at the current insertion point as a block comment
|
||||
* Write out a value at the next line from the current insertion point.
|
||||
* The comment block will always be preceded by a newline character.
|
||||
* @param object aValue
|
||||
* The Object to write out as a string
|
||||
*/
|
||||
|
@ -452,7 +453,7 @@ var Scratchpad = {
|
|||
selection.end : // after selected text
|
||||
this.editor.getCharCount(); // after text end
|
||||
|
||||
let newComment = "/*\n" + aValue + "\n*/";
|
||||
let newComment = "\n/*\n" + aValue + "\n*/";
|
||||
|
||||
this.setText(newComment, insertionPoint, insertionPoint);
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ function runTests()
|
|||
var scratchpad = gScratchpadWindow.Scratchpad;
|
||||
|
||||
var message = "\"Hello World!\""
|
||||
var openComment = "/*\n";
|
||||
var openComment = "\n/*\n";
|
||||
var closeComment = "\n*/";
|
||||
var error = "throw new Error(\"Ouch!\")";
|
||||
let messageArray = {};
|
||||
|
|
|
@ -30,25 +30,25 @@ function verifyFalsies(sp)
|
|||
{
|
||||
sp.setText("undefined");
|
||||
sp.display();
|
||||
is(sp.selectedText, "/*\nundefined\n*/", "'undefined' is displayed");
|
||||
is(sp.selectedText, "\n/*\nundefined\n*/", "'undefined' is displayed");
|
||||
|
||||
sp.setText("false");
|
||||
sp.display();
|
||||
is(sp.selectedText, "/*\nfalse\n*/", "'false' is displayed");
|
||||
is(sp.selectedText, "\n/*\nfalse\n*/", "'false' is displayed");
|
||||
|
||||
sp.setText("0");
|
||||
sp.display();
|
||||
is(sp.selectedText, "/*\n0\n*/", "'0' is displayed");
|
||||
is(sp.selectedText, "\n/*\n0\n*/", "'0' is displayed");
|
||||
|
||||
sp.setText("null");
|
||||
sp.display();
|
||||
is(sp.selectedText, "/*\nnull\n*/", "'null' is displayed");
|
||||
is(sp.selectedText, "\n/*\nnull\n*/", "'null' is displayed");
|
||||
|
||||
sp.setText("NaN");
|
||||
sp.display();
|
||||
is(sp.selectedText, "/*\nNaN\n*/", "'NaN' is displayed");
|
||||
is(sp.selectedText, "\n/*\nNaN\n*/", "'NaN' is displayed");
|
||||
|
||||
sp.setText("''");
|
||||
sp.display();
|
||||
is(sp.selectedText, "/*\n\n*/", "empty string is displayed");
|
||||
is(sp.selectedText, "\n/*\n\n*/", "empty string is displayed");
|
||||
}
|
||||
|
|
|
@ -40,13 +40,13 @@ function runTests()
|
|||
is(content.wrappedJSObject.foobarBug636725, 3,
|
||||
"display() updated window.foobarBug636725");
|
||||
|
||||
is(sp.getText(), "++window.foobarBug636725/*\n3\n*/",
|
||||
is(sp.getText(), "++window.foobarBug636725\n/*\n3\n*/",
|
||||
"display() shows evaluation result in the textbox");
|
||||
|
||||
is(sp.selectedText, "/*\n3\n*/", "selectedText is correct");
|
||||
is(sp.selectedText, "\n/*\n3\n*/", "selectedText is correct");
|
||||
let selection = sp.getSelectionRange();
|
||||
is(selection.start, 24, "selection.start is correct");
|
||||
is(selection.end, 31, "selection.end is correct");
|
||||
is(selection.end, 32, "selection.end is correct");
|
||||
|
||||
// Test selection run() and display().
|
||||
|
||||
|
@ -94,16 +94,16 @@ function runTests()
|
|||
"display() worked for the selected range");
|
||||
|
||||
is(sp.getText(), "window.foobarBug636725" +
|
||||
"/*\na\n*/" +
|
||||
"\n/*\na\n*/" +
|
||||
" = 'c';\n" +
|
||||
"window.foobarBug636725 = 'b';",
|
||||
"display() shows evaluation result in the textbox");
|
||||
|
||||
is(sp.selectedText, "/*\na\n*/", "selectedText is correct");
|
||||
is(sp.selectedText, "\n/*\na\n*/", "selectedText is correct");
|
||||
|
||||
selection = sp.getSelectionRange();
|
||||
is(selection.start, 22, "selection.start is correct");
|
||||
is(selection.end, 29, "selection.end is correct");
|
||||
is(selection.end, 30, "selection.end is correct");
|
||||
|
||||
sp.deselect();
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ function ElementStyle(aElement, aStore)
|
|||
// how their .style attribute reflects them as computed values.
|
||||
this.dummyElement = doc.createElementNS(this.element.namespaceURI,
|
||||
this.element.tagName);
|
||||
this._populate();
|
||||
this.populate();
|
||||
}
|
||||
// We're exporting _ElementStyle for unit tests.
|
||||
var _ElementStyle = ElementStyle;
|
||||
|
@ -147,7 +147,7 @@ ElementStyle.prototype = {
|
|||
* Refresh the list of rules to be displayed for the active element.
|
||||
* Upon completion, this.rules[] will hold a list of Rule objects.
|
||||
*/
|
||||
_populate: function ElementStyle_populate()
|
||||
populate: function ElementStyle_populate()
|
||||
{
|
||||
this.rules = [];
|
||||
|
||||
|
@ -713,15 +713,33 @@ CssRuleView.prototype = {
|
|||
|
||||
this._createEditors();
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the rules for the currently highlighted element.
|
||||
*/
|
||||
nodeChanged: function CssRuleView_nodeChanged()
|
||||
{
|
||||
this._clearRules();
|
||||
this._elementStyle.populate();
|
||||
this._createEditors();
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear the rules.
|
||||
*/
|
||||
_clearRules: function CssRuleView_clearRules()
|
||||
{
|
||||
while (this.element.hasChildNodes()) {
|
||||
this.element.removeChild(this.element.lastChild);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear the rule view.
|
||||
*/
|
||||
clear: function CssRuleView_clear()
|
||||
{
|
||||
while (this.element.hasChildNodes()) {
|
||||
this.element.removeChild(this.element.lastChild);
|
||||
}
|
||||
this._clearRules();
|
||||
this._viewedElement = null;
|
||||
this._elementStyle = null;
|
||||
},
|
||||
|
|
|
@ -120,6 +120,11 @@ StyleInspector.prototype = {
|
|||
this.cssHtmlTree.highlight(selectedNode);
|
||||
this.iframe.removeEventListener("load", boundIframeOnLoad, true);
|
||||
this.iframeReady = true;
|
||||
|
||||
// Now that we've loaded, select any node we were previously asked
|
||||
// to show.
|
||||
this.selectNode(this.selectedNode);
|
||||
|
||||
Services.obs.notifyObservers(null, "StyleInspector-opened", null);
|
||||
}
|
||||
}.bind(this);
|
||||
|
@ -215,11 +220,16 @@ StyleInspector.prototype = {
|
|||
*/
|
||||
isOpen: function SI_isOpen()
|
||||
{
|
||||
return this.openDocked ? this.iframeReady && this.IUI.isSidebarOpen &&
|
||||
return this.openDocked ? this.IUI.isSidebarOpen &&
|
||||
(this.IUI.sidebarDeck.selectedPanel == this.iframe) :
|
||||
this.panel && this.panel.state && this.panel.state == "open";
|
||||
},
|
||||
|
||||
isLoaded: function SI_isLoaded()
|
||||
{
|
||||
return this.openDocked ? this.iframeReady : this.iframeReady && this.panelReady;
|
||||
},
|
||||
|
||||
/**
|
||||
* Select from Path (via CssHtmlTree_pathClick)
|
||||
* @param aNode The node to inspect.
|
||||
|
@ -242,7 +252,7 @@ StyleInspector.prototype = {
|
|||
selectNode: function SI_selectNode(aNode)
|
||||
{
|
||||
this.selectedNode = aNode;
|
||||
if (this.isOpen() && !this.dimmed) {
|
||||
if (this.isLoaded() && !this.dimmed) {
|
||||
this.cssLogic.highlight(aNode);
|
||||
this.cssHtmlTree.highlight(aNode);
|
||||
}
|
||||
|
@ -253,7 +263,7 @@ StyleInspector.prototype = {
|
|||
*/
|
||||
updateNode: function SI_updateNode()
|
||||
{
|
||||
if (this.isOpen() && !this.dimmed) {
|
||||
if (this.isLoaded() && !this.dimmed) {
|
||||
this.cssLogic.highlight(this.selectedNode);
|
||||
this.cssHtmlTree.refreshPanel();
|
||||
}
|
||||
|
|
|
@ -127,7 +127,6 @@ Tilt.prototype = {
|
|||
chromeWindow: this.chromeWindow,
|
||||
contentWindow: this.chromeWindow.gBrowser.selectedBrowser.contentWindow,
|
||||
parentNode: this.chromeWindow.gBrowser.selectedBrowser.parentNode,
|
||||
requestAnimationFrame: this.chromeWindow.mozRequestAnimationFrame,
|
||||
notifications: this.NOTIFICATIONS
|
||||
});
|
||||
|
||||
|
@ -141,7 +140,7 @@ Tilt.prototype = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Destroys a specific instance of the visualizer.
|
||||
* Starts destroying a specific instance of the visualizer.
|
||||
*
|
||||
* @param {String} aId
|
||||
* the identifier of the instance in the visualizers array
|
||||
|
@ -150,43 +149,49 @@ Tilt.prototype = {
|
|||
*/
|
||||
destroy: function T_destroy(aId, aAnimateFlag)
|
||||
{
|
||||
// if the visualizer is already destroyed, don't do anything
|
||||
if (!this.visualizers[aId]) {
|
||||
// if the visualizer is destroyed or destroying, don't do anything
|
||||
if (!this.visualizers[aId] || this._isDestroying) {
|
||||
return;
|
||||
}
|
||||
this._isDestroying = true;
|
||||
|
||||
let controller = this.visualizers[aId].controller;
|
||||
let presenter = this.visualizers[aId].presenter;
|
||||
|
||||
let content = presenter.contentWindow;
|
||||
let pageXOffset = content.pageXOffset * presenter.transforms.zoom;
|
||||
let pageYOffset = content.pageYOffset * presenter.transforms.zoom;
|
||||
TiltUtils.setDocumentZoom(this.chromeWindow, presenter.transforms.zoom);
|
||||
|
||||
// if we're not doing any outro animation, just finish destruction directly
|
||||
if (!aAnimateFlag) {
|
||||
this._finish(aId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.isDestroying) {
|
||||
this.isDestroying = true;
|
||||
// otherwise, trigger the outro animation and notify necessary observers
|
||||
Services.obs.notifyObservers(null, TILT_NOTIFICATIONS.DESTROYING, null);
|
||||
|
||||
let finalize = function T_finalize(aId) {
|
||||
this.visualizers[aId].removeOverlay();
|
||||
this.visualizers[aId].cleanup();
|
||||
this.visualizers[aId] = null;
|
||||
controller.removeEventListeners();
|
||||
controller.arcball.reset([-pageXOffset, -pageYOffset]);
|
||||
presenter.executeDestruction(this._finish.bind(this, aId));
|
||||
},
|
||||
|
||||
this.isDestroying = false;
|
||||
this.chromeWindow.gBrowser.selectedBrowser.focus();
|
||||
Services.obs.notifyObservers(null, TILT_NOTIFICATIONS.DESTROYED, null);
|
||||
};
|
||||
/**
|
||||
* Finishes detroying a specific instance of the visualizer.
|
||||
*
|
||||
* @param {String} aId
|
||||
* the identifier of the instance in the visualizers array
|
||||
*/
|
||||
_finish: function T__finish(aId)
|
||||
{
|
||||
this.visualizers[aId].removeOverlay();
|
||||
this.visualizers[aId].cleanup();
|
||||
this.visualizers[aId] = null;
|
||||
|
||||
if (!aAnimateFlag) {
|
||||
finalize.call(this, aId);
|
||||
return;
|
||||
}
|
||||
|
||||
let controller = this.visualizers[aId].controller;
|
||||
let presenter = this.visualizers[aId].presenter;
|
||||
|
||||
let content = presenter.contentWindow;
|
||||
let pageXOffset = content.pageXOffset * presenter.transforms.zoom;
|
||||
let pageYOffset = content.pageYOffset * presenter.transforms.zoom;
|
||||
|
||||
Services.obs.notifyObservers(null, TILT_NOTIFICATIONS.DESTROYING, null);
|
||||
TiltUtils.setDocumentZoom(this.chromeWindow, presenter.transforms.zoom);
|
||||
|
||||
controller.removeEventListeners();
|
||||
controller.arcball.reset([-pageXOffset, -pageYOffset]);
|
||||
presenter.executeDestruction(finalize.bind(this, aId));
|
||||
}
|
||||
this._isDestroying = false;
|
||||
this.chromeWindow.gBrowser.selectedBrowser.focus();
|
||||
Services.obs.notifyObservers(null, TILT_NOTIFICATIONS.DESTROYED, null);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -286,16 +291,18 @@ Tilt.prototype = {
|
|||
|
||||
// FIXME: this shouldn't be done here, see bug #705131
|
||||
let onOpened = function() {
|
||||
if (this.currentInstance) {
|
||||
this.chromeWindow.InspectorUI.stopInspecting();
|
||||
this.inspectButton.disabled = true;
|
||||
this.highlighterContainer.style.display = "none";
|
||||
if (this.inspector && this.highlighter && this.currentInstance) {
|
||||
this.inspector.stopInspecting();
|
||||
this.inspector.inspectToolbutton.disabled = true;
|
||||
this.highlighter.hide();
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
let onClosed = function() {
|
||||
this.inspectButton.disabled = false;
|
||||
this.highlighterContainer.style.display = "";
|
||||
if (this.inspector && this.highlighter) {
|
||||
this.inspector.inspectToolbutton.disabled = false;
|
||||
this.highlighter.show();
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
Services.obs.addObserver(onOpened,
|
||||
|
@ -337,32 +344,27 @@ Tilt.prototype = {
|
|||
return this.visualizers[this.currentWindowId];
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the current InspectorUI instance.
|
||||
*/
|
||||
get inspector()
|
||||
{
|
||||
return this.chromeWindow.InspectorUI;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the current Highlighter instance from the InspectorUI.
|
||||
*/
|
||||
get highlighter()
|
||||
{
|
||||
return this.inspector.highlighter;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the Tilt button in the Inspector toolbar.
|
||||
*/
|
||||
get tiltButton()
|
||||
{
|
||||
return this.chromeWindow.document.getElementById(
|
||||
"inspector-3D-button");
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the Inspect button in the Inspector toolbar.
|
||||
* FIXME: this shouldn't be needed here, remove after bug #705131
|
||||
*/
|
||||
get inspectButton()
|
||||
{
|
||||
return this.chromeWindow.document.getElementById(
|
||||
"inspector-inspect-toolbutton");
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the Highlighter contaniner stack.
|
||||
* FIXME: this shouldn't be needed here, remove after bug #705131
|
||||
*/
|
||||
get highlighterContainer()
|
||||
{
|
||||
return this.chromeWindow.document.getElementById(
|
||||
"highlighter-container");
|
||||
return this.chromeWindow.document.getElementById("inspector-3D-button");
|
||||
}
|
||||
};
|
||||
|
|
|
@ -92,6 +92,8 @@ TiltGL.Renderer = function TGL_Renderer(aCanvas, onError, onLoad)
|
|||
*/
|
||||
this.width = aCanvas.width;
|
||||
this.height = aCanvas.height;
|
||||
this.initialWidth = this.width;
|
||||
this.initialHeight = this.height;
|
||||
|
||||
/**
|
||||
* The current model view matrix.
|
||||
|
@ -864,21 +866,29 @@ TiltGL.Program.prototype = {
|
|||
|
||||
// use the the program if it wasn't already set
|
||||
this._context.useProgram(this._ref);
|
||||
this.cleanupVertexAttrib();
|
||||
|
||||
// check if the required vertex attributes aren't already set
|
||||
if (utils._enabledAttributes < this._attributes.length) {
|
||||
utils._enabledAttributes = this._attributes.length;
|
||||
|
||||
// enable any necessary vertex attributes using the cache
|
||||
for (let i in this._attributes) {
|
||||
if (this._attributes.hasOwnProperty(i)) {
|
||||
this._context.enableVertexAttribArray(this._attributes[i]);
|
||||
}
|
||||
}
|
||||
// enable any necessary vertex attributes using the cache
|
||||
for each (let attribute in this._attributes) {
|
||||
this._context.enableVertexAttribArray(attribute);
|
||||
utils._enabledAttributes.push(attribute);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Disables all currently enabled vertex attribute arrays.
|
||||
*/
|
||||
cleanupVertexAttrib: function TGLP_cleanupVertexAttrib()
|
||||
{
|
||||
let utils = TiltGL.ProgramUtils;
|
||||
|
||||
for each (let attribute in utils._enabledAttributes) {
|
||||
this._context.disableVertexAttribArray(attribute);
|
||||
}
|
||||
utils._enabledAttributes = [];
|
||||
},
|
||||
|
||||
/**
|
||||
* Binds a vertex buffer as an array buffer for a specific shader attribute.
|
||||
*
|
||||
|
@ -949,9 +959,9 @@ TiltGL.Program.prototype = {
|
|||
{
|
||||
let gl = this._context;
|
||||
|
||||
gl.uniform1i(this._uniforms[aSampler], 0);
|
||||
gl.activeTexture(gl.TEXTURE0);
|
||||
gl.bindTexture(gl.TEXTURE_2D, aTexture._ref);
|
||||
gl.uniform1i(this._uniforms[aSampler], 0);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1177,7 +1187,7 @@ TiltGL.ProgramUtils = {
|
|||
/**
|
||||
* Represents the current enabled attributes.
|
||||
*/
|
||||
_enabledAttributes: -1
|
||||
_enabledAttributes: []
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1415,7 +1425,7 @@ TiltGL.TextureUtils = {
|
|||
|
||||
/**
|
||||
* This shim renders a content window to a canvas element, but clamps the
|
||||
* maximum width and height of the canvas to half the WebGL MAX_TEXTURE_SIZE.
|
||||
* maximum width and height of the canvas to the WebGL MAX_TEXTURE_SIZE.
|
||||
*
|
||||
* @param {Window} aContentWindow
|
||||
* the content window to get a texture from
|
||||
|
@ -1615,5 +1625,5 @@ TiltGL.create3DContext = function TGL_create3DContext(aCanvas, aFlags)
|
|||
TiltGL.clearCache = function TGL_clearCache()
|
||||
{
|
||||
TiltGL.ProgramUtils._activeProgram = -1;
|
||||
TiltGL.ProgramUtils._enabledAttributes = -1;
|
||||
TiltGL.ProgramUtils._enabledAttributes = [];
|
||||
};
|
||||
|
|
|
@ -518,8 +518,8 @@ TiltUtils.destroyObject = function TU_destroyObject(aScope)
|
|||
}
|
||||
|
||||
// objects in Tilt usually use a function to handle internal destruction
|
||||
if ("function" === typeof aScope.finalize) {
|
||||
aScope.finalize();
|
||||
if ("function" === typeof aScope._finalize) {
|
||||
aScope._finalize();
|
||||
}
|
||||
for (let i in aScope) {
|
||||
if (aScope.hasOwnProperty(i)) {
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -38,9 +38,6 @@
|
|||
***** END LICENSE BLOCK *****/
|
||||
"use strict";
|
||||
|
||||
const SIXTEEN_OVER_255 = 16 / 255;
|
||||
const ONE_OVER_255 = 1 / 255;
|
||||
|
||||
/**
|
||||
* Given the initialization data (thickness, sizes and information about
|
||||
* each DOM node) this worker sends back the arrays representing
|
||||
|
@ -52,27 +49,44 @@ const ONE_OVER_255 = 1 / 255;
|
|||
self.onmessage = function TWC_onMessage(event)
|
||||
{
|
||||
let data = event.data;
|
||||
let maxGroupNodes = parseInt(data.maxGroupNodes);
|
||||
let thickness = data.thickness;
|
||||
let style = data.style;
|
||||
let texWidth = data.texWidth;
|
||||
let texHeight = data.texHeight;
|
||||
let nodesInfo = data.nodesInfo;
|
||||
|
||||
// create the arrays used to construct the 3D mesh data
|
||||
let vertices = [];
|
||||
let texCoord = [];
|
||||
let color = [];
|
||||
let stacksIndices = [];
|
||||
let wireframeIndices = [];
|
||||
let meshWidth = 0;
|
||||
let meshHeight = 0;
|
||||
let mesh = {
|
||||
allVertices: [],
|
||||
groups: [],
|
||||
width: 0,
|
||||
height: 0
|
||||
};
|
||||
|
||||
let vertices;
|
||||
let texCoord;
|
||||
let color;
|
||||
let stacksIndices;
|
||||
let wireframeIndices;
|
||||
let index;
|
||||
|
||||
// seed the random function to get the same values each time
|
||||
// we're doing this to avoid ugly z-fighting with overlapping nodes
|
||||
self.random.seed(0);
|
||||
|
||||
// go through all the dom nodes and compute the verts, texcoord etc.
|
||||
for (let n = 0, i = 0, len = nodesInfo.length; n < len; n++) {
|
||||
for (let n = 0, len = nodesInfo.length; n < len; n++) {
|
||||
|
||||
// check if we need to start creating a new group
|
||||
if (n % maxGroupNodes === 0) {
|
||||
vertices = []; // recreate the arrays used to construct the 3D mesh data
|
||||
texCoord = [];
|
||||
color = [];
|
||||
stacksIndices = [];
|
||||
wireframeIndices = [];
|
||||
index = 0;
|
||||
}
|
||||
|
||||
let info = nodesInfo[n];
|
||||
let depth = info.depth;
|
||||
let coord = info.coord;
|
||||
|
@ -155,6 +169,7 @@ self.onmessage = function TWC_onMessage(event)
|
|||
g20, g21, g22,
|
||||
g20, g21, g22);
|
||||
|
||||
let i = index; // number of vertex points, used to create the indices array
|
||||
let ip1 = i + 1;
|
||||
let ip2 = ip1 + 1;
|
||||
let ip3 = ip2 + 1;
|
||||
|
@ -182,23 +197,28 @@ self.onmessage = function TWC_onMessage(event)
|
|||
ip11, ip3, ip10, ip2);
|
||||
}
|
||||
|
||||
// number of vertex points, used for creating the indices array
|
||||
i += 12; // a vertex has 3 coords: x, y and z
|
||||
// there are 12 vertices in a stack representing a node
|
||||
index += 12;
|
||||
|
||||
// set the maximum mesh width and height to calculate the center offset
|
||||
meshWidth = Math.max(w, meshWidth);
|
||||
meshHeight = Math.max(h, meshHeight);
|
||||
mesh.width = Math.max(w, mesh.width);
|
||||
mesh.height = Math.max(h, mesh.height);
|
||||
|
||||
// check if we need to save the currently active group; this happens after
|
||||
// we filled all the "slots" in a group or there aren't any remaining nodes
|
||||
if (((n + 1) % maxGroupNodes === 0) || (n === len - 1)) {
|
||||
mesh.groups.push({
|
||||
vertices: vertices,
|
||||
texCoord: texCoord,
|
||||
color: color,
|
||||
stacksIndices: stacksIndices,
|
||||
wireframeIndices: wireframeIndices
|
||||
});
|
||||
mesh.allVertices = mesh.allVertices.concat(vertices);
|
||||
}
|
||||
}
|
||||
|
||||
self.postMessage({
|
||||
vertices: vertices,
|
||||
texCoord: texCoord,
|
||||
color: color,
|
||||
stacksIndices: stacksIndices,
|
||||
wireframeIndices: wireframeIndices,
|
||||
meshWidth: meshWidth,
|
||||
meshHeight: meshHeight
|
||||
});
|
||||
self.postMessage(mesh);
|
||||
close();
|
||||
};
|
||||
|
||||
|
|
|
@ -80,6 +80,7 @@ _BROWSER_TEST_FILES = \
|
|||
browser_tilt_picking_highlight01.js \
|
||||
browser_tilt_picking_highlight02.js \
|
||||
browser_tilt_picking_highlight03.js \
|
||||
browser_tilt_picking_miv.js \
|
||||
browser_tilt_utils01.js \
|
||||
browser_tilt_utils02.js \
|
||||
browser_tilt_utils03.js \
|
||||
|
|
|
@ -62,11 +62,23 @@ function performTest(canvas, arcball, callback) {
|
|||
window.setTimeout(function() {
|
||||
info("Synthesizing arcball reset key press.");
|
||||
|
||||
arcball.onResetStart = function() {
|
||||
arcball._onResetStart = function() {
|
||||
info("Starting arcball reset animation.");
|
||||
};
|
||||
|
||||
arcball.onResetFinish = function() {
|
||||
arcball._onResetStep = function() {
|
||||
info("\nlastRot: " + quat4.str(arcball._lastRot) +
|
||||
"\ndeltaRot: " + quat4.str(arcball._deltaRot) +
|
||||
"\ncurrentRot: " + quat4.str(arcball._currentRot) +
|
||||
"\nlastTrans: " + vec3.str(arcball._lastTrans) +
|
||||
"\ndeltaTrans: " + vec3.str(arcball._deltaTrans) +
|
||||
"\ncurrentTrans: " + vec3.str(arcball._currentTrans) +
|
||||
"\nadditionalRot: " + vec3.str(arcball._additionalRot) +
|
||||
"\nadditionalTrans: " + vec3.str(arcball._additionalTrans) +
|
||||
"\nzoomAmount: " + arcball._zoomAmount);
|
||||
};
|
||||
|
||||
arcball._onResetFinish = function() {
|
||||
ok(isApproxVec(arcball._lastRot, [0, 0, 0, 1]),
|
||||
"The arcball _lastRot field wasn't reset correctly.");
|
||||
ok(isApproxVec(arcball._deltaRot, [0, 0, 0, 1]),
|
||||
|
@ -89,8 +101,10 @@ function performTest(canvas, arcball, callback) {
|
|||
ok(isApproxVec([arcball._zoomAmount], [0]),
|
||||
"The arcball _zoomAmount field wasn't reset correctly.");
|
||||
|
||||
info("Finishing arcball reset test.");
|
||||
callback();
|
||||
executeSoon(function() {
|
||||
info("Finishing arcball reset test.");
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
EventUtils.synthesizeKey("VK_R", { type: "keydown" });
|
||||
|
|
|
@ -60,11 +60,23 @@ function performTest(canvas, arcball, callback) {
|
|||
window.setTimeout(function() {
|
||||
info("Synthesizing arcball reset key press.");
|
||||
|
||||
arcball.onResetStart = function() {
|
||||
arcball._onResetStart = function() {
|
||||
info("Starting arcball reset animation.");
|
||||
};
|
||||
|
||||
arcball.onResetFinish = function() {
|
||||
arcball._onResetStep = function() {
|
||||
info("\nlastRot: " + quat4.str(arcball._lastRot) +
|
||||
"\ndeltaRot: " + quat4.str(arcball._deltaRot) +
|
||||
"\ncurrentRot: " + quat4.str(arcball._currentRot) +
|
||||
"\nlastTrans: " + vec3.str(arcball._lastTrans) +
|
||||
"\ndeltaTrans: " + vec3.str(arcball._deltaTrans) +
|
||||
"\ncurrentTrans: " + vec3.str(arcball._currentTrans) +
|
||||
"\nadditionalRot: " + vec3.str(arcball._additionalRot) +
|
||||
"\nadditionalTrans: " + vec3.str(arcball._additionalTrans) +
|
||||
"\nzoomAmount: " + arcball._zoomAmount);
|
||||
};
|
||||
|
||||
arcball._onResetFinish = function() {
|
||||
ok(isApproxVec(arcball._lastRot, [0, 0, 0, 1]),
|
||||
"The arcball _lastRot field wasn't reset correctly.");
|
||||
ok(isApproxVec(arcball._deltaRot, [0, 0, 0, 1]),
|
||||
|
@ -87,8 +99,10 @@ function performTest(canvas, arcball, callback) {
|
|||
ok(isApproxVec([arcball._zoomAmount], [0]),
|
||||
"The arcball _zoomAmount field wasn't reset correctly.");
|
||||
|
||||
info("Finishing arcball reset test.");
|
||||
callback();
|
||||
executeSoon(function() {
|
||||
info("Finishing arcball reset test.");
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
EventUtils.synthesizeKey("VK_R", { type: "keydown" });
|
||||
|
|
|
@ -48,10 +48,10 @@ function test() {
|
|||
let arcball3 = new TiltVisualizer.Arcball(window, 512, 512);
|
||||
|
||||
let sphereVec = vec3.create();
|
||||
arcball3.pointToSphere(123, 456, 256, 512, 512, sphereVec);
|
||||
arcball3._pointToSphere(123, 456, 256, 512, 512, sphereVec);
|
||||
|
||||
ok(isApproxVec(sphereVec, [-0.009765625, 0.390625, 0.9204980731010437]),
|
||||
"The pointToSphere() function didn't map the coordinates correctly.");
|
||||
"The _pointToSphere() function didn't map the coordinates correctly.");
|
||||
|
||||
let stack1 = [];
|
||||
let expect1 = [
|
||||
|
|
|
@ -47,7 +47,7 @@ function test() {
|
|||
|
||||
EventUtils.synthesizeKey("VK_A", { type: "keydown" });
|
||||
EventUtils.synthesizeKey("VK_LEFT", { type: "keydown" });
|
||||
instance.controller.update();
|
||||
instance.controller._update();
|
||||
|
||||
ok(!isEqualVec(tran(), prev_tran),
|
||||
"After a translation key is pressed, the vector should change.");
|
||||
|
@ -58,7 +58,7 @@ function test() {
|
|||
|
||||
|
||||
cancellingEvent();
|
||||
instance.controller.update();
|
||||
instance.controller._update();
|
||||
|
||||
ok(!isEqualVec(tran(), prev_tran),
|
||||
"Even if the canvas lost focus, the vector has some inertia.");
|
||||
|
@ -70,7 +70,7 @@ function test() {
|
|||
|
||||
while (!isEqualVec(tran(), prev_tran) ||
|
||||
!isEqualVec(rot(), prev_rot)) {
|
||||
instance.controller.update();
|
||||
instance.controller._update();
|
||||
save();
|
||||
}
|
||||
|
||||
|
|
|
@ -21,15 +21,13 @@ function test() {
|
|||
let presenter = instance.presenter;
|
||||
let canvas = presenter.canvas;
|
||||
|
||||
presenter.onSetupMesh = function() {
|
||||
presenter._onSetupMesh = function() {
|
||||
|
||||
presenter.pickNode(canvas.width / 2, 10, {
|
||||
onpick: function(data)
|
||||
{
|
||||
ok(data.index > 0,
|
||||
"Simply picking a node didn't work properly.");
|
||||
ok(!presenter.highlight.disabled,
|
||||
"After only picking a node, it shouldn't be highlighted.");
|
||||
|
||||
Services.obs.addObserver(cleanup, DESTROYED, false);
|
||||
InspectorUI.closeInspectorUI();
|
||||
|
|
|
@ -23,13 +23,13 @@ function test() {
|
|||
presenter = instance.presenter;
|
||||
Services.obs.addObserver(whenNodeRemoved, NODE_REMOVED, false);
|
||||
|
||||
presenter.onSetupMesh = function() {
|
||||
presenter._onSetupMesh = function() {
|
||||
presenter.highlightNodeAt(presenter.canvas.width / 2, 10, {
|
||||
onpick: function()
|
||||
{
|
||||
ok(presenter._currentSelection > 0,
|
||||
"Highlighting a node didn't work properly.");
|
||||
ok(!presenter.highlight.disabled,
|
||||
ok(!presenter._highlight.disabled,
|
||||
"After highlighting a node, it should be highlighted. D'oh.");
|
||||
|
||||
presenter.deleteNode();
|
||||
|
@ -44,14 +44,14 @@ function test() {
|
|||
function whenNodeRemoved() {
|
||||
ok(presenter._currentSelection > 0,
|
||||
"Deleting a node shouldn't change the current selection.");
|
||||
ok(presenter.highlight.disabled,
|
||||
ok(presenter._highlight.disabled,
|
||||
"After deleting a node, it shouldn't be highlighted.");
|
||||
|
||||
let nodeIndex = presenter._currentSelection;
|
||||
let meshData = presenter.meshData;
|
||||
let vertices = presenter._meshStacks[0].vertices.components;
|
||||
|
||||
for (let i = 0, k = 36 * nodeIndex; i < 36; i++) {
|
||||
is(meshData.vertices[i + k], 0,
|
||||
is(vertices[i + k], 0,
|
||||
"The stack vertices weren't degenerated properly.");
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ function test() {
|
|||
presenter = instance.presenter;
|
||||
Services.obs.addObserver(whenHighlighting, HIGHLIGHTING, false);
|
||||
|
||||
presenter.onInitializationFinished = function() {
|
||||
presenter._onInitializationFinished = function() {
|
||||
let contentDocument = presenter.contentWindow.document;
|
||||
let div = contentDocument.getElementById("far-far-away");
|
||||
|
||||
|
@ -38,9 +38,9 @@ function test() {
|
|||
function whenHighlighting() {
|
||||
ok(presenter._currentSelection > 0,
|
||||
"Highlighting a node didn't work properly.");
|
||||
ok(!presenter.highlight.disabled,
|
||||
ok(!presenter._highlight.disabled,
|
||||
"After highlighting a node, it should be highlighted. D'oh.");
|
||||
ok(presenter.controller.arcball._resetInterval,
|
||||
ok(presenter.controller.arcball._resetInProgress,
|
||||
"Highlighting a node that's not already visible should trigger a reset!");
|
||||
|
||||
executeSoon(function() {
|
||||
|
@ -52,7 +52,7 @@ function whenHighlighting() {
|
|||
function whenUnhighlighting() {
|
||||
ok(presenter._currentSelection < 0,
|
||||
"Unhighlighting a should remove the current selection.");
|
||||
ok(presenter.highlight.disabled,
|
||||
ok(presenter._highlight.disabled,
|
||||
"After unhighlighting a node, it shouldn't be highlighted anymore. D'oh.");
|
||||
|
||||
executeSoon(function() {
|
||||
|
|
|
@ -23,7 +23,7 @@ function test() {
|
|||
presenter = instance.presenter;
|
||||
Services.obs.addObserver(whenHighlighting, HIGHLIGHTING, false);
|
||||
|
||||
presenter.onSetupMesh = function() {
|
||||
presenter._onSetupMesh = function() {
|
||||
let contentDocument = presenter.contentWindow.document;
|
||||
let div = contentDocument.getElementById("first-law");
|
||||
|
||||
|
@ -37,9 +37,9 @@ function test() {
|
|||
function whenHighlighting() {
|
||||
ok(presenter._currentSelection > 0,
|
||||
"Highlighting a node didn't work properly.");
|
||||
ok(!presenter.highlight.disabled,
|
||||
ok(!presenter._highlight.disabled,
|
||||
"After highlighting a node, it should be highlighted. D'oh.");
|
||||
ok(!presenter.controller.arcball._resetInterval,
|
||||
ok(!presenter.controller.arcball._resetInProgress,
|
||||
"Highlighting a node that's already visible shouldn't trigger a reset.");
|
||||
|
||||
executeSoon(function() {
|
||||
|
@ -51,7 +51,7 @@ function whenHighlighting() {
|
|||
function whenUnhighlighting() {
|
||||
ok(presenter._currentSelection < 0,
|
||||
"Unhighlighting a should remove the current selection.");
|
||||
ok(presenter.highlight.disabled,
|
||||
ok(presenter._highlight.disabled,
|
||||
"After unhighlighting a node, it shouldn't be highlighted anymore. D'oh.");
|
||||
|
||||
executeSoon(function() {
|
||||
|
|
|
@ -23,7 +23,7 @@ function test() {
|
|||
presenter = instance.presenter;
|
||||
Services.obs.addObserver(whenHighlighting, HIGHLIGHTING, false);
|
||||
|
||||
presenter.onSetupMesh = function() {
|
||||
presenter._onSetupMesh = function() {
|
||||
presenter.highlightNodeAt(presenter.canvas.width / 2, 10);
|
||||
};
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ function test() {
|
|||
function whenHighlighting() {
|
||||
ok(presenter._currentSelection > 0,
|
||||
"Highlighting a node didn't work properly.");
|
||||
ok(!presenter.highlight.disabled,
|
||||
ok(!presenter._highlight.disabled,
|
||||
"After highlighting a node, it should be highlighted. D'oh.");
|
||||
|
||||
executeSoon(function() {
|
||||
|
@ -46,7 +46,7 @@ function whenHighlighting() {
|
|||
function whenUnhighlighting() {
|
||||
ok(presenter._currentSelection < 0,
|
||||
"Unhighlighting a should remove the current selection.");
|
||||
ok(presenter.highlight.disabled,
|
||||
ok(presenter._highlight.disabled,
|
||||
"After unhighlighting a node, it shouldn't be highlighted anymore. D'oh.");
|
||||
|
||||
executeSoon(function() {
|
||||
|
|
|
@ -23,7 +23,7 @@ function test() {
|
|||
presenter = instance.presenter;
|
||||
Services.obs.addObserver(whenHighlighting, HIGHLIGHTING, false);
|
||||
|
||||
presenter.onSetupMesh = function() {
|
||||
presenter._onSetupMesh = function() {
|
||||
presenter.highlightNodeFor(5); // 1 = html, 2 = body, 3 = first div
|
||||
};
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ function test() {
|
|||
function whenHighlighting() {
|
||||
ok(presenter._currentSelection > 0,
|
||||
"Highlighting a node didn't work properly.");
|
||||
ok(!presenter.highlight.disabled,
|
||||
ok(!presenter._highlight.disabled,
|
||||
"After highlighting a node, it should be highlighted. D'oh.");
|
||||
|
||||
executeSoon(function() {
|
||||
|
@ -46,7 +46,7 @@ function whenHighlighting() {
|
|||
function whenUnhighlighting() {
|
||||
ok(presenter._currentSelection < 0,
|
||||
"Unhighlighting a should remove the current selection.");
|
||||
ok(presenter.highlight.disabled,
|
||||
ok(presenter._highlight.disabled,
|
||||
"After unhighlighting a node, it shouldn't be highlighted anymore. D'oh.");
|
||||
|
||||
executeSoon(function() {
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
let presenter;
|
||||
|
||||
function test() {
|
||||
if (!isTiltEnabled()) {
|
||||
info("Skipping highlight test because Tilt isn't enabled.");
|
||||
return;
|
||||
}
|
||||
if (!isWebGLSupported()) {
|
||||
info("Skipping highlight test because WebGL isn't supported.");
|
||||
return;
|
||||
}
|
||||
|
||||
requestLongerTimeout(10);
|
||||
waitForExplicitFinish();
|
||||
|
||||
createTab(function() {
|
||||
createTilt({
|
||||
onTiltOpen: function(instance)
|
||||
{
|
||||
presenter = instance.presenter;
|
||||
Services.obs.addObserver(whenHighlighting, HIGHLIGHTING, false);
|
||||
|
||||
presenter._onInitializationFinished = function() {
|
||||
let contentDocument = presenter.contentWindow.document;
|
||||
let div = contentDocument.getElementById("far-far-away");
|
||||
|
||||
presenter.highlightNode(div);
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function whenHighlighting() {
|
||||
ok(presenter._currentSelection > 0,
|
||||
"Highlighting a node didn't work properly.");
|
||||
ok(!presenter._highlight.disabled,
|
||||
"After highlighting a node, it should be highlighted. D'oh.");
|
||||
ok(!presenter.controller.arcball._resetInProgress,
|
||||
"Highlighting a node that's not already visible shouldn't trigger a reset " +
|
||||
"without this being explicitly requested!");
|
||||
|
||||
EventUtils.sendKey("F");
|
||||
executeSoon(whenBringingIntoView);
|
||||
}
|
||||
|
||||
function whenBringingIntoView() {
|
||||
ok(presenter._currentSelection > 0,
|
||||
"The node should still be selected.");
|
||||
ok(!presenter._highlight.disabled,
|
||||
"The node should still be highlighted");
|
||||
ok(presenter.controller.arcball._resetInProgress,
|
||||
"Highlighting a node that's not already visible should trigger a reset " +
|
||||
"when this is being explicitly requested!");
|
||||
|
||||
executeSoon(function() {
|
||||
Services.obs.addObserver(cleanup, DESTROYED, false);
|
||||
InspectorUI.closeInspectorUI();
|
||||
});
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
Services.obs.removeObserver(whenHighlighting, HIGHLIGHTING);
|
||||
Services.obs.removeObserver(cleanup, DESTROYED);
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
|
@ -2,10 +2,6 @@
|
|||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
let tmp = {};
|
||||
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm", tmp);
|
||||
let LayoutHelpers = tmp.LayoutHelpers;
|
||||
|
||||
function init(callback) {
|
||||
let iframe = gBrowser.ownerDocument.createElement("iframe");
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ let someObject = {
|
|||
};
|
||||
|
||||
let anotherObject = {
|
||||
finalize: function()
|
||||
_finalize: function()
|
||||
{
|
||||
someObject.c = 3;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ function test() {
|
|||
chromeWindow: window,
|
||||
contentWindow: gBrowser.selectedBrowser.contentWindow,
|
||||
parentNode: gBrowser.selectedBrowser.parentNode,
|
||||
requestAnimationFrame: window.mozRequestAnimationFrame,
|
||||
inspectorUI: window.InspectorUI,
|
||||
|
||||
onError: function onWebGLError()
|
||||
|
@ -71,33 +70,33 @@ function test() {
|
|||
}
|
||||
|
||||
function testPresenter(presenter) {
|
||||
ok(presenter.renderer,
|
||||
ok(presenter._renderer,
|
||||
"The presenter renderer wasn't initialized properly.");
|
||||
ok(presenter.visualizationProgram,
|
||||
ok(presenter._visualizationProgram,
|
||||
"The presenter visualizationProgram wasn't initialized properly.");
|
||||
ok(presenter.texture,
|
||||
ok(presenter._texture,
|
||||
"The presenter texture wasn't initialized properly.");
|
||||
ok(!presenter.meshStacks,
|
||||
ok(!presenter._meshStacks,
|
||||
"The presenter meshStacks shouldn't be initialized yet.");
|
||||
ok(!presenter.meshWireframe,
|
||||
ok(!presenter._meshWireframe,
|
||||
"The presenter meshWireframe shouldn't be initialized yet.");
|
||||
ok(presenter.traverseData,
|
||||
ok(presenter._traverseData,
|
||||
"The presenter nodesInformation wasn't initialized properly.");
|
||||
ok(presenter.highlight,
|
||||
ok(presenter._highlight,
|
||||
"The presenter highlight wasn't initialized properly.");
|
||||
ok(presenter.highlight.disabled,
|
||||
"The presenter highlight should be initially disabled");
|
||||
ok(isApproxVec(presenter.highlight.v0, [0, 0, 0]),
|
||||
ok(presenter._highlight.disabled,
|
||||
"The presenter highlight should be initially disabled.");
|
||||
ok(isApproxVec(presenter._highlight.v0, [0, 0, 0]),
|
||||
"The presenter highlight first vertex should be initially zeroed.");
|
||||
ok(isApproxVec(presenter.highlight.v1, [0, 0, 0]),
|
||||
ok(isApproxVec(presenter._highlight.v1, [0, 0, 0]),
|
||||
"The presenter highlight second vertex should be initially zeroed.");
|
||||
ok(isApproxVec(presenter.highlight.v2, [0, 0, 0]),
|
||||
ok(isApproxVec(presenter._highlight.v2, [0, 0, 0]),
|
||||
"The presenter highlight third vertex should be initially zeroed.");
|
||||
ok(isApproxVec(presenter.highlight.v3, [0, 0, 0]),
|
||||
ok(isApproxVec(presenter._highlight.v3, [0, 0, 0]),
|
||||
"The presenter highlight fourth vertex should be initially zeroed.");
|
||||
ok(presenter.transforms,
|
||||
"The presenter transforms wasn't initialized properly.");
|
||||
ok(isApproxVec(presenter.transforms.zoom, 1),
|
||||
is(presenter.transforms.zoom, 1,
|
||||
"The presenter transforms zoom should be initially 1.");
|
||||
ok(isApproxVec(presenter.transforms.offset, [0, 0, 0]),
|
||||
"The presenter transforms offset should be initially zeroed.");
|
||||
|
@ -113,7 +112,7 @@ function testPresenter(presenter) {
|
|||
"The presenter transforms translation wasn't modified as it should");
|
||||
ok(isApproxVec(presenter.transforms.rotation, [5, 6, 7, 8]),
|
||||
"The presenter transforms rotation wasn't modified as it should");
|
||||
ok(presenter.redraw,
|
||||
ok(presenter._redraw,
|
||||
"The new transforms should have issued a redraw request.");
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ function test() {
|
|||
let initialWidth = contentWindow.innerWidth;
|
||||
let initialHeight = contentWindow.innerHeight;
|
||||
|
||||
let renderer = instance.presenter.renderer;
|
||||
let renderer = instance.presenter._renderer;
|
||||
let arcball = instance.controller.arcball;
|
||||
|
||||
ok(isApprox(contentWindow.innerWidth * ZOOM, renderer.width, 1),
|
||||
|
|
|
@ -7,6 +7,7 @@ Components.utils.import("resource:///modules/devtools/TiltGL.jsm", tempScope);
|
|||
Components.utils.import("resource:///modules/devtools/TiltMath.jsm", tempScope);
|
||||
Components.utils.import("resource:///modules/devtools/TiltUtils.jsm", tempScope);
|
||||
Components.utils.import("resource:///modules/devtools/TiltVisualizer.jsm", tempScope);
|
||||
Components.utils.import("resource:///modules/devtools/LayoutHelpers.jsm", tempScope);
|
||||
let TiltGL = tempScope.TiltGL;
|
||||
let EPSILON = tempScope.EPSILON;
|
||||
let TiltMath = tempScope.TiltMath;
|
||||
|
@ -16,6 +17,7 @@ let mat4 = tempScope.mat4;
|
|||
let quat4 = tempScope.quat4;
|
||||
let TiltUtils = tempScope.TiltUtils;
|
||||
let TiltVisualizer = tempScope.TiltVisualizer;
|
||||
let LayoutHelpers = tempScope.LayoutHelpers;
|
||||
|
||||
|
||||
const DEFAULT_HTML = "data:text/html," +
|
||||
|
|
|
@ -0,0 +1,224 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is GCLI Commands.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Victor Porof <vporof@mozilla.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
let EXPORTED_SYMBOLS = [ "GcliCommands" ];
|
||||
|
||||
Components.utils.import("resource:///modules/gcli.jsm");
|
||||
Components.utils.import("resource:///modules/HUDService.jsm");
|
||||
|
||||
|
||||
/**
|
||||
* 'tilt' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: 'tilt',
|
||||
description: gcli.lookup("tiltDesc"),
|
||||
manual: gcli.lookup("tiltManual")
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'tilt open' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: 'tilt open',
|
||||
description: gcli.lookup("tiltOpenDesc"),
|
||||
manual: gcli.lookup("tiltOpenManual"),
|
||||
params: [
|
||||
{
|
||||
name: "node",
|
||||
type: "node",
|
||||
defaultValue: null,
|
||||
description: gcli.lookup("inspectNodeDesc"),
|
||||
manual: gcli.lookup("inspectNodeManual")
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
let chromeWindow = context.environment.chromeDocument.defaultView;
|
||||
let InspectorUI = chromeWindow.InspectorUI;
|
||||
let Tilt = chromeWindow.Tilt;
|
||||
|
||||
if (Tilt.currentInstance) {
|
||||
Tilt.update(args.node);
|
||||
} else {
|
||||
let hudId = chromeWindow.HUDConsoleUI.getOpenHUD();
|
||||
let hud = HUDService.getHudReferenceById(hudId);
|
||||
|
||||
if (hud && !hud.consolePanel) {
|
||||
HUDService.deactivateHUDForContext(chromeWindow.gBrowser.selectedTab);
|
||||
}
|
||||
InspectorUI.openInspectorUI(args.node);
|
||||
Tilt.initialize();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'tilt translate' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: 'tilt translate',
|
||||
description: gcli.lookup("tiltTranslateDesc"),
|
||||
manual: gcli.lookup("tiltTranslateManual"),
|
||||
params: [
|
||||
{
|
||||
name: "x",
|
||||
type: "number",
|
||||
defaultValue: 0,
|
||||
description: gcli.lookup("tiltTranslateXDesc"),
|
||||
manual: gcli.lookup("tiltTranslateXManual")
|
||||
},
|
||||
{
|
||||
name: "y",
|
||||
type: "number",
|
||||
defaultValue: 0,
|
||||
description: gcli.lookup("tiltTranslateYDesc"),
|
||||
manual: gcli.lookup("tiltTranslateYManual")
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
let chromeWindow = context.environment.chromeDocument.defaultView;
|
||||
let Tilt = chromeWindow.Tilt;
|
||||
|
||||
if (Tilt.currentInstance) {
|
||||
Tilt.currentInstance.controller.arcball.translate([args.x, args.y]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'tilt rotate' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: 'tilt rotate',
|
||||
description: gcli.lookup("tiltRotateDesc"),
|
||||
manual: gcli.lookup("tiltRotateManual"),
|
||||
params: [
|
||||
{
|
||||
name: "x",
|
||||
type: { name: 'number', min: -360, max: 360, step: 10 },
|
||||
defaultValue: 0,
|
||||
description: gcli.lookup("tiltRotateXDesc"),
|
||||
manual: gcli.lookup("tiltRotateXManual")
|
||||
},
|
||||
{
|
||||
name: "y",
|
||||
type: { name: 'number', min: -360, max: 360, step: 10 },
|
||||
defaultValue: 0,
|
||||
description: gcli.lookup("tiltRotateYDesc"),
|
||||
manual: gcli.lookup("tiltRotateYManual")
|
||||
},
|
||||
{
|
||||
name: "z",
|
||||
type: { name: 'number', min: -360, max: 360, step: 10 },
|
||||
defaultValue: 0,
|
||||
description: gcli.lookup("tiltRotateZDesc"),
|
||||
manual: gcli.lookup("tiltRotateZManual")
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
let chromeWindow = context.environment.chromeDocument.defaultView;
|
||||
let Tilt = chromeWindow.Tilt;
|
||||
|
||||
if (Tilt.currentInstance) {
|
||||
Tilt.currentInstance.controller.arcball.rotate([args.x, args.y, args.z]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'tilt zoom' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: 'tilt zoom',
|
||||
description: gcli.lookup("tiltZoomDesc"),
|
||||
manual: gcli.lookup("tiltZoomManual"),
|
||||
params: [
|
||||
{
|
||||
name: "zoom",
|
||||
type: { name: 'number' },
|
||||
description: gcli.lookup("tiltZoomAmountDesc"),
|
||||
manual: gcli.lookup("tiltZoomAmountManual")
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
let chromeWindow = context.environment.chromeDocument.defaultView;
|
||||
let Tilt = chromeWindow.Tilt;
|
||||
|
||||
if (Tilt.currentInstance) {
|
||||
Tilt.currentInstance.controller.arcball.zoom(-args.zoom);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'tilt reset' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: 'tilt reset',
|
||||
description: gcli.lookup("tiltResetDesc"),
|
||||
manual: gcli.lookup("tiltResetManual"),
|
||||
exec: function(args, context) {
|
||||
let chromeWindow = context.environment.chromeDocument.defaultView;
|
||||
let Tilt = chromeWindow.Tilt;
|
||||
|
||||
if (Tilt.currentInstance) {
|
||||
Tilt.currentInstance.controller.arcball.reset();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'tilt close' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: 'tilt close',
|
||||
description: gcli.lookup("tiltCloseDesc"),
|
||||
manual: gcli.lookup("tiltCloseManual"),
|
||||
exec: function(args, context) {
|
||||
let chromeWindow = context.environment.chromeDocument.defaultView;
|
||||
let Tilt = chromeWindow.Tilt;
|
||||
|
||||
Tilt.destroy(Tilt.currentWindowId);
|
||||
}
|
||||
});
|
|
@ -164,6 +164,7 @@ function loadCommands() {
|
|||
let commandExports = {};
|
||||
|
||||
Cu.import("resource:///modules/GcliCommands.jsm", commandExports);
|
||||
Cu.import("resource:///modules/GcliTiltCommands.jsm", commandExports);
|
||||
|
||||
return commandExports;
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ EXTRA_JS_MODULES = \
|
|||
AutocompletePopup.jsm \
|
||||
gcli.jsm \
|
||||
GcliCommands.jsm \
|
||||
GcliTiltCommands.jsm \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_PP_JS_MODULES = \
|
||||
|
|
|
@ -1103,7 +1103,6 @@ exports.testIncompleteMultiMatch = function() {
|
|||
test.is(Status.ERROR, status);
|
||||
test.is(-1, assignC.paramIndex);
|
||||
test.ok(assignC.getPredictions().length > 0);
|
||||
test.ok(assignC.getPredictions().length < 20); // could break ...
|
||||
verifyPredictionsContains('tsv', assignC.getPredictions());
|
||||
verifyPredictionsContains('tsr', assignC.getPredictions());
|
||||
test.is(null, requ.commandAssignment.getValue());
|
||||
|
|
|
@ -213,11 +213,19 @@ can reach it easily. -->
|
|||
<!ENTITY scratchpad.keycode "VK_F4">
|
||||
<!ENTITY scratchpad.keytext "F4">
|
||||
|
||||
<!ENTITY inspectPanelTitle.label "HTML">
|
||||
<!ENTITY inspectButton.label "Inspect">
|
||||
<!ENTITY inspectButton.accesskey "I">
|
||||
<!ENTITY inspectCloseButton.tooltiptext "Close Inspector">
|
||||
|
||||
<!ENTITY inspectorHTMLCopyInner.label "Copy Inner HTML">
|
||||
<!ENTITY inspectorHTMLCopyInner.accesskey "I">
|
||||
|
||||
<!ENTITY inspectorHTMLCopyOuter.label "Copy Outer HTML">
|
||||
<!ENTITY inspectorHTMLCopyOuter.accesskey "O">
|
||||
|
||||
<!ENTITY inspectorHTMLDelete.label "Delete Node">
|
||||
<!ENTITY inspectorHTMLDelete.accesskey "D">
|
||||
|
||||
<!-- LOCALIZATION NOTE (inspect3DViewButton.label): This button shows an
|
||||
- alternate view for the Inspector, creating a 3D visualization of the
|
||||
- webpage. -->
|
||||
|
@ -599,3 +607,15 @@ just addresses the organization to follow, e.g. "This site is run by " -->
|
|||
|
||||
<!ENTITY addonBarCloseButton.tooltip "Close Add-on Bar">
|
||||
<!ENTITY toggleAddonBarCmd.key "/">
|
||||
|
||||
<!-- LOCALIZATION NOTE (htmlPanel.label): This is a label for a button that
|
||||
activates the Web Developer->Inspect UI's HTML Tree Panel. -->
|
||||
<!ENTITY htmlPanel.label "HTML">
|
||||
|
||||
<!-- LOCALIZATION NOTE (htmlPanel.tooltiptext): The text that appears when a user
|
||||
hovers over the HTML panel's toolbar button. -->
|
||||
<!ENTITY htmlPanel.tooltiptext "HTML panel">
|
||||
|
||||
<!-- LOCALIZATION NOTE (htmlPanel.accesskey): The key bound to the HTML panel's
|
||||
toolbar button -->
|
||||
<!ENTITY htmlPanel.accesskey "H">
|
||||
|
|
|
@ -56,6 +56,136 @@ inspectNodeDesc=CSS selector
|
|||
# on what it does.
|
||||
inspectNodeManual=A CSS selector for use with Document.querySelector which identifies a single element
|
||||
|
||||
# LOCALIZATION NOTE (tiltDesc) A very short description of the 'tilt'
|
||||
# command. See tiltManual for a fuller description of what it does. This
|
||||
# string is designed to be shown in a menu alongside the command name, which
|
||||
# is why it should be as short as possible.
|
||||
tiltDesc=Visualize the webpage in 3D
|
||||
|
||||
# LOCALIZATION NOTE (tiltManual) A fuller description of the 'tilt'
|
||||
# command, displayed when the user asks for help on what it does.
|
||||
tiltManual=Investigate the relationship between various parts of a webpage and their ancestors in a 3D environment
|
||||
|
||||
# LOCALIZATION NOTE (tiltOpenDesc) A very short description of the 'tilt inspect'
|
||||
# command. See tiltOpenManual for a fuller description of what it does. This
|
||||
# string is designed to be shown in a menu alongside the command name, which
|
||||
# is why it should be as short as possible.
|
||||
tiltOpenDesc=Open the Inspector 3D view
|
||||
|
||||
# LOCALIZATION NOTE (tiltOpenManual) A fuller description of the 'tilt translate'
|
||||
# command, displayed when the user asks for help on what it does.
|
||||
tiltOpenManual=Initialize the 3D page inspector and optionally highlight a node using a CSS selector
|
||||
|
||||
# LOCALIZATION NOTE (tiltTranslateDesc) A very short description of the 'tilt translate'
|
||||
# command. See tiltTranslateManual for a fuller description of what it does. This
|
||||
# string is designed to be shown in a menu alongside the command name, which
|
||||
# is why it should be as short as possible.
|
||||
tiltTranslateDesc=Move the webpage mesh
|
||||
|
||||
# LOCALIZATION NOTE (tiltTranslateManual) A fuller description of the 'tilt translate'
|
||||
# command, displayed when the user asks for help on what it does.
|
||||
tiltTranslateManual=Incrementally translate the webpage mesh in a certain direction
|
||||
|
||||
# LOCALIZATION NOTE (tiltTranslateXDesc) A very short string to describe the
|
||||
# 'x' parameter to the 'tilt translate' command, which is displayed in a dialog
|
||||
# when the user is using this command.
|
||||
tiltTranslateXDesc=X (pixels)
|
||||
|
||||
# LOCALIZATION NOTE (tiltTranslateXManual) A fuller description of the 'x'
|
||||
# parameter to the 'translate' command, displayed when the user asks for help
|
||||
# on what it does.
|
||||
tiltTranslateXManual=The ammount in pixels to translate the webpage mesh on the X axis
|
||||
|
||||
# LOCALIZATION NOTE (tiltTranslateYDesc) A very short string to describe the
|
||||
# 'y' parameter to the 'tilt translate' command, which is displayed in a dialog
|
||||
# when the user is using this command.
|
||||
tiltTranslateYDesc=Y (pixels)
|
||||
|
||||
# LOCALIZATION NOTE (tiltTranslateYManual) A fuller description of the 'y'
|
||||
# parameter to the 'translate' command, displayed when the user asks for help
|
||||
# on what it does.
|
||||
tiltTranslateYManual=The ammount in pixels to translate the webpage mesh on the Y axis
|
||||
|
||||
# LOCALIZATION NOTE (tiltRotateDesc) A very short description of the 'tilt rotate'
|
||||
# command. See tiltRotateManual for a fuller description of what it does. This
|
||||
# string is designed to be shown in a menu alongside the command name, which
|
||||
# is why it should be as short as possible.
|
||||
tiltRotateDesc=Spin the webpage mesh
|
||||
|
||||
# LOCALIZATION NOTE (tiltRotateManual) A fuller description of the 'tilt rotate'
|
||||
# command, displayed when the user asks for help on what it does.
|
||||
tiltRotateManual=Incrementally rotate the webpage mesh in a certain direction
|
||||
|
||||
# LOCALIZATION NOTE (tiltRotateXDesc) A very short string to describe the
|
||||
# 'x' parameter to the 'tilt rotate' command, which is displayed in a dialog
|
||||
# when the user is using this command.
|
||||
tiltRotateXDesc=X (degrees)
|
||||
|
||||
# LOCALIZATION NOTE (tiltRotateXManual) A fuller description of the 'x'
|
||||
# parameter to the 'rotate' command, displayed when the user asks for help
|
||||
# on what it does.
|
||||
tiltRotateXManual=The ammount in degrees to rotate the webpage mesh along the X axis
|
||||
|
||||
# LOCALIZATION NOTE (tiltRotateYDesc) A very short string to describe the
|
||||
# 'y' parameter to the 'tilt rotate' command, which is displayed in a dialog
|
||||
# when the user is using this command.
|
||||
tiltRotateYDesc=Y (degrees)
|
||||
|
||||
# LOCALIZATION NOTE (tiltRotateYManual) A fuller description of the 'y'
|
||||
# parameter to the 'rotate' command, displayed when the user asks for help
|
||||
# on what it does.
|
||||
tiltRotateYManual=The ammount in degrees to rotate the webpage mesh along the Y axis
|
||||
|
||||
# LOCALIZATION NOTE (tiltRotateZDesc) A very short string to describe the
|
||||
# 'z' parameter to the 'tilt rotate' command, which is displayed in a dialog
|
||||
# when the user is using this command.
|
||||
tiltRotateZDesc=Z (degrees)
|
||||
|
||||
# LOCALIZATION NOTE (tiltRotateZManual) A fuller description of the 'z'
|
||||
# parameter to the 'rotate' command, displayed when the user asks for help
|
||||
# on what it does.
|
||||
tiltRotateZManual=The ammount in degrees to rotate the webpage mesh along the Z axis
|
||||
|
||||
# LOCALIZATION NOTE (tiltZoomDesc) A very short description of the 'tilt zoom'
|
||||
# command. See tiltZoomManual for a fuller description of what it does. This
|
||||
# string is designed to be shown in a menu alongside the command name, which
|
||||
# is why it should be as short as possible.
|
||||
tiltZoomDesc=Move away or towards the webpage mesh
|
||||
|
||||
# LOCALIZATION NOTE (tiltZoomManual) A fuller description of the 'tilt zoom'
|
||||
# command, displayed when the user asks for help on what it does.
|
||||
tiltZoomManual=Incrementally move the webpage mesh in a certain direction along the Z axis
|
||||
|
||||
# LOCALIZATION NOTE (tiltZoomAmountDesc) A very short string to describe the
|
||||
# 'zoom' parameter to the 'tilt zoom' command, which is displayed in a dialog
|
||||
# when the user is using this command.
|
||||
tiltZoomAmountDesc=Zoom (pixels)
|
||||
|
||||
# LOCALIZATION NOTE (tiltZoomAmmuntManual) A fuller description of the 'zoom'
|
||||
# parameter to the 'zoom' command, displayed when the user asks for help
|
||||
# on what it does.
|
||||
tiltZoomAmountManual=The amount in pixels to translate the webpage mesh along the Z axis
|
||||
|
||||
# LOCALIZATION NOTE (tiltResetDesc) A very short description of the 'tilt reset'
|
||||
# command. See tiltResetManual for a fuller description of what it does. This
|
||||
# string is designed to be shown in a menu alongside the command name, which
|
||||
# is why it should be as short as possible.
|
||||
tiltResetDesc=Reset the translation, rotation and zoom
|
||||
|
||||
# LOCALIZATION NOTE (tiltResetManual) A fuller description of the 'tilt reset'
|
||||
# command, displayed when the user asks for help on what it does.
|
||||
tiltResetManual=Resets any transformations applied to the webpage mesh modelview matrix
|
||||
|
||||
# LOCALIZATION NOTE (tiltCloseDesc) A very short description of the 'tilt close'
|
||||
# command. See tiltCloseManual for a fuller description of what it does. This
|
||||
# string is designed to be shown in a menu alongside the command name, which
|
||||
# is why it should be as short as possible.
|
||||
tiltCloseDesc=Close the visualization if open
|
||||
|
||||
# LOCALIZATION NOTE (tiltCloseManual) A fuller description of the 'tilt close'
|
||||
# command, displayed when the user asks for help on what it does.
|
||||
tiltCloseManual=Close the visualization and switch back to the Inspector default highlighter
|
||||
|
||||
# LOCALIZATION NOTE (breakDesc) A very short string used to describe the
|
||||
# function of the break command.
|
||||
breakDesc=Manage breakpoints
|
||||
|
|
|
@ -20,20 +20,8 @@ breadcrumbs.siblings=Siblings
|
|||
# LOCALIZATION NOTE (htmlPanel): Used in the Inspector tool's openInspectorUI
|
||||
# method when registering the HTML panel.
|
||||
|
||||
# LOCALIZATION NOTE (htmlPanel.label): This is a lable for a button that
|
||||
# activates the Web Developer->Inspect UI's HTML Tree Panel.
|
||||
htmlPanel.label=HTML
|
||||
|
||||
# LOCALIZATION NOTE (htmlPanel.tooltiptext): The text that appears when a user
|
||||
# hovers over the HTML panel's toolbar button.
|
||||
htmlPanel.tooltiptext=HTML panel
|
||||
|
||||
# LOCALIZATION NOTE (htmlPanel.accesskey): The key bound to the HTML panel's
|
||||
# toolbar button.
|
||||
htmlPanel.accesskey=H
|
||||
|
||||
# LOCALIZATION NOTE (ruleView.*): Button label, accesskey and tooltip text
|
||||
# associated with the Highlighter's CSS Rule View in the Style Sidebar.
|
||||
ruleView.label=Rules
|
||||
ruleView.accesskey=R
|
||||
ruleView.tooltiptext=View and Edit CSS
|
||||
ruleView.tooltiptext=View and Edit CSS
|
||||
|
|
|
@ -1992,10 +1992,6 @@ panel[dimmed="true"] {
|
|||
border-top: 1px solid hsla(210, 8%, 5%, .65);
|
||||
}
|
||||
|
||||
#inspector-toolbar[treepanel-open] {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
#devtools-side-splitter {
|
||||
-moz-appearance: none;
|
||||
border: 0;
|
||||
|
@ -2011,15 +2007,6 @@ panel[dimmed="true"] {
|
|||
background-color: -moz-Field;
|
||||
}
|
||||
|
||||
/* Highlighter - toolbar resizer */
|
||||
|
||||
#inspector-top-resizer {
|
||||
-moz-appearance: none;
|
||||
cursor: n-resize;
|
||||
background: none;
|
||||
height: 4px;
|
||||
}
|
||||
|
||||
/* Highlighter - Node Infobar */
|
||||
|
||||
/* Highlighter - Node Infobar - text */
|
||||
|
@ -2032,6 +2019,10 @@ html|*#highlighter-nodeinfobar-id {
|
|||
color: hsl(90, 79%, 52%);
|
||||
}
|
||||
|
||||
html|*#highlighter-nodeinfobar-pseudo-classes {
|
||||
color: hsl(20, 100%, 70%);
|
||||
}
|
||||
|
||||
/* Highlighter - Node Infobar - box & arrow */
|
||||
|
||||
#highlighter-nodeinfobar {
|
||||
|
@ -2136,11 +2127,19 @@ html|*#highlighter-nodeinfobar-id {
|
|||
color: hsl(205,100%,70%);
|
||||
}
|
||||
|
||||
.inspector-breadcrumbs-button[checked] > .inspector-breadcrumbs-pseudo-classes {
|
||||
color: hsl(20, 100%, 70%);
|
||||
}
|
||||
|
||||
.inspector-breadcrumbs-id,
|
||||
.inspector-breadcrumbs-classes {
|
||||
color: #8d99a6;
|
||||
}
|
||||
|
||||
.inspector-breadcrumbs-pseudo-classes {
|
||||
color: hsl(20, 100%, 85%);
|
||||
}
|
||||
|
||||
/* Highlighter toolbar - breadcrumbs - LTR */
|
||||
|
||||
.inspector-breadcrumbs-button:-moz-locale-dir(ltr):first-of-type {
|
||||
|
@ -2260,3 +2259,15 @@ html|*#highlighter-nodeinfobar-id {
|
|||
.inspector-breadcrumbs-button:last-of-type[checked]:hover:active:-moz-locale-dir(rtl) {
|
||||
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-selected-pressed.png") 1 13 2 13 fill stretch;
|
||||
}
|
||||
|
||||
/* Highlighter toolbar - HTML Tree */
|
||||
|
||||
#inspector-tree-splitter {
|
||||
-moz-appearance: none;
|
||||
border-top: 1px solid black;
|
||||
border-bottom-width: 0;
|
||||
min-height: 3px;
|
||||
height: 3px;
|
||||
margin-bottom: -3px;
|
||||
position: relative;
|
||||
}
|
||||
|
|
|
@ -247,6 +247,29 @@ a {
|
|||
-moz-appearance: treetwistyopen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Animations
|
||||
*/
|
||||
|
||||
.details[open] {
|
||||
-moz-animation-duration: 0.25s;
|
||||
-moz-animation-name: showblock;
|
||||
}
|
||||
|
||||
@-moz-keyframes showblock {
|
||||
from {
|
||||
opacity: 0;
|
||||
-moz-transform-origin: top;
|
||||
-moz-transform: scaleY(0);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
-moz-transform-origin: top;
|
||||
-moz-transform: scaleY(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display helpers
|
||||
*/
|
||||
|
|
|
@ -59,7 +59,7 @@ body {
|
|||
overflow: auto;
|
||||
font-family: Lucida Grande, sans-serif;
|
||||
font-size: 11px;
|
||||
border-top: 1px solid #BBB9BA;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
|
|
|
@ -2739,12 +2739,6 @@ panel[dimmed="true"] {
|
|||
padding-right: 18px; /* use -moz-padding-end when/if bug 631729 gets fixed */
|
||||
}
|
||||
|
||||
#inspector-toolbar[treepanel-open] {
|
||||
padding-top: 0;
|
||||
padding-right: 0;
|
||||
-moz-padding-end: 4px;
|
||||
}
|
||||
|
||||
#devtools-side-splitter {
|
||||
background-image: none !important;
|
||||
border: 0;
|
||||
|
@ -2760,15 +2754,6 @@ panel[dimmed="true"] {
|
|||
background-color: -moz-Field;
|
||||
}
|
||||
|
||||
/* Highlighter - toolbar resizer */
|
||||
|
||||
#inspector-top-resizer {
|
||||
-moz-appearance: none;
|
||||
cursor: n-resize;
|
||||
background: none;
|
||||
height: 4px;
|
||||
}
|
||||
|
||||
/* Highlighter - Node Infobar */
|
||||
|
||||
/* Highlighter - Node Infobar - text */
|
||||
|
@ -2781,6 +2766,10 @@ html|*#highlighter-nodeinfobar-id {
|
|||
color: hsl(90, 79%, 52%);
|
||||
}
|
||||
|
||||
html|*#highlighter-nodeinfobar-pseudo-classes {
|
||||
color: hsl(20, 100%, 70%);
|
||||
}
|
||||
|
||||
/* Highlighter - Node Infobar - box & arrow */
|
||||
|
||||
#highlighter-nodeinfobar {
|
||||
|
@ -2879,11 +2868,19 @@ html|*#highlighter-nodeinfobar-id {
|
|||
color: hsl(205,100%,70%);
|
||||
}
|
||||
|
||||
.inspector-breadcrumbs-button[checked] > .inspector-breadcrumbs-pseudo-classes {
|
||||
color: hsl(20, 100%, 70%);
|
||||
}
|
||||
|
||||
.inspector-breadcrumbs-id,
|
||||
.inspector-breadcrumbs-classes {
|
||||
color: #8d99a6;
|
||||
}
|
||||
|
||||
.inspector-breadcrumbs-pseudo-classes {
|
||||
color: hsl(20, 100%, 85%);
|
||||
}
|
||||
|
||||
/* Highlighter toolbar - breadcrumbs - LTR */
|
||||
|
||||
.inspector-breadcrumbs-button:-moz-locale-dir(ltr):first-of-type {
|
||||
|
@ -3003,3 +3000,15 @@ html|*#highlighter-nodeinfobar-id {
|
|||
.inspector-breadcrumbs-button:last-of-type[checked]:hover:active:-moz-locale-dir(rtl) {
|
||||
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-selected-pressed.png") 1 13 2 13 fill stretch;
|
||||
}
|
||||
|
||||
/* Highlighter toolbar - HTML Tree */
|
||||
|
||||
#inspector-tree-splitter {
|
||||
-moz-appearance: none;
|
||||
border-top: 1px solid black;
|
||||
border-bottom-width: 0;
|
||||
min-height: 3px;
|
||||
height: 3px;
|
||||
margin-bottom: -3px;
|
||||
position: relative;
|
||||
}
|
||||
|
|
|
@ -245,6 +245,29 @@ a {
|
|||
-moz-appearance: treetwistyopen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Animations
|
||||
*/
|
||||
|
||||
.details[open] {
|
||||
-moz-animation-duration: 0.25s;
|
||||
-moz-animation-name: showblock;
|
||||
}
|
||||
|
||||
@-moz-keyframes showblock {
|
||||
from {
|
||||
opacity: 0;
|
||||
-moz-transform-origin: top;
|
||||
-moz-transform: scaleY(0);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
-moz-transform-origin: top;
|
||||
-moz-transform: scaleY(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display helpers
|
||||
*/
|
||||
|
|
|
@ -59,7 +59,7 @@ body {
|
|||
overflow: auto;
|
||||
font-family: Lucida Grande, sans-serif;
|
||||
font-size: 11px;
|
||||
border-top: 1px solid #BBB9BA;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
|
|
|
@ -2687,10 +2687,6 @@ panel[dimmed="true"] {
|
|||
border-top: 1px solid hsla(211,68%,6%,.65) !important;
|
||||
}
|
||||
|
||||
#inspector-toolbar[treepanel-open] {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
#devtools-side-splitter {
|
||||
border: 0;
|
||||
-moz-border-start: 1px solid #242b33;
|
||||
|
@ -2705,15 +2701,6 @@ panel[dimmed="true"] {
|
|||
background-color: -moz-Field;
|
||||
}
|
||||
|
||||
/* Highlighter - toolbar resizer */
|
||||
|
||||
#inspector-top-resizer {
|
||||
-moz-appearance: none;
|
||||
cursor: n-resize;
|
||||
background: none;
|
||||
height: 4px;
|
||||
}
|
||||
|
||||
/* Highlighter - Node Infobar */
|
||||
|
||||
/* Highlighter - Node Infobar - text */
|
||||
|
@ -2726,6 +2713,10 @@ html|*#highlighter-nodeinfobar-id {
|
|||
color: hsl(90, 79%, 52%);
|
||||
}
|
||||
|
||||
html|*#highlighter-nodeinfobar-pseudo-classes {
|
||||
color: hsl(20, 100%, 70%);
|
||||
}
|
||||
|
||||
/* Highlighter - Node Infobar - box & arrow */
|
||||
|
||||
#highlighter-nodeinfobar {
|
||||
|
@ -2830,11 +2821,19 @@ html|*#highlighter-nodeinfobar-id {
|
|||
color: hsl(200,100%,70%);
|
||||
}
|
||||
|
||||
.inspector-breadcrumbs-button[checked] > .inspector-breadcrumbs-pseudo-classes {
|
||||
color: hsl(20, 100%, 70%);
|
||||
}
|
||||
|
||||
.inspector-breadcrumbs-id,
|
||||
.inspector-breadcrumbs-classes {
|
||||
color: #8d99a6;
|
||||
}
|
||||
|
||||
.inspector-breadcrumbs-pseudo-classes {
|
||||
color: hsl(20, 100%, 85%);
|
||||
}
|
||||
|
||||
/* Highlighter toolbar - breadcrumbs - LTR */
|
||||
|
||||
.inspector-breadcrumbs-button:-moz-locale-dir(ltr):first-of-type {
|
||||
|
@ -2954,3 +2953,15 @@ html|*#highlighter-nodeinfobar-id {
|
|||
.inspector-breadcrumbs-button:last-of-type[checked]:hover:active:-moz-locale-dir(rtl) {
|
||||
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-selected-pressed.png") 2 13 2 13 fill stretch;
|
||||
}
|
||||
|
||||
/* Highlighter toolbar - HTML Tree */
|
||||
|
||||
#inspector-tree-splitter {
|
||||
-moz-appearance: none;
|
||||
border-top: 1px solid black;
|
||||
border-bottom-width: 0;
|
||||
min-height: 3px;
|
||||
height: 3px;
|
||||
margin-bottom: -3px;
|
||||
position: relative;
|
||||
}
|
||||
|
|
|
@ -249,6 +249,29 @@ a {
|
|||
background-image: url("chrome://global/skin/tree/twisty-open.png");
|
||||
}
|
||||
|
||||
/**
|
||||
* Animations
|
||||
*/
|
||||
|
||||
.details[open] {
|
||||
-moz-animation-duration: 0.25s;
|
||||
-moz-animation-name: showblock;
|
||||
}
|
||||
|
||||
@-moz-keyframes showblock {
|
||||
from {
|
||||
opacity: 0;
|
||||
-moz-transform-origin: top;
|
||||
-moz-transform: scaleY(0);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
-moz-transform-origin: top;
|
||||
-moz-transform: scaleY(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display helpers
|
||||
*/
|
||||
|
|
|
@ -59,6 +59,7 @@ body {
|
|||
overflow: auto;
|
||||
font-family: Lucida Grande, sans-serif;
|
||||
font-size: 11px;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
|
|
|
@ -754,7 +754,7 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
|
|||
self.log.info("Can't trigger Breakpad, just killing process")
|
||||
proc.kill()
|
||||
|
||||
def waitForFinish(self, proc, utilityPath, timeout, maxTime, startTime, debuggerInfo, symbolsPath):
|
||||
def waitForFinish(self, proc, utilityPath, timeout, maxTime, startTime, debuggerInfo, symbolsPath, logger):
|
||||
""" Look for timeout or crashes and return the status after the process terminates """
|
||||
stackFixerProcess = None
|
||||
stackFixerFunction = None
|
||||
|
@ -788,6 +788,8 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
|
|||
|
||||
(line, didTimeout) = self.readWithTimeout(logsource, timeout)
|
||||
while line != "" and not didTimeout:
|
||||
if logger:
|
||||
logger.log(line)
|
||||
if "TEST-START" in line and "|" in line:
|
||||
self.lastTestSeen = line.split("|")[1].strip()
|
||||
if stackFixerFunction:
|
||||
|
@ -877,7 +879,7 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
|
|||
|
||||
def runApp(self, testURL, env, app, profileDir, extraArgs,
|
||||
runSSLTunnel = False, utilityPath = None,
|
||||
xrePath = None, certPath = None,
|
||||
xrePath = None, certPath = None, logger = None,
|
||||
debuggerInfo = None, symbolsPath = None,
|
||||
timeout = -1, maxTime = None):
|
||||
"""
|
||||
|
@ -936,7 +938,7 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
|
|||
stderr = subprocess.STDOUT)
|
||||
self.log.info("INFO | automation.py | Application pid: %d", proc.pid)
|
||||
|
||||
status = self.waitForFinish(proc, utilityPath, timeout, maxTime, startTime, debuggerInfo, symbolsPath)
|
||||
status = self.waitForFinish(proc, utilityPath, timeout, maxTime, startTime, debuggerInfo, symbolsPath, logger)
|
||||
self.log.info("INFO | automation.py | Application ran for: %s", str(datetime.now() - startTime))
|
||||
|
||||
# Do a final check for zombie child processes.
|
||||
|
|
|
@ -40,6 +40,7 @@ from __future__ import with_statement
|
|||
import glob, logging, os, platform, shutil, subprocess, sys, tempfile, urllib2, zipfile
|
||||
import re
|
||||
from urlparse import urlparse
|
||||
from operator import itemgetter
|
||||
|
||||
__all__ = [
|
||||
"ZipFileReader",
|
||||
|
@ -52,6 +53,7 @@ __all__ = [
|
|||
"DEBUGGER_INFO",
|
||||
"replaceBackSlashes",
|
||||
"wrapCommand",
|
||||
"ShutdownLeakLogger"
|
||||
]
|
||||
|
||||
# Map of debugging programs to information about them, like default arguments
|
||||
|
@ -450,3 +452,106 @@ def wrapCommand(cmd):
|
|||
return ["arch", "-arch", "i386"] + cmd
|
||||
# otherwise just execute the command normally
|
||||
return cmd
|
||||
|
||||
class ShutdownLeakLogger(object):
|
||||
"""
|
||||
Parses the mochitest run log when running a debug build, assigns all leaked
|
||||
DOM windows (that are still around after test suite shutdown, despite running
|
||||
the GC) to the tests that created them and prints leak statistics.
|
||||
"""
|
||||
MAX_LEAK_COUNT = 120
|
||||
|
||||
def __init__(self, logger):
|
||||
self.logger = logger
|
||||
self.tests = []
|
||||
self.leakedWindows = {}
|
||||
self.leakedDocShells = set()
|
||||
self.currentTest = None
|
||||
self.seenShutdown = False
|
||||
|
||||
def log(self, line):
|
||||
if line[2:11] == "DOMWINDOW":
|
||||
self._logWindow(line)
|
||||
elif line[2:10] == "DOCSHELL":
|
||||
self._logDocShell(line)
|
||||
elif line.startswith("TEST-START"):
|
||||
fileName = line.split(" ")[-1].strip().replace("chrome://mochitests/content/browser/", "")
|
||||
self.currentTest = {"fileName": fileName, "windows": set(), "docShells": set()}
|
||||
elif line.startswith("INFO TEST-END"):
|
||||
# don't track a test if no windows or docShells leaked
|
||||
if self.currentTest["windows"] and self.currentTest["docShells"]:
|
||||
self.tests.append(self.currentTest)
|
||||
self.currentTest = None
|
||||
elif line.startswith("INFO TEST-START | Shutdown"):
|
||||
self.seenShutdown = True
|
||||
|
||||
def parse(self):
|
||||
leakingTests = self._parseLeakingTests()
|
||||
|
||||
if leakingTests:
|
||||
totalWindows = sum(len(test["leakedWindows"]) for test in leakingTests)
|
||||
totalDocShells = sum(len(test["leakedDocShells"]) for test in leakingTests)
|
||||
msgType = "INFO" if totalWindows + totalDocShells < self.MAX_LEAK_COUNT else "UNEXPECTED-FAIL"
|
||||
self.logger.info("TEST-%s | ShutdownLeaks | leaked %d DOMWindow(s) and %d DocShell(s) until shutdown", msgType, totalWindows, totalDocShells)
|
||||
|
||||
for test in leakingTests:
|
||||
self.logger.info("\n[%s]", test["fileName"])
|
||||
|
||||
for url, count in self._zipLeakedWindows(test["leakedWindows"]):
|
||||
self.logger.info(" %d window(s) [url = %s]", count, url)
|
||||
|
||||
if test["leakedDocShells"]:
|
||||
self.logger.info(" %d docShell(s)", len(test["leakedDocShells"]))
|
||||
|
||||
def _logWindow(self, line):
|
||||
created = line[:2] == "++"
|
||||
id = self._parseValue(line, "serial")
|
||||
|
||||
if self.currentTest:
|
||||
windows = self.currentTest["windows"]
|
||||
if created:
|
||||
windows.add(id)
|
||||
else:
|
||||
windows.discard(id)
|
||||
elif self.seenShutdown and not created:
|
||||
self.leakedWindows[id] = self._parseValue(line, "url")
|
||||
|
||||
def _logDocShell(self, line):
|
||||
created = line[:2] == "++"
|
||||
id = self._parseValue(line, "id")
|
||||
|
||||
if self.currentTest:
|
||||
docShells = self.currentTest["docShells"]
|
||||
if created:
|
||||
docShells.add(id)
|
||||
else:
|
||||
docShells.discard(id)
|
||||
elif self.seenShutdown and not created:
|
||||
self.leakedDocShells.add(id)
|
||||
|
||||
def _parseValue(self, line, name):
|
||||
return re.search("\[%s = (.+?)\]" % name, line).group(1)
|
||||
|
||||
def _parseLeakingTests(self):
|
||||
leakingTests = []
|
||||
|
||||
for test in self.tests:
|
||||
test["leakedWindows"] = [self.leakedWindows[id] for id in test["windows"] if id in self.leakedWindows]
|
||||
test["leakedDocShells"] = [id for id in test["docShells"] if id in self.leakedDocShells]
|
||||
test["leakCount"] = len(test["leakedWindows"]) + len(test["leakedDocShells"])
|
||||
|
||||
if test["leakCount"]:
|
||||
leakingTests.append(test)
|
||||
|
||||
return sorted(leakingTests, key=itemgetter("leakCount"), reverse=True)
|
||||
|
||||
def _zipLeakedWindows(self, leakedWindows):
|
||||
counts = []
|
||||
counted = set()
|
||||
|
||||
for url in leakedWindows:
|
||||
if not url in counted:
|
||||
counts.append((url, leakedWindows.count(url)))
|
||||
counted.add(url)
|
||||
|
||||
return sorted(counts, key=itemgetter(1), reverse=True)
|
||||
|
|
|
@ -96,7 +96,7 @@ class RemoteAutomation(Automation):
|
|||
|
||||
return env
|
||||
|
||||
def waitForFinish(self, proc, utilityPath, timeout, maxTime, startTime, debuggerInfo, symbolsDir):
|
||||
def waitForFinish(self, proc, utilityPath, timeout, maxTime, startTime, debuggerInfo, symbolsDir, logger):
|
||||
# maxTime is used to override the default timeout, we should honor that
|
||||
status = proc.wait(timeout = maxTime)
|
||||
|
||||
|
|
|
@ -785,7 +785,8 @@ nsDocShell::nsDocShell():
|
|||
// We're counting the number of |nsDocShells| to help find leaks
|
||||
++gNumberOfDocShells;
|
||||
if (!PR_GetEnv("MOZ_QUIET")) {
|
||||
printf("++DOCSHELL %p == %ld\n", (void*) this, gNumberOfDocShells);
|
||||
printf("++DOCSHELL %p == %ld [id = %ld]\n", (void*) this,
|
||||
gNumberOfDocShells, mHistoryID);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -813,7 +814,8 @@ nsDocShell::~nsDocShell()
|
|||
// We're counting the number of |nsDocShells| to help find leaks
|
||||
--gNumberOfDocShells;
|
||||
if (!PR_GetEnv("MOZ_QUIET")) {
|
||||
printf("--DOCSHELL %p == %ld\n", (void*) this, gNumberOfDocShells);
|
||||
printf("--DOCSHELL %p == %ld [id = %ld]\n", (void*) this,
|
||||
gNumberOfDocShells, mHistoryID);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -675,6 +675,12 @@ class Mochitest(object):
|
|||
else:
|
||||
timeout = 330.0 # default JS harness timeout is 300 seconds
|
||||
|
||||
# it's a debug build, we can parse leaked DOMWindows and docShells
|
||||
if Automation.IS_DEBUG_BUILD:
|
||||
logger = ShutdownLeakLogger(self.automation.log)
|
||||
else:
|
||||
logger = None
|
||||
|
||||
if options.vmwareRecording:
|
||||
self.startVMwareRecording(options);
|
||||
|
||||
|
@ -688,6 +694,7 @@ class Mochitest(object):
|
|||
certPath=options.certPath,
|
||||
debuggerInfo=debuggerInfo,
|
||||
symbolsPath=options.symbolsPath,
|
||||
logger = logger,
|
||||
timeout = timeout)
|
||||
except KeyboardInterrupt:
|
||||
self.automation.log.info("INFO | runtests.py | Received keyboard interrupt.\n");
|
||||
|
@ -702,6 +709,10 @@ class Mochitest(object):
|
|||
self.stopWebServer(options)
|
||||
self.stopWebSocketServer(options)
|
||||
processLeakLog(self.leak_report_file, options.leakThreshold)
|
||||
|
||||
if logger:
|
||||
logger.parse()
|
||||
|
||||
self.automation.log.info("\nINFO | runtests.py | Running tests: end.")
|
||||
|
||||
if manifest is not None:
|
||||
|
|
|
@ -634,10 +634,15 @@
|
|||
}
|
||||
for each (let event in this.videoEvents)
|
||||
this.video.removeEventListener(event, this, false);
|
||||
|
||||
for each(let element in this.controlListeners)
|
||||
element.item.removeEventListener(element.event, element.func, false);
|
||||
|
||||
delete this.controlListeners;
|
||||
|
||||
this.video.removeEventListener("media-showStatistics", this._handleCustomEventsBound, false);
|
||||
delete this._handleCustomEventsBound;
|
||||
this.video.ownerDocument.removeEventListener("mozfullscreenchange", this._setFullscreenButtonStateBound, false);
|
||||
delete this._setFullscreenButtonStateBound;
|
||||
|
||||
this.log("--- videocontrols terminated ---");
|
||||
},
|
||||
|
||||
|
@ -931,6 +936,7 @@
|
|||
togglePause : function () {
|
||||
if (this.video.paused || this.video.ended) {
|
||||
this._triggeredByControls = true;
|
||||
this.hideClickToPlay();
|
||||
this.video.play();
|
||||
} else {
|
||||
this.video.pause();
|
||||
|
@ -975,7 +981,19 @@
|
|||
this.fullscreenButton.removeAttribute("fullscreened");
|
||||
},
|
||||
|
||||
handleClickToPlay : function () {
|
||||
clickToPlayClickHandler : function(e) {
|
||||
if (e.button != 0 || this.hasError())
|
||||
return;
|
||||
// Read defaultPrevented asynchronously, since Web content
|
||||
// may want to consume the "click" event but will only
|
||||
// receive it after us.
|
||||
let self = this;
|
||||
setTimeout(function clickToPlayCallback() {
|
||||
if (!e.defaultPrevented)
|
||||
self.togglePause();
|
||||
}, 0);
|
||||
},
|
||||
hideClickToPlay : function () {
|
||||
let videoHeight = this.video.clientHeight;
|
||||
let videoWidth = this.video.clientWidth;
|
||||
|
||||
|
@ -990,7 +1008,6 @@
|
|||
this.clickToPlay.removeAttribute("immediate");
|
||||
}
|
||||
this.clickToPlay.setAttribute("fadeout", "true");
|
||||
this.togglePause();
|
||||
},
|
||||
|
||||
setPlayButtonState : function(aPaused) {
|
||||
|
@ -1330,47 +1347,36 @@
|
|||
this.video.addEventListener(event, this, (event == "error") ? true : false);
|
||||
|
||||
var self = this;
|
||||
this.muteButton.addEventListener("command", function() { self.toggleMute(); }, false);
|
||||
this.playButton.addEventListener("command", function() { self.togglePause(); }, false);
|
||||
this.fullscreenButton.addEventListener("command", function() { self.toggleFullscreen(); }, false );
|
||||
this.clickToPlay.addEventListener("click", function clickToPlayClickHandler(e) {
|
||||
if (e.button != 0 || self.hasError())
|
||||
return;
|
||||
// Read defaultPrevented asynchronously, since Web content
|
||||
// may want to consume the "click" event but will only
|
||||
// receive it after us.
|
||||
setTimeout(function clickToPlayCallback() {
|
||||
if (!e.defaultPrevented)
|
||||
self.handleClickToPlay();
|
||||
}, 0);
|
||||
}, false);
|
||||
|
||||
this.controlsSpacer.addEventListener("click", function spacerClickHandler(e) {
|
||||
if (e.button != 0 || self.hasError())
|
||||
return;
|
||||
// Read defaultPrevented asynchronously, since Web content
|
||||
// may want to consume the "click" event but will only
|
||||
// receive it after us (bug 693014).
|
||||
setTimeout(function togglePauseCallback() {
|
||||
if (!e.defaultPrevented)
|
||||
self.togglePause();
|
||||
}, 0);
|
||||
}, false);
|
||||
this.controlListeners = [];
|
||||
|
||||
if (!this.isAudioOnly) {
|
||||
this.muteButton.addEventListener("mouseover", function(e) { self.onVolumeMouseInOut(e); }, false);
|
||||
this.muteButton.addEventListener("mouseout", function(e) { self.onVolumeMouseInOut(e); }, false);
|
||||
this.volumeStack.addEventListener("mouseover", function(e) { self.onVolumeMouseInOut(e); }, false);
|
||||
this.volumeStack.addEventListener("mouseout", function(e) { self.onVolumeMouseInOut(e); }, false);
|
||||
// Helper function to add an event listener to the given element
|
||||
function addListener(elem, eventName, func) {
|
||||
let boundFunc = func.bind(self);
|
||||
self.controlListeners.push({ item: elem, event: eventName, func: boundFunc });
|
||||
elem.addEventListener(eventName, boundFunc, false);
|
||||
}
|
||||
|
||||
this.videocontrols.addEventListener("transitionend", function(e) { self.onTransitionEnd(e); }, false);
|
||||
this._setFullscreenButtonStateBound = this.setFullscreenButtonState.bind(this);
|
||||
this.video.ownerDocument.addEventListener("mozfullscreenchange", this._setFullscreenButtonStateBound, false);
|
||||
addListener(this.muteButton, "command", this.toggleMute);
|
||||
addListener(this.playButton, "command", this.togglePause);
|
||||
addListener(this.fullscreenButton, "command", this.toggleFullscreen);
|
||||
addListener(this.clickToPlay, "click", this.clickToPlayClickHandler);
|
||||
addListener(this.controlsSpacer, "click", this.clickToPlayClickHandler);
|
||||
|
||||
if (!this.isAudioOnly) {
|
||||
addListener(this.muteButton, "mouseover", this.onVolumeMouseInOut);
|
||||
addListener(this.muteButton, "mouseout", this.onVolumeMouseInOut);
|
||||
addListener(this.volumeStack, "mouseover", this.onVolumeMouseInOut);
|
||||
addListener(this.volumeStack, "mouseout", this.onVolumeMouseInOut);
|
||||
}
|
||||
|
||||
addListener(this.videocontrols, "transitionend", this.onTransitionEnd);
|
||||
addListener(this.video.ownerDocument, "mozfullscreenchange", this.setFullscreenButtonState);
|
||||
|
||||
// Make the <video> element keyboard accessible.
|
||||
this.video.setAttribute("tabindex", 0);
|
||||
this.video.addEventListener("keypress", function (e) { self.keyHandler(e) }, false);
|
||||
|
||||
addListener(this.video, "keypress", this.keyHandler);
|
||||
|
||||
this.log("--- videocontrols initialized ---");
|
||||
}
|
||||
|
|
|
@ -67,6 +67,7 @@ function BrowserRootActor(aConnection)
|
|||
this._actorFactories = null;
|
||||
|
||||
this.onTabClosed = this.onTabClosed.bind(this);
|
||||
this._onWindowCreated = this.onWindowCreated.bind(this);
|
||||
windowMediator.addListener(this);
|
||||
}
|
||||
|
||||
|
@ -75,6 +76,10 @@ BrowserRootActor.prototype = {
|
|||
* Return a 'hello' packet as specified by the Remote Debugging Protocol.
|
||||
*/
|
||||
sayHello: function BRA_sayHello() {
|
||||
// Create the tab actor for the selected tab right away so that it gets a
|
||||
// chance to listen to onNewScript notifications.
|
||||
this._preInitTabActor();
|
||||
|
||||
return { from: "root",
|
||||
applicationType: "browser",
|
||||
traits: [] };
|
||||
|
@ -114,10 +119,6 @@ BrowserRootActor.prototype = {
|
|||
while (e.hasMoreElements()) {
|
||||
let win = e.getNext();
|
||||
|
||||
// Watch the window for tab closes so we can invalidate
|
||||
// actors as needed.
|
||||
this.watchWindow(win);
|
||||
|
||||
// List the tabs in this browser.
|
||||
let selectedBrowser = win.getBrowser().selectedBrowser;
|
||||
let browsers = win.getBrowser().browsers;
|
||||
|
@ -178,16 +179,61 @@ BrowserRootActor.prototype = {
|
|||
this.exitTabActor(aEvent.target.linkedBrowser);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle location changes, by preinitializing a tab actor.
|
||||
*/
|
||||
onWindowCreated: function BRA_onWindowCreated(evt) {
|
||||
if (evt.target === this.browser.contentDocument) {
|
||||
this._preInitTabActor();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Exit the tab actor of the specified tab.
|
||||
*/
|
||||
exitTabActor: function BRA_exitTabActor(aWindow) {
|
||||
this.browser.removeEventListener("DOMWindowCreated", this._onWindowCreated, true);
|
||||
let actor = this._tabActors.get(aWindow);
|
||||
if (actor) {
|
||||
actor.exit();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Create the tab actor in the selected tab right away so that it gets a
|
||||
* chance to listen to onNewScript notifications.
|
||||
*/
|
||||
_preInitTabActor: function BRA__preInitTabActor() {
|
||||
let actorPool = new ActorPool(this.conn);
|
||||
|
||||
// Walk over open browser windows.
|
||||
let e = windowMediator.getEnumerator("navigator:browser");
|
||||
while (e.hasMoreElements()) {
|
||||
let win = e.getNext();
|
||||
|
||||
// Watch the window for tab closes so we can invalidate
|
||||
// actors as needed.
|
||||
this.watchWindow(win);
|
||||
|
||||
this.browser = win.getBrowser().selectedBrowser;
|
||||
let actor = this._tabActors.get(this.browser);
|
||||
if (actor) {
|
||||
actor._detach();
|
||||
}
|
||||
actor = new BrowserTabActor(this.conn, this.browser);
|
||||
actor.parentID = this.actorID;
|
||||
this._tabActors.set(this.browser, actor);
|
||||
|
||||
actorPool.addActor(actor);
|
||||
}
|
||||
|
||||
this._tabActorPool = actorPool;
|
||||
this.conn.addActorPool(this._tabActorPool);
|
||||
|
||||
// Watch for globals being created in this tab.
|
||||
this.browser.addEventListener("DOMWindowCreated", this._onWindowCreated, true);
|
||||
},
|
||||
|
||||
// nsIWindowMediatorListener
|
||||
onWindowTitleChange: function BRA_onWindowTitleChange(aWindow, aTitle) { },
|
||||
onOpenWindow: function BRA_onOpenWindow(aWindow) { },
|
||||
|
@ -195,7 +241,7 @@ BrowserRootActor.prototype = {
|
|||
if (aWindow.getBrowser) {
|
||||
this.unwatchWindow(aWindow);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -220,6 +266,7 @@ function BrowserTabActor(aConnection, aBrowser)
|
|||
this._browser = aBrowser;
|
||||
|
||||
this._onWindowCreated = this.onWindowCreated.bind(this);
|
||||
this._attach();
|
||||
}
|
||||
|
||||
// XXX (bug 710213): BrowserTabActor attach/detach/exit/disconnect is a
|
||||
|
@ -290,7 +337,7 @@ BrowserTabActor.prototype = {
|
|||
this._pushContext();
|
||||
|
||||
// Watch for globals being created in this tab.
|
||||
this.browser.addEventListener("DOMWindowCreated", this._onWindowCreated, true);
|
||||
this.browser.addEventListener("DOMWindowCreated", this._onWindowCreated, false);
|
||||
|
||||
this._attached = true;
|
||||
},
|
||||
|
@ -331,7 +378,7 @@ BrowserTabActor.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
this.browser.removeEventListener("DOMWindowCreated", this._onWindowCreated, true);
|
||||
this.browser.removeEventListener("DOMWindowCreated", this._onWindowCreated, false);
|
||||
|
||||
this._popContext();
|
||||
|
||||
|
@ -397,8 +444,7 @@ BrowserTabActor.prototype = {
|
|||
url: this.browser.contentDocument.URL });
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -99,12 +99,19 @@ ThreadActor.prototype = {
|
|||
this._dbg = new Debugger();
|
||||
}
|
||||
|
||||
// TODO: Remove this horrible hack when bug 723563 is fixed.
|
||||
// Make sure that a chrome window is not added as a debuggee when opening
|
||||
// the debugger in an empty tab or during tests.
|
||||
if (aGlobal.location &&
|
||||
(aGlobal.location.protocol == "about:" ||
|
||||
aGlobal.location.protocol == "chrome:")) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.dbg.addDebuggee(aGlobal);
|
||||
this.dbg.uncaughtExceptionHook = this.uncaughtExceptionHook.bind(this);
|
||||
this.dbg.onDebuggerStatement = this.onDebuggerStatement.bind(this);
|
||||
this.dbg.onNewScript = this.onNewScript.bind(this);
|
||||
// Keep the debugger disabled until a client attaches.
|
||||
this.dbg.enabled = false;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -146,6 +146,7 @@ add_test(function() {
|
|||
}, false);
|
||||
|
||||
info("Opening context menu on enabled extension item");
|
||||
el.parentNode.ensureElementIsVisible(el);
|
||||
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
|
||||
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
|
||||
});
|
||||
|
@ -165,6 +166,7 @@ add_test(function() {
|
|||
}, false);
|
||||
|
||||
info("Opening context menu on newly disabled extension item");
|
||||
el.parentNode.ensureElementIsVisible(el);
|
||||
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
|
||||
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
|
||||
});
|
||||
|
@ -184,6 +186,7 @@ add_test(function() {
|
|||
}, false);
|
||||
|
||||
info("Opening context menu on newly enabled extension item");
|
||||
el.parentNode.ensureElementIsVisible(el);
|
||||
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
|
||||
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
|
||||
});
|
||||
|
@ -201,6 +204,7 @@ add_test(function() {
|
|||
}, false);
|
||||
|
||||
info("Opening context menu on disabled extension item");
|
||||
el.parentNode.ensureElementIsVisible(el);
|
||||
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
|
||||
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
|
||||
});
|
||||
|
@ -214,13 +218,14 @@ add_test(function() {
|
|||
gContextMenu.addEventListener("popupshown", function() {
|
||||
gContextMenu.removeEventListener("popupshown", arguments.callee, false);
|
||||
|
||||
check_contextmenu(true, true, false, false, false);
|
||||
check_contextmenu(true, true, false, false, false);
|
||||
|
||||
gContextMenu.hidePopup();
|
||||
run_next_test();
|
||||
}, false);
|
||||
|
||||
info("Opening context menu on enabled theme item");
|
||||
el.parentNode.ensureElementIsVisible(el);
|
||||
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
|
||||
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
|
||||
});
|
||||
|
@ -240,6 +245,7 @@ add_test(function() {
|
|||
}, false);
|
||||
|
||||
info("Opening context menu on disabled theme item");
|
||||
el.parentNode.ensureElementIsVisible(el);
|
||||
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
|
||||
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
|
||||
});
|
||||
|
@ -260,6 +266,7 @@ add_test(function() {
|
|||
}, false);
|
||||
|
||||
info("Opening context menu on enabled LW theme item");
|
||||
el.parentNode.ensureElementIsVisible(el);
|
||||
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
|
||||
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
|
||||
});
|
||||
|
@ -280,6 +287,7 @@ add_test(function() {
|
|||
}, false);
|
||||
|
||||
info("Opening context menu on disabled LW theme item");
|
||||
el.parentNode.ensureElementIsVisible(el);
|
||||
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
|
||||
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
|
||||
});
|
||||
|
@ -467,6 +475,7 @@ add_test(function() {
|
|||
}, false);
|
||||
|
||||
info("Opening context menu on remote extension item");
|
||||
el.parentNode.ensureElementIsVisible(el);
|
||||
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
|
||||
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
|
||||
|
||||
|
|
|
@ -13,6 +13,12 @@ function test() {
|
|||
|
||||
function check_load(aCallback) {
|
||||
gBrowser.addEventListener("load", function(aEvent) {
|
||||
// SeaMonkey needs to deal with intermediate "about:blank" document(s).
|
||||
if (!aEvent.target.location) {
|
||||
info("Ignoring about:blank load. (Expected (a few times) on SeaMonkey only.)");
|
||||
return;
|
||||
}
|
||||
|
||||
gBrowser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
// Let the load handler complete
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
/* margin left/right: make bar 8px wide (control width = 28, minus 2 * 10 margin) */
|
||||
margin: 0 10px;
|
||||
background-color: rgba(255,255,255,.5);
|
||||
border-radius: 4px 4px;
|
||||
border-radius: 2.5px;
|
||||
}
|
||||
|
||||
.durationBox {
|
||||
|
@ -102,7 +102,7 @@
|
|||
/* margin left/right: 1/2 of scrubber thumb width, for overhang. */
|
||||
margin: 10px 22px;
|
||||
background-color: rgba(255,255,255,.5);
|
||||
border-radius: 4px;
|
||||
border-radius: 2.5px;
|
||||
}
|
||||
|
||||
.bufferBar,
|
||||
|
@ -122,12 +122,12 @@
|
|||
* compositing gives it a different visual appearance.
|
||||
*/
|
||||
background-color: rgba(255,255,255,.5);
|
||||
border-radius: 4px;
|
||||
border-radius: 2.5px;
|
||||
}
|
||||
|
||||
.progressBar .progress-bar {
|
||||
background-color: white;
|
||||
border-radius: 4px 0 0 4px;
|
||||
border-radius: 2.5px;
|
||||
}
|
||||
|
||||
/* .scale-slider is an element inside the <scale> implementation. */
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
/* margin left/right: make bar 8px wide (control width = 28, minus 2 * 10 margin) */
|
||||
margin: 0 10px;
|
||||
background-color: rgba(255,255,255,.5);
|
||||
border-radius: 4px 4px;
|
||||
border-radius: 2.5px;
|
||||
}
|
||||
|
||||
.durationBox {
|
||||
|
@ -104,7 +104,7 @@
|
|||
/* margin left/right: 1/2 of scrubber thumb width, for overhang. */
|
||||
margin: 10px 22px;
|
||||
background-color: rgba(255,255,255,.5);
|
||||
border-radius: 4px;
|
||||
border-radius: 2.5px;
|
||||
}
|
||||
|
||||
.bufferBar,
|
||||
|
@ -127,13 +127,13 @@
|
|||
* compositing gives it a different visual appearance.
|
||||
*/
|
||||
background-color: rgba(255,255,255,.5);
|
||||
border-radius: 4px;
|
||||
border-radius: 2.5px;
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
.progressBar .progress-bar {
|
||||
background-color: white;
|
||||
border-radius: 4px 0 0 4px;
|
||||
border-radius: 2.5px;
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
|
|
|
@ -972,8 +972,8 @@ nsWindow::OnGlobalAndroidEvent(AndroidGeckoEvent *ae)
|
|||
if (points.Length() > 0) {
|
||||
pt = points[0];
|
||||
}
|
||||
pt.x = clamped(pt.x, 0, gAndroidBounds.width - 1);
|
||||
pt.y = clamped(pt.y, 0, gAndroidBounds.height - 1);
|
||||
pt.x = clamped(pt.x, 0, PR_MAX(gAndroidBounds.width - 1, 0));
|
||||
pt.y = clamped(pt.y, 0, PR_MAX(gAndroidBounds.height - 1, 0));
|
||||
nsWindow *target = win->FindWindowForPoint(pt);
|
||||
#if 0
|
||||
ALOG("MOTION_EVENT %f,%f -> %p (visible: %d children: %d)", pt.x, pt.y, (void*)target,
|
||||
|
|
Загрузка…
Ссылка в новой задаче