зеркало из https://github.com/mozilla/pjs.git
bug 441794: properly convert dom key events into keyspecs and thence to readable strings
This commit is contained in:
Родитель
034e502cac
Коммит
6b5253da97
|
@ -58,14 +58,16 @@
|
|||
<stringbundle id="bundle_browser" src="chrome://browser/locale/browser.properties"/>
|
||||
<stringbundle id="bundle-keys" src="chrome://global/locale/keys.properties"/>
|
||||
<stringbundle id="bundle-platformKeys" src="chrome://global-platform/locale/platformKeys.properties"/>
|
||||
<stringbundle id="bundle-shortcuts" src="chrome://browser/locale/shortcuts.properties"/>
|
||||
</stringbundleset>
|
||||
<stringbundleset id="shortcut-bundles">
|
||||
<stringbundle src="chrome://browser/locale/shortcuts.properties"/>
|
||||
</stringbundleset>
|
||||
|
||||
<script type="application/x-javascript" src="chrome://global/content/inlineSpellCheckUI.js"/>
|
||||
<script type="application/x-javascript" src="chrome://browser/content/commandUtil.js"/>
|
||||
<script type="application/x-javascript" src="chrome://browser/content/browser.js"/>
|
||||
<script type="application/x-javascript" src="chrome://browser/content/browser-ui.js"/>
|
||||
<script type="application/x-javascript" src="chrome://browser/content/shortcuts.js"/>
|
||||
<script type="application/x-javascript;version=1.8" src="chrome://browser/content/shortcuts.js"/>
|
||||
|
||||
<commandset id="cmdset_main">
|
||||
<!-- basic navigation -->
|
||||
|
@ -115,7 +117,7 @@
|
|||
|
||||
<!-- misc -->
|
||||
<key id="key_fullscreen" keycode="VK_F6" command="cmd_fullscreen"/>
|
||||
<key id="key_addons" key="E" command="cmd_addons" modifiers="control"/>
|
||||
<key id="key_addons" key="E" command="cmd_addons" modifiers="accel"/>
|
||||
<key id="key_downloads" key="J" command="cmd_downloads" modifiers="control"/>
|
||||
</keyset>
|
||||
|
||||
|
@ -242,6 +244,7 @@
|
|||
<treechildren id="shortcuts-children"/>
|
||||
</tree>
|
||||
<hbox pack="end">
|
||||
<textbox id="test"/>
|
||||
<button label="Dismiss" oncommand="Shortcuts.dismiss();"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
// TODO: read the prefs when the window is opened, and make the required changes
|
||||
// TODO: see about grouping the keys into categories
|
||||
|
||||
//Components.utils.import("resource://gre/modules/json.jsm");
|
||||
Components.utils.import("resource://gre/modules/JSON.jsm");
|
||||
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
|
||||
|
@ -125,19 +125,132 @@ function ShortcutEditor()
|
|||
|
||||
function makeKeySpec(modifiers, key, keycode)
|
||||
{
|
||||
// TODO: make this check more specific, once key elements implement a unique interface
|
||||
if (modifiers instanceof Components.interfaces.nsIDOMElement)
|
||||
return {
|
||||
modifiers: modifiers.getAttribute("modifiers"),
|
||||
modifiers: getFlagsForModifiers(modifiers.getAttribute("modifiers")),
|
||||
key: modifiers.getAttribute("key"),
|
||||
keycode: modifiers.getAttribute("keycode")
|
||||
};
|
||||
if (modifiers instanceof Components.interfaces.nsIDOMKeyEvent)
|
||||
return {
|
||||
modifiers: getEventModifiers(modifiers),
|
||||
key: getEventKey(modifiers),
|
||||
keycode: getEventKeyCode(modifiers)
|
||||
};
|
||||
return {
|
||||
modifiers: modifiers,
|
||||
modifiers: getFlagsForModifiers(modifiers),
|
||||
key: key,
|
||||
keycode: keycode
|
||||
};
|
||||
}
|
||||
|
||||
var modifierFlags = { alt: 1, control: 2, meta: 4, shift: 8 };
|
||||
function getFlagsForModifiers(modifiers)
|
||||
{
|
||||
if (!modifiers)
|
||||
return 0;
|
||||
|
||||
var result;
|
||||
for each (m in modifiers.split(" "))
|
||||
result |= modifierFlags[m];
|
||||
return result;
|
||||
}
|
||||
|
||||
function getEventModifiers(event)
|
||||
{
|
||||
var result, i = 1;
|
||||
for each (m in [event.altKey, event.ctrlKey, event.metaKey, event.shiftKey])
|
||||
{
|
||||
result |= (m && i);
|
||||
i += i;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function getEventKey(event)
|
||||
{
|
||||
if (event.charCode)
|
||||
return String.fromCharCode(event.charCode);
|
||||
}
|
||||
|
||||
function getEventKeyCode(event)
|
||||
{
|
||||
var keyCodeMap = { };
|
||||
var nsIDOMKeyEvent = Components.interfaces.nsIDOMKeyEvent;
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_CANCEL] = "VK_CANCEL";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_HELP] = "VK_HELP";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_BACK_SPACE] = "VK_BACK_SPACE";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_TAB] = "VK_TAB";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_CLEAR] = "VK_CLEAR";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_RETURN] = "VK_RETURN";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_ENTER] = "VK_ENTER";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_SHIFT] = "VK_SHIFT";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_CONTROL] = "VK_CONTROL";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_ALT] = "VK_ALT";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_PAUSE] = "VK_PAUSE";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_CAPS_LOCK] = "VK_CAPS_LOCK";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_ESCAPE] = "VK_ESCAPE";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_SPACE] = "VK_SPACE";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_PAGE_UP] = "VK_PAGE_UP";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_PAGE_DOWN] = "VK_PAGE_DOWN";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_END] = "VK_END";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_HOME] = "VK_HOME";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_LEFT] = "VK_LEFT";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_UP] = "VK_UP";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_RIGHT] = "VK_RIGHT";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_DOWN] = "VK_DOWN";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_PRINTSCREEN] = "VK_PRINTSCREEN";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_INSERT] = "VK_INSERT";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_DELETE] = "VK_DELETE";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_SEMICOLON] = "VK_SEMICOLON";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_EQUALS] = "VK_EQUALS";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_CONTEXT_MENU] = "VK_CONTEXT_MENU";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_MULTIPLY] = "VK_MULTIPLY";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_ADD] = "VK_ADD";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_SEPARATOR] = "VK_SEPARATOR";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_SUBTRACT] = "VK_SUBTRACT";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_DECIMAL] = "VK_DECIMAL";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_DIVIDE] = "VK_DIVIDE";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_F1] = "VK_F1";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_F2] = "VK_F2";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_F3] = "VK_F3";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_F4] = "VK_F4";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_F5] = "VK_F5";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_F6] = "VK_F6";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_F7] = "VK_F7";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_F8] = "VK_F8";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_F9] = "VK_F9";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_F10] = "VK_F10";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_F11] = "VK_F11";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_F12] = "VK_F12";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_F13] = "VK_F13";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_F14] = "VK_F14";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_F15] = "VK_F15";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_F16] = "VK_F16";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_F17] = "VK_F17";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_F18] = "VK_F18";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_F19] = "VK_F19";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_F20] = "VK_F20";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_F21] = "VK_F21";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_F22] = "VK_F22";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_F23] = "VK_F23";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_F24] = "VK_F24";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_NUM_LOCK] = "VK_NUM_LOCK";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_SCROLL_LOCK] = "VK_SCROLL_LOCK";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_COMMA] = "VK_COMMA";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_PERIOD] = "VK_PERIOD";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_SLASH] = "VK_SLASH";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_BACK_QUOTE] = "VK_BACK_QUOTE";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_OPEN_BRACKET] = "VK_OPEN_BRACKET";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_BACK_SLASH] = "VK_BACK_SLASH";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_CLOSE_BRACKET] = "VK_CLOSE_BRACKET";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_QUOTE] = "VK_QUOTE";
|
||||
keyCodeMap[nsIDOMKeyEvent.DOM_VK_META] = "VK_META";
|
||||
|
||||
return keyCodeMap[event.keyCode];
|
||||
}
|
||||
|
||||
// This code is all about converting key elements into human-readable
|
||||
// descriptions of the keys they match. Copied essentially verbatim from
|
||||
// nsMenuFrame::BuildAcceleratorText
|
||||
|
@ -170,25 +283,43 @@ function ShortcutEditor()
|
|||
platformAccel[Components.interfaces.nsIDOMKeyEvent.DOM_VK_CONTROL] = platformKeys.control;
|
||||
platformKeys.accel = platformAccel[accelKey] || platformKeys.control;
|
||||
|
||||
function getKeyName(key) {
|
||||
function getKeyName(keySpec) {
|
||||
// convert a key element into a string describing what keys to push.
|
||||
// "Control-C" or "Control-Meta-Hyper-Shift-Q" or whatever
|
||||
if (!key)
|
||||
if (!keySpec)
|
||||
return "";
|
||||
var keySpec = makeKeySpec(key);
|
||||
if (keySpec instanceof Components.interfaces.nsIDOMElement)
|
||||
keySpec = makeKeySpec(keySpec);
|
||||
|
||||
var accel = [];
|
||||
var keybundle = document.getElementById("bundle-keys");
|
||||
var keyName = keySpec.keytext || keySpec.key || keybundle.getString(keySpec.keycode);
|
||||
var modifiers = keySpec.modifiers.split(" ");
|
||||
|
||||
// this is sorta dumb, but whatever
|
||||
var modifiers = [], i = 1;
|
||||
for each (m in ["alt", "control", "meta", "shift"])
|
||||
{
|
||||
if (keySpec.modifiers & i)
|
||||
modifiers.push(m);
|
||||
i += i;
|
||||
}
|
||||
|
||||
for each (m in modifiers)
|
||||
if (m in platformKeys)
|
||||
accel.push(platformKeys[m]);
|
||||
accel.push(keyName);
|
||||
accel.push(keySpec.keytext || keySpec.key || keybundle.getString(keySpec.keycode));
|
||||
|
||||
return accel.join(modifierSeparator);
|
||||
}
|
||||
|
||||
// this listens to keyup events and converts them into the proper display name for the textbox
|
||||
function keyListener(event)
|
||||
{
|
||||
if (!event instanceof Components.interfaces.nsIDOMKeyEvent)
|
||||
return;
|
||||
document.getElementById("test").value = getKeyName(makeKeySpec(event));
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
// show the window
|
||||
this.edit = function()
|
||||
{
|
||||
|
@ -196,53 +327,61 @@ function ShortcutEditor()
|
|||
Array.forEach(nodes, function(n) { if (n.getAttribute("id") != "browser-container") { n.hidden = true; }});
|
||||
document.getElementById("shortcuts-container").hidden = false;
|
||||
fillShortcutList();
|
||||
|
||||
document.getElementById("test").addEventListener("keypress", keyListener, true);
|
||||
};
|
||||
|
||||
this.dismiss = function()
|
||||
{
|
||||
document.getElementById("test").removeEventListener("keypress", keyListener, true);
|
||||
document.getElementById("shortcuts-container").hidden = true;
|
||||
};
|
||||
|
||||
// also, updating the UI is helpful
|
||||
function fillShortcutList()
|
||||
{
|
||||
var tree = document.getElementById("shortcuts");
|
||||
var commands = getCommandNames();
|
||||
var sb = document.getElementById("bundle-shortcuts");
|
||||
var sb = document.getElementById("shortcut-bundles").childNodes;
|
||||
|
||||
function doAppend(name, key)
|
||||
function doAppend(command)
|
||||
{
|
||||
// TODO: alter the listbox xbl binding so that if appendItem is
|
||||
// given more than 2 arguments, it interprets the additional
|
||||
// arguments as labels for additional cells.
|
||||
var key = findKeyForCommand(command)
|
||||
var cell1 = document.createElementNS(XUL_NS, "treecell");
|
||||
cell1.setAttribute("label", name);
|
||||
cell1.setAttribute("label", doGetString(command +".name") || command);
|
||||
cell1.setAttribute("value", command);
|
||||
var cell2 = document.createElementNS(XUL_NS, "treecell");
|
||||
cell2.setAttribute("label", key);
|
||||
cell2.setAttribute("label", getKeyName(key));
|
||||
cell2.setAttribute("value", makeKeySpec(key));
|
||||
var row = document.createElementNS(XUL_NS, "treerow");
|
||||
row.appendChild(cell1);
|
||||
row.appendChild(cell2);
|
||||
var item = document.createElementNS(XUL_NS, "treeitem");
|
||||
item.appendChild(row);
|
||||
document.getElementById("shortcuts-children").appendChild(item);
|
||||
children.appendChild(item);
|
||||
}
|
||||
|
||||
function doGetString(name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return sb.getString(name);
|
||||
}
|
||||
catch (e) { }
|
||||
var l = sb.length;
|
||||
for (var i = 0; i < l; i++)
|
||||
try
|
||||
{
|
||||
return sb[i].getString(name);
|
||||
}
|
||||
catch (e) { }
|
||||
}
|
||||
|
||||
var tree = document.getElementById("shortcuts");
|
||||
var children = document.getElementById("shortcuts-children");
|
||||
tree.removeChild(children);
|
||||
children = document.createElementNS(XUL_NS, "treechildren");
|
||||
children.setAttribute("id", "shortcuts-children");
|
||||
tree.appendChild(children);
|
||||
|
||||
commands.forEach(function(c) { doAppend(doGetString(c +".name") || c, getKeyName(findKeyForCommand(c)) || "—"); });
|
||||
commands.forEach(doAppend);
|
||||
}
|
||||
|
||||
// saving and restoring a key assignment to the prefs
|
||||
|
|
Загрузка…
Ссылка в новой задаче