Bug 1258987 - Stop generating useless xul:command and xul:broadcaster. r=jryans
This commit is contained in:
@@ -16,6 +16,7 @@ const Services = require("Services");
|
||||
const MenuStrings = Services.strings.createBundle("chrome://devtools/locale/menus.properties");
|
||||
|
||||
loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools", true);
|
||||
loader.lazyRequireGetter(this, "gDevToolsBrowser", "devtools/client/framework/devtools-browser", true);
|
||||
|
||||
// Keep list of inserted DOM Elements in order to remove them on unload
|
||||
// Maps browser xul document => list of DOM Elements
|
||||
@@ -30,40 +31,41 @@ function l10n(key) {
|
||||
*
|
||||
* @param {XULDocument} doc
|
||||
* The document to which keys are to be added.
|
||||
* @param {String} l10nKey
|
||||
* Prefix of the properties entry to look for key shortcut in
|
||||
* localization file. We will look for {property}.key and
|
||||
* {property}.keytext for non-character shortcuts like F12.
|
||||
* @param {String} command
|
||||
* Id of the xul:command to map to.
|
||||
* @param {Object} key definition dictionnary
|
||||
* Definition with following attributes:
|
||||
* - {String} id
|
||||
* xul:key's id, automatically prefixed with "key_",
|
||||
* - {String} modifiers
|
||||
* Space separater list of modifier names,
|
||||
* - {Boolean} keytext
|
||||
* If true, consider the shortcut as a characther one,
|
||||
* otherwise a non-character one like F12.
|
||||
* @param {String} id
|
||||
* key's id, automatically prefixed with "key_".
|
||||
* @param {String} shortcut
|
||||
* The key shortcut value.
|
||||
* @param {String} keytext
|
||||
* If `shortcut` refers to a function key, refers to the localized
|
||||
* string to describe a non-character shortcut.
|
||||
* @param {String} modifiers
|
||||
* Space separated list of modifier names.
|
||||
* @param {Function} oncommand
|
||||
* The function to call when the shortcut is pressed.
|
||||
*
|
||||
* @return XULKeyElement
|
||||
*/
|
||||
function createKey(doc, l10nKey, command, key) {
|
||||
function createKey({ doc, id, shortcut, keytext, modifiers, oncommand }) {
|
||||
let k = doc.createElement("key");
|
||||
k.id = "key_" + key.id;
|
||||
let shortcut = l10n(l10nKey + ".key");
|
||||
k.id = "key_" + id;
|
||||
|
||||
if (shortcut.startsWith("VK_")) {
|
||||
k.setAttribute("keycode", shortcut);
|
||||
k.setAttribute("keytext", l10n(l10nKey + ".keytext"));
|
||||
if (keytext) {
|
||||
k.setAttribute("keytext", keytext);
|
||||
}
|
||||
} else {
|
||||
k.setAttribute("key", shortcut);
|
||||
}
|
||||
if (command) {
|
||||
k.setAttribute("command", command);
|
||||
}
|
||||
if (key.modifiers) {
|
||||
k.setAttribute("modifiers", key.modifiers);
|
||||
|
||||
if (modifiers) {
|
||||
k.setAttribute("modifiers", modifiers);
|
||||
}
|
||||
|
||||
// Bug 371900: command event is fired only if "oncommand" attribute is set.
|
||||
k.setAttribute("oncommand", ";");
|
||||
k.addEventListener("command", oncommand);
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
@@ -76,25 +78,18 @@ function createKey(doc, l10nKey, command, key) {
|
||||
* Element id.
|
||||
* @param {String} label
|
||||
* Menu label.
|
||||
* @param {String} broadcasterId (optional)
|
||||
* Id of the xul:broadcaster to map to.
|
||||
* @param {String} accesskey (optional)
|
||||
* Access key of the menuitem, used as shortcut while opening the menu.
|
||||
* @param {Boolean} isCheckbox
|
||||
* @param {Boolean} isCheckbox (optional)
|
||||
* If true, the menuitem will act as a checkbox and have an optional
|
||||
* tick on its left.
|
||||
*
|
||||
* @return XULMenuItemElement
|
||||
*/
|
||||
function createMenuItem({ doc, id, label, broadcasterId, accesskey, isCheckbox }) {
|
||||
function createMenuItem({ doc, id, label, accesskey, isCheckbox }) {
|
||||
let menuitem = doc.createElement("menuitem");
|
||||
menuitem.id = id;
|
||||
if (label) {
|
||||
menuitem.setAttribute("label", label);
|
||||
}
|
||||
if (broadcasterId) {
|
||||
menuitem.setAttribute("observes", broadcasterId);
|
||||
}
|
||||
menuitem.setAttribute("label", label);
|
||||
if (accesskey) {
|
||||
menuitem.setAttribute("accesskey", accesskey);
|
||||
}
|
||||
@@ -105,56 +100,6 @@ function createMenuItem({ doc, id, label, broadcasterId, accesskey, isCheckbox }
|
||||
return menuitem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a xul:broadcaster element
|
||||
*
|
||||
* @param {XULDocument} doc
|
||||
* The document to which keys are to be added.
|
||||
* @param {String} id
|
||||
* Element id.
|
||||
* @param {String} label
|
||||
* Broadcaster label.
|
||||
* @param {Boolean} isCheckbox
|
||||
* If true, the broadcaster is a checkbox one.
|
||||
*
|
||||
* @return XULMenuItemElement
|
||||
*/
|
||||
function createBroadcaster({ doc, id, label, isCheckbox }) {
|
||||
let broadcaster = doc.createElement("broadcaster");
|
||||
broadcaster.id = id;
|
||||
broadcaster.setAttribute("label", label);
|
||||
if (isCheckbox) {
|
||||
broadcaster.setAttribute("type", "checkbox");
|
||||
broadcaster.setAttribute("autocheck", "false");
|
||||
}
|
||||
return broadcaster;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a xul:command element
|
||||
*
|
||||
* @param {XULDocument} doc
|
||||
* The document to which keys are to be added.
|
||||
* @param {String} id
|
||||
* Element id.
|
||||
* @param {String} oncommand
|
||||
* JS String to run when the command is fired.
|
||||
* @param {Boolean} disabled
|
||||
* If true, the command is disabled and hidden.
|
||||
*
|
||||
* @return XULCommandElement
|
||||
*/
|
||||
function createCommand({ doc, id, oncommand, disabled }) {
|
||||
let command = doc.createElement("command");
|
||||
command.id = id;
|
||||
command.setAttribute("oncommand", oncommand);
|
||||
if (disabled) {
|
||||
command.setAttribute("disabled", "true");
|
||||
command.setAttribute("hidden", "true");
|
||||
}
|
||||
return command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a <key> to <keyset id="devtoolsKeyset">.
|
||||
* Appending a <key> element is not always enough. The <keyset> needs
|
||||
@@ -188,61 +133,49 @@ function attachKeybindingsToBrowser(doc, keys) {
|
||||
*/
|
||||
function createToolMenuElements(toolDefinition, doc) {
|
||||
let id = toolDefinition.id;
|
||||
let menuId = "menuitem_" + id;
|
||||
|
||||
// Prevent multiple entries for the same tool.
|
||||
if (doc.getElementById("Tools:" + id)) {
|
||||
if (doc.getElementById(menuId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let cmd = createCommand({
|
||||
doc,
|
||||
id: "Tools:" + id,
|
||||
oncommand: 'gDevToolsBrowser.selectToolCommand(gBrowser, "' + id + '");',
|
||||
});
|
||||
let oncommand = function (id, event) {
|
||||
let window = event.target.ownerDocument.defaultView;
|
||||
gDevToolsBrowser.selectToolCommand(window.gBrowser, id);
|
||||
}.bind(null, id);
|
||||
|
||||
let key = null;
|
||||
if (toolDefinition.key) {
|
||||
key = doc.createElement("key");
|
||||
key.id = "key_" + id;
|
||||
|
||||
if (toolDefinition.key.startsWith("VK_")) {
|
||||
key.setAttribute("keycode", toolDefinition.key);
|
||||
} else {
|
||||
key.setAttribute("key", toolDefinition.key);
|
||||
}
|
||||
|
||||
key.setAttribute("command", cmd.id);
|
||||
key.setAttribute("modifiers", toolDefinition.modifiers);
|
||||
}
|
||||
|
||||
let bc = createBroadcaster({
|
||||
doc,
|
||||
id: "devtoolsMenuBroadcaster_" + id,
|
||||
label: toolDefinition.menuLabel || toolDefinition.label
|
||||
});
|
||||
bc.setAttribute("command", cmd.id);
|
||||
|
||||
if (key) {
|
||||
bc.setAttribute("key", "key_" + id);
|
||||
key = createKey({
|
||||
doc,
|
||||
id,
|
||||
shortcut: toolDefinition.key,
|
||||
modifiers: toolDefinition.modifiers,
|
||||
oncommand: oncommand
|
||||
});
|
||||
}
|
||||
|
||||
let menuitem = createMenuItem({
|
||||
doc,
|
||||
id: "menuitem_" + id,
|
||||
broadcasterId: "devtoolsMenuBroadcaster_" + id,
|
||||
label: toolDefinition.menuLabel || toolDefinition.label,
|
||||
accesskey: toolDefinition.accesskey
|
||||
});
|
||||
if (key) {
|
||||
// Refer to the key in order to display the key shortcut at menu ends
|
||||
menuitem.setAttribute("key", key.id);
|
||||
}
|
||||
menuitem.addEventListener("command", oncommand);
|
||||
|
||||
return {
|
||||
cmd: cmd,
|
||||
key: key,
|
||||
bc: bc,
|
||||
menuitem: menuitem
|
||||
key,
|
||||
menuitem
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create xul menuitem, command, broadcaster and key elements for a given tool.
|
||||
* Create xul menuitem, key elements for a given tool.
|
||||
* And then insert them into browser DOM.
|
||||
*
|
||||
* @param {XULDocument} doc
|
||||
@@ -253,16 +186,12 @@ function createToolMenuElements(toolDefinition, doc) {
|
||||
* The tool definition after which the tool menu item is to be added.
|
||||
*/
|
||||
function insertToolMenuElements(doc, toolDefinition, prevDef) {
|
||||
let elements = createToolMenuElements(toolDefinition, doc);
|
||||
let { key, menuitem } = createToolMenuElements(toolDefinition, doc);
|
||||
|
||||
doc.getElementById("mainCommandSet").appendChild(elements.cmd);
|
||||
|
||||
if (elements.key) {
|
||||
attachKeybindingsToBrowser(doc, elements.key);
|
||||
if (key) {
|
||||
attachKeybindingsToBrowser(doc, key);
|
||||
}
|
||||
|
||||
doc.getElementById("mainBroadcasterSet").appendChild(elements.bc);
|
||||
|
||||
let ref;
|
||||
if (prevDef) {
|
||||
let menuitem = doc.getElementById("menuitem_" + prevDef.id);
|
||||
@@ -272,7 +201,7 @@ function insertToolMenuElements(doc, toolDefinition, prevDef) {
|
||||
}
|
||||
|
||||
if (ref) {
|
||||
ref.parentNode.insertBefore(elements.menuitem, ref);
|
||||
ref.parentNode.insertBefore(menuitem, ref);
|
||||
}
|
||||
}
|
||||
exports.insertToolMenuElements = insertToolMenuElements;
|
||||
@@ -286,24 +215,14 @@ exports.insertToolMenuElements = insertToolMenuElements;
|
||||
* The document to which the tool menu item is to be removed from
|
||||
*/
|
||||
function removeToolFromMenu(toolId, doc) {
|
||||
let command = doc.getElementById("Tools:" + toolId);
|
||||
if (command) {
|
||||
command.parentNode.removeChild(command);
|
||||
}
|
||||
|
||||
let key = doc.getElementById("key_" + toolId);
|
||||
if (key) {
|
||||
key.parentNode.removeChild(key);
|
||||
}
|
||||
|
||||
let bc = doc.getElementById("devtoolsMenuBroadcaster_" + toolId);
|
||||
if (bc) {
|
||||
bc.parentNode.removeChild(bc);
|
||||
key.remove();
|
||||
}
|
||||
|
||||
let menuitem = doc.getElementById("menuitem_" + toolId);
|
||||
if (menuitem) {
|
||||
menuitem.parentNode.removeChild(menuitem);
|
||||
menuitem.remove();
|
||||
}
|
||||
}
|
||||
exports.removeToolFromMenu = removeToolFromMenu;
|
||||
@@ -315,9 +234,7 @@ exports.removeToolFromMenu = removeToolFromMenu;
|
||||
* The document to which the tool items are to be added.
|
||||
*/
|
||||
function addAllToolsToMenu(doc) {
|
||||
let fragCommands = doc.createDocumentFragment();
|
||||
let fragKeys = doc.createDocumentFragment();
|
||||
let fragBroadcasters = doc.createDocumentFragment();
|
||||
let fragMenuItems = doc.createDocumentFragment();
|
||||
|
||||
for (let toolDefinition of gDevTools.getToolDefinitionArray()) {
|
||||
@@ -331,22 +248,14 @@ function addAllToolsToMenu(doc) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fragCommands.appendChild(elements.cmd);
|
||||
if (elements.key) {
|
||||
fragKeys.appendChild(elements.key);
|
||||
}
|
||||
fragBroadcasters.appendChild(elements.bc);
|
||||
fragMenuItems.appendChild(elements.menuitem);
|
||||
}
|
||||
|
||||
let mcs = doc.getElementById("mainCommandSet");
|
||||
mcs.appendChild(fragCommands);
|
||||
|
||||
attachKeybindingsToBrowser(doc, fragKeys);
|
||||
|
||||
let mbs = doc.getElementById("mainBroadcasterSet");
|
||||
mbs.appendChild(fragBroadcasters);
|
||||
|
||||
let mps = doc.getElementById("menu_devtools_separator");
|
||||
if (mps) {
|
||||
mps.parentNode.insertBefore(fragMenuItems, mps);
|
||||
@@ -385,10 +294,15 @@ function addTopLevelItems(doc) {
|
||||
|
||||
if (item.key && l10nKey) {
|
||||
// Create a <key>
|
||||
let key = createKey(doc, l10nKey, null, item.key);
|
||||
// Bug 371900: command event is fired only if "oncommand" attribute is set.
|
||||
key.setAttribute("oncommand", ";");
|
||||
key.addEventListener("command", item.oncommand);
|
||||
let shortcut = l10n(l10nKey + ".key");
|
||||
let key = createKey({
|
||||
doc,
|
||||
id: item.key.id,
|
||||
shortcut: shortcut,
|
||||
keytext: shortcut.startsWith("VK_") ? l10n(l10nKey + ".keytext") : null,
|
||||
modifiers: item.key.modifiers,
|
||||
oncommand: item.oncommand
|
||||
});
|
||||
// Refer to the key in order to display the key shortcut at menu ends
|
||||
menuitem.setAttribute("key", key.id);
|
||||
keys.appendChild(key);
|
||||
@@ -396,10 +310,15 @@ function addTopLevelItems(doc) {
|
||||
if (item.additionalKeys) {
|
||||
// Create additional <key>
|
||||
for (let key of item.additionalKeys) {
|
||||
let node = createKey(doc, key.l10nKey, null, key);
|
||||
// Bug 371900: command event is fired only if "oncommand" attribute is set.
|
||||
node.setAttribute("oncommand", ";");
|
||||
node.addEventListener("command", item.oncommand);
|
||||
let shortcut = l10n(key.l10nKey + ".key");
|
||||
let node = createKey({
|
||||
doc,
|
||||
id: key.id,
|
||||
shortcut: shortcut,
|
||||
keytext: shortcut.startsWith("VK_") ? l10n(key.l10nKey + ".keytext") : null,
|
||||
modifiers: key.modifiers,
|
||||
oncommand: item.oncommand
|
||||
});
|
||||
keys.appendChild(node);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user