mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2025-12-19 16:27:58 +01:00
Move events.(toString|fromString|iterKeys|canonicalKeys) to DOM.Event.
This commit is contained in:
@@ -6,7 +6,7 @@
|
|||||||
<page id="about-&dactyl.name;" orient="vertical" title="About &dactyl.appName;"
|
<page id="about-&dactyl.name;" orient="vertical" title="About &dactyl.appName;"
|
||||||
xmlns="&xmlns.xul;" xmlns:html="&xmlns.html;">
|
xmlns="&xmlns.xul;" xmlns:html="&xmlns.html;">
|
||||||
|
|
||||||
<html:link rel="icon" href="chrome://&dactyl.name;/skin/icon.png"
|
<html:link rel="icon" href="resource://dactyl-local-skin/icon.png"
|
||||||
type="image/png" style="display: none;"/>
|
type="image/png" style="display: none;"/>
|
||||||
|
|
||||||
<spring flex="1"/>
|
<spring flex="1"/>
|
||||||
|
|||||||
@@ -393,7 +393,7 @@ var CommandMode = Class("CommandMode", {
|
|||||||
this.onChange(commandline.command);
|
this.onChange(commandline.command);
|
||||||
},
|
},
|
||||||
keyup: function CM_onKeyUp(event) {
|
keyup: function CM_onKeyUp(event) {
|
||||||
let key = events.toString(event);
|
let key = DOM.Event.stringify(event);
|
||||||
if (/-?Tab>$/.test(key) && this.completions)
|
if (/-?Tab>$/.test(key) && this.completions)
|
||||||
this.completions.tabTimer.flush();
|
this.completions.tabTimer.flush();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ var Editor = Module("editor", {
|
|||||||
if (count == null)
|
if (count == null)
|
||||||
count = 1;
|
count = 1;
|
||||||
|
|
||||||
let code = events.fromString(key)[0].charCode;
|
let code = DOM.Event.parse(key)[0].charCode;
|
||||||
util.assert(code);
|
util.assert(code);
|
||||||
let char = String.fromCharCode(code);
|
let char = String.fromCharCode(code);
|
||||||
|
|
||||||
|
|||||||
@@ -115,67 +115,6 @@ var Events = Module("events", {
|
|||||||
if (isString(m))
|
if (isString(m))
|
||||||
m = { keys: m, timeRecorded: Date.now() };
|
m = { keys: m, timeRecorded: Date.now() };
|
||||||
|
|
||||||
// NOTE: the order of ["Esc", "Escape"] or ["Escape", "Esc"]
|
|
||||||
// matters, so use that string as the first item, that you
|
|
||||||
// want to refer to within dactyl's source code for
|
|
||||||
// comparisons like if (key == "<Esc>") { ... }
|
|
||||||
this._keyTable = {
|
|
||||||
add: ["Plus", "Add"],
|
|
||||||
back_space: ["BS"],
|
|
||||||
count: ["count"],
|
|
||||||
delete: ["Del"],
|
|
||||||
escape: ["Esc", "Escape"],
|
|
||||||
insert: ["Insert", "Ins"],
|
|
||||||
leader: ["Leader"],
|
|
||||||
left_shift: ["LT", "<"],
|
|
||||||
nop: ["Nop"],
|
|
||||||
pass: ["Pass"],
|
|
||||||
return: ["Return", "CR", "Enter"],
|
|
||||||
right_shift: [">"],
|
|
||||||
space: ["Space", " "],
|
|
||||||
subtract: ["Minus", "Subtract"]
|
|
||||||
};
|
|
||||||
|
|
||||||
this._pseudoKeys = Set(["count", "leader", "nop", "pass"]);
|
|
||||||
|
|
||||||
this._key_key = {};
|
|
||||||
this._code_key = {};
|
|
||||||
this._key_code = {};
|
|
||||||
this._code_nativeKey = {};
|
|
||||||
|
|
||||||
for (let list in values(this._keyTable))
|
|
||||||
for (let v in values(list)) {
|
|
||||||
if (v.length == 1)
|
|
||||||
v = v.toLowerCase();
|
|
||||||
this._key_key[v.toLowerCase()] = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let [k, v] in Iterator(KeyEvent)) {
|
|
||||||
this._code_nativeKey[v] = k.substr(4);
|
|
||||||
|
|
||||||
k = k.substr(7).toLowerCase();
|
|
||||||
let names = [k.replace(/(^|_)(.)/g, function (m, n1, n2) n2.toUpperCase())
|
|
||||||
.replace(/^NUMPAD/, "k")];
|
|
||||||
|
|
||||||
if (names[0].length == 1)
|
|
||||||
names[0] = names[0].toLowerCase();
|
|
||||||
|
|
||||||
if (k in this._keyTable)
|
|
||||||
names = this._keyTable[k];
|
|
||||||
this._code_key[v] = names[0];
|
|
||||||
for (let [, name] in Iterator(names)) {
|
|
||||||
this._key_key[name.toLowerCase()] = name;
|
|
||||||
this._key_code[name.toLowerCase()] = v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// HACK: as Gecko does not include an event for <, we must add this in manually.
|
|
||||||
if (!("<" in this._key_code)) {
|
|
||||||
this._key_code["<"] = 60;
|
|
||||||
this._key_code["lt"] = 60;
|
|
||||||
this._code_key[60] = "lt";
|
|
||||||
}
|
|
||||||
|
|
||||||
this.popups = {
|
this.popups = {
|
||||||
active: [],
|
active: [],
|
||||||
|
|
||||||
@@ -298,8 +237,8 @@ var Events = Module("events", {
|
|||||||
|
|
||||||
if (/[A-Z]/.test(macro)) { // uppercase (append)
|
if (/[A-Z]/.test(macro)) { // uppercase (append)
|
||||||
macro = macro.toLowerCase();
|
macro = macro.toLowerCase();
|
||||||
this._macroKeys = events.fromString((this._macros.get(macro) || { keys: "" }).keys, true)
|
this._macroKeys = DOM.Event.stringify((this._macros.get(macro) || { keys: "" }).keys, true)
|
||||||
.map(events.closure.toString);
|
.map(DOM.Event.closure.stringify);
|
||||||
}
|
}
|
||||||
else if (macro) {
|
else if (macro) {
|
||||||
this._macroKeys = [];
|
this._macroKeys = [];
|
||||||
@@ -421,9 +360,9 @@ var Events = Module("events", {
|
|||||||
|
|
||||||
keys = mappings.expandLeader(keys);
|
keys = mappings.expandLeader(keys);
|
||||||
|
|
||||||
for (let [, evt_obj] in Iterator(events.fromString(keys))) {
|
for (let [, evt_obj] in Iterator(DOM.Event.parse(keys))) {
|
||||||
let now = Date.now();
|
let now = Date.now();
|
||||||
let key = events.toString(evt_obj);
|
let key = DOM.Event.stringify(evt_obj);
|
||||||
for (let type in values(["keydown", "keypress", "keyup"])) {
|
for (let type in values(["keydown", "keypress", "keyup"])) {
|
||||||
let evt = update({}, evt_obj, { type: type });
|
let evt = update({}, evt_obj, { type: type });
|
||||||
if (type !== "keypress" && !evt.keyCode)
|
if (type !== "keypress" && !evt.keyCode)
|
||||||
@@ -472,267 +411,21 @@ var Events = Module("events", {
|
|||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
create: deprecated("DOM.Event", function create() DOM.Event.apply(null, arguments)),
|
canonicalKeys: deprecated("DOM.Event.canonicalKeys", { get: function canonicalKeys() DOM.Event.closure.canonicalKeys }),
|
||||||
dispatch: deprecated("DOM.Event.dispatch", function dispatch() DOM.Event.dispatch.apply(DOM.Event, arguments)),
|
create: deprecated("DOM.Event", function create() DOM.Event.apply(null, arguments)),
|
||||||
|
dispatch: deprecated("DOM.Event.dispatch", function dispatch() DOM.Event.dispatch.apply(DOM.Event, arguments)),
|
||||||
|
fromString: deprecated("DOM.Event.parse", { get: function fromString() DOM.Event.closure.parse }),
|
||||||
|
iterKeys: deprecated("DOM.Event.iterKeys", { get: function iterKeys() DOM.Event.closure.iterKeys }),
|
||||||
|
|
||||||
/**
|
toString: function toString() {
|
||||||
* Converts a user-input string of keys into a canonical
|
if (!arguments.length)
|
||||||
* representation.
|
return toString.supercall(this);
|
||||||
*
|
deprecated.warn(toString, "toString", "DOM.Event.stringify");
|
||||||
* <C-A> maps to <C-a>, <C-S-a> maps to <C-S-A>
|
return DOM.Event.stringify.apply(DOM.Event, arguments);
|
||||||
* <C- > maps to <C-Space>, <S-a> maps to A
|
|
||||||
* << maps to <lt><lt>
|
|
||||||
*
|
|
||||||
* <S-@> is preserved, as in Vim, to allow untypeable key-combinations
|
|
||||||
* in macros.
|
|
||||||
*
|
|
||||||
* canonicalKeys(canonicalKeys(x)) == canonicalKeys(x) for all values
|
|
||||||
* of x.
|
|
||||||
*
|
|
||||||
* @param {string} keys Messy form.
|
|
||||||
* @param {boolean} unknownOk Whether unknown keys are passed
|
|
||||||
* through rather than being converted to <lt>keyname>.
|
|
||||||
* @default false
|
|
||||||
* @returns {string} Canonical form.
|
|
||||||
*/
|
|
||||||
canonicalKeys: function (keys, unknownOk) {
|
|
||||||
if (arguments.length === 1)
|
|
||||||
unknownOk = true;
|
|
||||||
return events.fromString(keys, unknownOk).map(events.closure.toString).join("");
|
|
||||||
},
|
},
|
||||||
|
|
||||||
iterKeys: function (keys) iter(function () {
|
|
||||||
let match, re = /<.*?>?>|[^<]/g;
|
|
||||||
while (match = re.exec(keys))
|
|
||||||
yield match[0];
|
|
||||||
}()),
|
|
||||||
|
|
||||||
get defaultTarget() dactyl.focusedElement || content.document.body || document.documentElement,
|
get defaultTarget() dactyl.focusedElement || content.document.body || document.documentElement,
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts an event string into an array of pseudo-event objects.
|
|
||||||
*
|
|
||||||
* These objects can be used as arguments to events.toString or
|
|
||||||
* events.create, though they are unlikely to be much use for other
|
|
||||||
* purposes. They have many of the properties you'd expect to find on a
|
|
||||||
* real event, but none of the methods.
|
|
||||||
*
|
|
||||||
* Also may contain two "special" parameters, .dactylString and
|
|
||||||
* .dactylShift these are set for characters that can never by
|
|
||||||
* typed, but may appear in mappings, for example <Nop> is passed as
|
|
||||||
* dactylString, and dactylShift is set when a user specifies
|
|
||||||
* <S-@> where @ is a non-case-changeable, non-space character.
|
|
||||||
*
|
|
||||||
* @param {string} keys The string to parse.
|
|
||||||
* @param {boolean} unknownOk Whether unknown keys are passed
|
|
||||||
* through rather than being converted to <lt>keyname>.
|
|
||||||
* @default false
|
|
||||||
* @returns {Array[Object]}
|
|
||||||
*/
|
|
||||||
fromString: function (input, unknownOk) {
|
|
||||||
|
|
||||||
if (arguments.length === 1)
|
|
||||||
unknownOk = true;
|
|
||||||
|
|
||||||
let out = [];
|
|
||||||
for (let match in util.regexp.iterate(/<.*?>?>|[^<]|<(?!.*>)/g, input)) {
|
|
||||||
let evt_str = match[0];
|
|
||||||
|
|
||||||
let evt_obj = { ctrlKey: false, shiftKey: false, altKey: false, metaKey: false,
|
|
||||||
keyCode: 0, charCode: 0, type: "keypress" };
|
|
||||||
|
|
||||||
if (evt_str.length == 1) {
|
|
||||||
evt_obj.charCode = evt_str.charCodeAt(0);
|
|
||||||
evt_obj._keyCode = this._key_code[evt_str[0].toLowerCase()];
|
|
||||||
evt_obj.shiftKey = evt_str !== evt_str.toLowerCase();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
let [match, modifier, keyname] = evt_str.match(/^<((?:[*12CASM⌘]-)*)(.+?)>$/i) || [false, '', ''];
|
|
||||||
modifier = Set(modifier.toUpperCase());
|
|
||||||
keyname = keyname.toLowerCase();
|
|
||||||
evt_obj.dactylKeyname = keyname;
|
|
||||||
if (/^u[0-9a-f]+$/.test(keyname))
|
|
||||||
keyname = String.fromCharCode(parseInt(keyname.substr(1), 16));
|
|
||||||
|
|
||||||
if (keyname && (unknownOk || keyname.length == 1 || /mouse$/.test(keyname) ||
|
|
||||||
this._key_code[keyname] || Set.has(this._pseudoKeys, keyname))) {
|
|
||||||
evt_obj.globKey ="*" in modifier;
|
|
||||||
evt_obj.ctrlKey ="C" in modifier;
|
|
||||||
evt_obj.altKey ="A" in modifier;
|
|
||||||
evt_obj.shiftKey ="S" in modifier;
|
|
||||||
evt_obj.metaKey ="M" in modifier || "⌘" in modifier;
|
|
||||||
evt_obj.dactylShift = evt_obj.shiftKey;
|
|
||||||
|
|
||||||
if (keyname.length == 1) { // normal characters
|
|
||||||
if (evt_obj.shiftKey)
|
|
||||||
keyname = keyname.toUpperCase();
|
|
||||||
|
|
||||||
evt_obj.dactylShift = evt_obj.shiftKey && keyname.toUpperCase() == keyname.toLowerCase();
|
|
||||||
evt_obj.charCode = keyname.charCodeAt(0);
|
|
||||||
evt_obj._keyCode = this._key_code[keyname.toLowerCase()];
|
|
||||||
}
|
|
||||||
else if (Set.has(this._pseudoKeys, keyname)) {
|
|
||||||
evt_obj.dactylString = "<" + this._key_key[keyname] + ">";
|
|
||||||
}
|
|
||||||
else if (/mouse$/.test(keyname)) { // mouse events
|
|
||||||
evt_obj.type = (/2-/.test(modifier) ? "dblclick" : "click");
|
|
||||||
evt_obj.button = ["leftmouse", "middlemouse", "rightmouse"].indexOf(keyname);
|
|
||||||
delete evt_obj.keyCode;
|
|
||||||
delete evt_obj.charCode;
|
|
||||||
}
|
|
||||||
else { // spaces, control characters, and <
|
|
||||||
evt_obj.keyCode = this._key_code[keyname];
|
|
||||||
evt_obj.charCode = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { // an invalid sequence starting with <, treat as a literal
|
|
||||||
out = out.concat(events.fromString("<lt>" + evt_str.substr(1)));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: make a list of characters that need keyCode and charCode somewhere
|
|
||||||
if (evt_obj.keyCode == 32 || evt_obj.charCode == 32)
|
|
||||||
evt_obj.charCode = evt_obj.keyCode = 32; // <Space>
|
|
||||||
if (evt_obj.keyCode == 60 || evt_obj.charCode == 60)
|
|
||||||
evt_obj.charCode = evt_obj.keyCode = 60; // <lt>
|
|
||||||
|
|
||||||
evt_obj.modifiers = (evt_obj.ctrlKey && Ci.nsIDOMNSEvent.CONTROL_MASK)
|
|
||||||
| (evt_obj.altKey && Ci.nsIDOMNSEvent.ALT_MASK)
|
|
||||||
| (evt_obj.shiftKey && Ci.nsIDOMNSEvent.SHIFT_MASK)
|
|
||||||
| (evt_obj.metaKey && Ci.nsIDOMNSEvent.META_MASK);
|
|
||||||
|
|
||||||
out.push(evt_obj);
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts the specified event to a string in dactyl key-code
|
|
||||||
* notation. Returns null for an unknown event.
|
|
||||||
*
|
|
||||||
* @param {Event} event
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
toString: function toString(event) {
|
|
||||||
if (!event)
|
|
||||||
return toString.supercall(this);
|
|
||||||
|
|
||||||
if (event.dactylString)
|
|
||||||
return event.dactylString;
|
|
||||||
|
|
||||||
let key = null;
|
|
||||||
let modifier = "";
|
|
||||||
|
|
||||||
if (event.globKey)
|
|
||||||
modifier += "*-";
|
|
||||||
if (event.ctrlKey)
|
|
||||||
modifier += "C-";
|
|
||||||
if (event.altKey)
|
|
||||||
modifier += "A-";
|
|
||||||
if (event.metaKey)
|
|
||||||
modifier += "M-";
|
|
||||||
|
|
||||||
if (/^key/.test(event.type)) {
|
|
||||||
let charCode = event.type == "keyup" ? 0 : event.charCode; // Why? --Kris
|
|
||||||
if (charCode == 0) {
|
|
||||||
if (event.keyCode in this._code_key) {
|
|
||||||
key = this._code_key[event.keyCode];
|
|
||||||
|
|
||||||
if (event.shiftKey && (key.length > 1 || event.ctrlKey || event.altKey || event.metaKey) || event.dactylShift)
|
|
||||||
modifier += "S-";
|
|
||||||
else if (!modifier && key.length === 1)
|
|
||||||
if (event.shiftKey)
|
|
||||||
key = key.toUpperCase();
|
|
||||||
else
|
|
||||||
key = key.toLowerCase();
|
|
||||||
|
|
||||||
if (!modifier && /^[a-z0-9]$/i.test(key))
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// [Ctrl-Bug] special handling of mysterious <C-[>, <C-\\>, <C-]>, <C-^>, <C-_> bugs (OS/X)
|
|
||||||
// (i.e., cntrl codes 27--31)
|
|
||||||
// ---
|
|
||||||
// For more information, see:
|
|
||||||
// [*] Referenced mailing list msg: http://www.mozdev.org/pipermail/pentadactyl/2008-May/001548.html
|
|
||||||
// [*] Mozilla bug 416227: event.charCode in keypress handler has unexpected values on Mac for Ctrl with chars in "[ ] _ \"
|
|
||||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=416227
|
|
||||||
// [*] Mozilla bug 432951: Ctrl+'foo' doesn't seem same charCode as Meta+'foo' on Cocoa
|
|
||||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=432951
|
|
||||||
// ---
|
|
||||||
//
|
|
||||||
// The following fixes are only activated if config.OS.isMacOSX.
|
|
||||||
// Technically, they prevent mappings from <C-Esc> (and
|
|
||||||
// <C-C-]> if your fancy keyboard permits such things<?>), but
|
|
||||||
// these <C-control> mappings are probably pathological (<C-Esc>
|
|
||||||
// certainly is on Windows), and so it is probably
|
|
||||||
// harmless to remove the config.OS.isMacOSX if desired.
|
|
||||||
//
|
|
||||||
else if (config.OS.isMacOSX && event.ctrlKey && charCode >= 27 && charCode <= 31) {
|
|
||||||
if (charCode == 27) { // [Ctrl-Bug 1/5] the <C-[> bug
|
|
||||||
key = "Esc";
|
|
||||||
modifier = modifier.replace("C-", "");
|
|
||||||
}
|
|
||||||
else // [Ctrl-Bug 2,3,4,5/5] the <C-\\>, <C-]>, <C-^>, <C-_> bugs
|
|
||||||
key = String.fromCharCode(charCode + 64);
|
|
||||||
}
|
|
||||||
// a normal key like a, b, c, 0, etc.
|
|
||||||
else if (charCode > 0) {
|
|
||||||
key = String.fromCharCode(charCode);
|
|
||||||
|
|
||||||
if (!/^[a-z0-9]$/i.test(key) && key in this._key_code) {
|
|
||||||
// a named charCode key (<Space> and <lt>) space can be shifted, <lt> must be forced
|
|
||||||
if ((key.match(/^\s$/) && event.shiftKey) || event.dactylShift)
|
|
||||||
modifier += "S-";
|
|
||||||
|
|
||||||
key = this._code_key[this._key_code[key]];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// a shift modifier is only allowed if the key is alphabetical and used in a C-A-M- mapping in the uppercase,
|
|
||||||
// or if the shift has been forced for a non-alphabetical character by the user while :map-ping
|
|
||||||
if (key !== key.toLowerCase() && (event.ctrlKey || event.altKey || event.metaKey) || event.dactylShift)
|
|
||||||
modifier += "S-";
|
|
||||||
if (/^\s$/.test(key))
|
|
||||||
key = let (s = charCode.toString(16)) "U" + "0000".substr(4 - s.length) + s;
|
|
||||||
else if (modifier.length == 0)
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (key == null) {
|
|
||||||
if (event.shiftKey)
|
|
||||||
modifier += "S-";
|
|
||||||
key = this._key_key[event.dactylKeyname] || event.dactylKeyname;
|
|
||||||
}
|
|
||||||
if (key == null)
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
else if (event.type == "click" || event.type == "dblclick") {
|
|
||||||
if (event.shiftKey)
|
|
||||||
modifier += "S-";
|
|
||||||
if (event.type == "dblclick")
|
|
||||||
modifier += "2-";
|
|
||||||
// TODO: triple and quadruple click
|
|
||||||
|
|
||||||
switch (event.button) {
|
|
||||||
case 0:
|
|
||||||
key = "LeftMouse";
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
key = "MiddleMouse";
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
key = "RightMouse";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return "<" + modifier + key + ">";
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if there's a known native key handler for the given
|
* Returns true if there's a known native key handler for the given
|
||||||
* event in the given mode.
|
* event in the given mode.
|
||||||
@@ -957,7 +650,7 @@ var Events = Module("events", {
|
|||||||
event[k] = v;
|
event[k] = v;
|
||||||
DOM.Event.feedingEvent = null;
|
DOM.Event.feedingEvent = null;
|
||||||
|
|
||||||
let key = events.toString(event);
|
let key = DOM.Event.stringify(event);
|
||||||
|
|
||||||
// Hack to deal with <BS> and so forth not dispatching input
|
// Hack to deal with <BS> and so forth not dispatching input
|
||||||
// events
|
// events
|
||||||
@@ -1079,7 +772,7 @@ var Events = Module("events", {
|
|||||||
!modes.passThrough && this.shouldPass(event) ||
|
!modes.passThrough && this.shouldPass(event) ||
|
||||||
!this.processor && event.type === "keydown"
|
!this.processor && event.type === "keydown"
|
||||||
&& options.get("passunknown").getKey(modes.main.allBases)
|
&& options.get("passunknown").getKey(modes.main.allBases)
|
||||||
&& let (key = events.toString(event))
|
&& let (key = DOM.Event.stringify(event))
|
||||||
!modes.main.allBases.some(
|
!modes.main.allBases.some(
|
||||||
function (mode) mappings.hives.some(
|
function (mode) mappings.hives.some(
|
||||||
function (hive) hive.get(mode, key) || hive.getCandidates(mode, key)));
|
function (hive) hive.get(mode, key) || hive.getCandidates(mode, key)));
|
||||||
@@ -1087,7 +780,7 @@ var Events = Module("events", {
|
|||||||
if (event.type === "keydown")
|
if (event.type === "keydown")
|
||||||
this.passing = pass;
|
this.passing = pass;
|
||||||
|
|
||||||
events.dbg("ON " + event.type.toUpperCase() + " " + this.toString(event) + " pass: " + pass + " replay: " + event.isReplay + " macro: " + event.isMacro);
|
events.dbg("ON " + event.type.toUpperCase() + " " + DOM.Event.stringify(event) + " pass: " + pass + " replay: " + event.isReplay + " macro: " + event.isMacro);
|
||||||
|
|
||||||
// Prevents certain sites from transferring focus to an input box
|
// Prevents certain sites from transferring focus to an input box
|
||||||
// before we get a chance to process our key bindings on the
|
// before we get a chance to process our key bindings on the
|
||||||
@@ -1220,7 +913,7 @@ var Events = Module("events", {
|
|||||||
|
|
||||||
shouldPass: function shouldPass(event)
|
shouldPass: function shouldPass(event)
|
||||||
!event.noremap && (!dactyl.focusedElement || events.isContentNode(dactyl.focusedElement)) &&
|
!event.noremap && (!dactyl.focusedElement || events.isContentNode(dactyl.focusedElement)) &&
|
||||||
options.get("passkeys").has(events.toString(event))
|
options.get("passkeys").has(DOM.Event.stringify(event))
|
||||||
}, {
|
}, {
|
||||||
ABORT: {},
|
ABORT: {},
|
||||||
KILL: true,
|
KILL: true,
|
||||||
@@ -1229,7 +922,7 @@ var Events = Module("events", {
|
|||||||
WAIT: null,
|
WAIT: null,
|
||||||
|
|
||||||
isEscape: function isEscape(event)
|
isEscape: function isEscape(event)
|
||||||
let (key = isString(event) ? event : events.toString(event))
|
let (key = isString(event) ? event : DOM.Event.stringify(event))
|
||||||
key === "<Esc>" || key === "<C-[>",
|
key === "<Esc>" || key === "<C-[>",
|
||||||
|
|
||||||
isHidden: function isHidden(elem, aggressive) {
|
isHidden: function isHidden(elem, aggressive) {
|
||||||
@@ -1405,9 +1098,9 @@ var Events = Module("events", {
|
|||||||
let value = parse.superapply(this, arguments);
|
let value = parse.superapply(this, arguments);
|
||||||
value.forEach(function (filter) {
|
value.forEach(function (filter) {
|
||||||
let vals = Option.splitList(filter.result);
|
let vals = Option.splitList(filter.result);
|
||||||
filter.keys = events.fromString(vals[0]).map(events.closure.toString);
|
filter.keys = DOM.Event.parse(vals[0]).map(DOM.Event.closure.stringify);
|
||||||
|
|
||||||
filter.commandKeys = vals.slice(1).map(events.closure.canonicalKeys);
|
filter.commandKeys = vals.slice(1).map(DOM.Event.closure.canonicalKeys);
|
||||||
filter.inputKeys = filter.commandKeys.filter(bind("test", /^<[ACM]-/));
|
filter.inputKeys = filter.commandKeys.filter(bind("test", /^<[ACM]-/));
|
||||||
});
|
});
|
||||||
return value;
|
return value;
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ var HintSession = Class("HintSession", CommandMode, {
|
|||||||
this.activeTimeout = null; // needed for hinttimeout > 0
|
this.activeTimeout = null; // needed for hinttimeout > 0
|
||||||
this.continue = Boolean(opts.continue);
|
this.continue = Boolean(opts.continue);
|
||||||
this.docs = [];
|
this.docs = [];
|
||||||
this.hintKeys = events.fromString(options["hintkeys"]).map(events.closure.toString);
|
this.hintKeys = DOM.Event.parse(options["hintkeys"]).map(DOM.Event.closure.stringify);
|
||||||
this.hintNumber = 0;
|
this.hintNumber = 0;
|
||||||
this.hintString = opts.filter || "";
|
this.hintString = opts.filter || "";
|
||||||
this.pageHints = [];
|
this.pageHints = [];
|
||||||
@@ -403,7 +403,7 @@ var HintSession = Class("HintSession", CommandMode, {
|
|||||||
*/
|
*/
|
||||||
onKeyPress: function onKeyPress(eventList) {
|
onKeyPress: function onKeyPress(eventList) {
|
||||||
const KILL = false, PASS = true;
|
const KILL = false, PASS = true;
|
||||||
let key = events.toString(eventList[0]);
|
let key = DOM.Event.stringify(eventList[0]);
|
||||||
|
|
||||||
this.clearTimeout();
|
this.clearTimeout();
|
||||||
|
|
||||||
@@ -1301,7 +1301,7 @@ var Hints = Module("hints", {
|
|||||||
"asdfg;lkjh": "Home Row"
|
"asdfg;lkjh": "Home Row"
|
||||||
},
|
},
|
||||||
validator: function (value) {
|
validator: function (value) {
|
||||||
let values = events.fromString(value).map(events.closure.toString);
|
let values = DOM.Event.parse(value).map(DOM.Event.closure.stringify);
|
||||||
return Option.validIf(array.uniq(values).length === values.length && values.length > 1,
|
return Option.validIf(array.uniq(values).length === values.length && values.length > 1,
|
||||||
_("option.hintkeys.duplicate"));
|
_("option.hintkeys.duplicate"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ var ProcessorStack = Class("ProcessorStack", {
|
|||||||
events.passing = true;
|
events.passing = true;
|
||||||
|
|
||||||
if (result === Events.PASS_THROUGH && this.keyEvents.length)
|
if (result === Events.PASS_THROUGH && this.keyEvents.length)
|
||||||
events.dbg("PASS_THROUGH:\n\t" + this.keyEvents.map(function (e) [e.type, events.toString(e)]).join("\n\t"));
|
events.dbg("PASS_THROUGH:\n\t" + this.keyEvents.map(function (e) [e.type, DOM.Event.stringify(e)]).join("\n\t"));
|
||||||
|
|
||||||
if (result === Events.PASS_THROUGH)
|
if (result === Events.PASS_THROUGH)
|
||||||
events.feedevents(null, this.keyEvents, { skipmap: true, isMacro: true, isReplay: true });
|
events.feedevents(null, this.keyEvents, { skipmap: true, isMacro: true, isReplay: true });
|
||||||
@@ -142,9 +142,9 @@ var ProcessorStack = Class("ProcessorStack", {
|
|||||||
let list = this.events.filter(function (e) e.getPreventDefault() && !e.dactylDefaultPrevented);
|
let list = this.events.filter(function (e) e.getPreventDefault() && !e.dactylDefaultPrevented);
|
||||||
|
|
||||||
if (result === Events.PASS)
|
if (result === Events.PASS)
|
||||||
events.dbg("PASS THROUGH: " + list.slice(0, length).filter(function (e) e.type === "keypress").map(events.closure.toString));
|
events.dbg("PASS THROUGH: " + list.slice(0, length).filter(function (e) e.type === "keypress").map(DOM.Event.closure.stringify));
|
||||||
if (list.length > length)
|
if (list.length > length)
|
||||||
events.dbg("REFEED: " + list.slice(length).filter(function (e) e.type === "keypress").map(events.closure.toString));
|
events.dbg("REFEED: " + list.slice(length).filter(function (e) e.type === "keypress").map(DOM.Event.closure.stringify));
|
||||||
|
|
||||||
if (result === Events.PASS)
|
if (result === Events.PASS)
|
||||||
events.feedevents(null, list.slice(0, length), { skipmap: true, isMacro: true, isReplay: true });
|
events.feedevents(null, list.slice(0, length), { skipmap: true, isMacro: true, isReplay: true });
|
||||||
@@ -159,7 +159,7 @@ var ProcessorStack = Class("ProcessorStack", {
|
|||||||
if (this.timer)
|
if (this.timer)
|
||||||
this.timer.cancel();
|
this.timer.cancel();
|
||||||
|
|
||||||
let key = events.toString(event);
|
let key = DOM.Event.stringify(event);
|
||||||
this.events.push(event);
|
this.events.push(event);
|
||||||
if (this.keyEvents)
|
if (this.keyEvents)
|
||||||
this.keyEvents.push(event);
|
this.keyEvents.push(event);
|
||||||
@@ -233,7 +233,7 @@ var KeyProcessor = Class("KeyProcessor", {
|
|||||||
|
|
||||||
append: function append(event) {
|
append: function append(event) {
|
||||||
this.events.push(event);
|
this.events.push(event);
|
||||||
let key = events.toString(event);
|
let key = DOM.Event.stringify(event);
|
||||||
|
|
||||||
if (this.wantCount && !this.command &&
|
if (this.wantCount && !this.command &&
|
||||||
(this.countStr ? /^[0-9]$/ : /^[1-9]$/).test(key))
|
(this.countStr ? /^[0-9]$/ : /^[1-9]$/).test(key))
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ var Map = Class("Map", {
|
|||||||
name: Class.Memoize(function () this.names[0]),
|
name: Class.Memoize(function () this.names[0]),
|
||||||
|
|
||||||
/** @property {[string]} All of this mapping's names (key sequences). */
|
/** @property {[string]} All of this mapping's names (key sequences). */
|
||||||
names: Class.Memoize(function () this._keys.map(function (k) events.canonicalKeys(k))),
|
names: Class.Memoize(function () this._keys.map(function (k) DOM.Event.canonicalKeys(k))),
|
||||||
|
|
||||||
get toStringParams() [this.modes.map(function (m) m.name), this.names.map(String.quote)],
|
get toStringParams() [this.modes.map(function (m) m.name), this.names.map(String.quote)],
|
||||||
|
|
||||||
@@ -303,7 +303,7 @@ var MapHive = Class("MapHive", Contexts.Hive, {
|
|||||||
for (let name in values(map.keys)) {
|
for (let name in values(map.keys)) {
|
||||||
states.mappings[name] = map;
|
states.mappings[name] = map;
|
||||||
let state = "";
|
let state = "";
|
||||||
for (let key in events.iterKeys(name)) {
|
for (let key in DOM.Event.iterKeys(name)) {
|
||||||
state += key;
|
state += key;
|
||||||
if (state !== name)
|
if (state !== name)
|
||||||
states.candidates[state] = (states.candidates[state] || 0) + 1;
|
states.candidates[state] = (states.candidates[state] || 0) + 1;
|
||||||
@@ -341,11 +341,11 @@ var Mappings = Module("mappings", {
|
|||||||
if (!/<\*-/.test(keys))
|
if (!/<\*-/.test(keys))
|
||||||
return keys;
|
return keys;
|
||||||
|
|
||||||
return util.debrace(events.iterKeys(keys).map(function (key) {
|
return util.debrace(DOM.Event.iterKeys(keys).map(function (key) {
|
||||||
if (/^<\*-/.test(key))
|
if (/^<\*-/.test(key))
|
||||||
return ["<", this.prefixes, key.slice(3)];
|
return ["<", this.prefixes, key.slice(3)];
|
||||||
return key;
|
return key;
|
||||||
}, this).flatten().array).map(function (k) events.canonicalKeys(k));
|
}, this).flatten().array).map(function (k) DOM.Event.canonicalKeys(k));
|
||||||
},
|
},
|
||||||
|
|
||||||
iterate: function (mode) {
|
iterate: function (mode) {
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ var Modes = Module("modes", {
|
|||||||
const KILL = false, PASS = true;
|
const KILL = false, PASS = true;
|
||||||
|
|
||||||
// Hack, really.
|
// Hack, really.
|
||||||
if (eventList[0].charCode || /^<(?:.-)*(?:BS|Del|C-h|C-w|C-u|C-k)>$/.test(events.toString(eventList[0]))) {
|
if (eventList[0].charCode || /^<(?:.-)*(?:BS|Del|C-h|C-w|C-u|C-k)>$/.test(DOM.Event.stringify(eventList[0]))) {
|
||||||
dactyl.beep();
|
dactyl.beep();
|
||||||
return KILL;
|
return KILL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ var MOW = Module("mow", {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (event.target instanceof HTMLAnchorElement)
|
if (event.target instanceof HTMLAnchorElement)
|
||||||
switch (events.toString(event)) {
|
switch (DOM.Event.stringify(event)) {
|
||||||
case "<LeftMouse>":
|
case "<LeftMouse>":
|
||||||
openLink(dactyl.CURRENT_TAB);
|
openLink(dactyl.CURRENT_TAB);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -768,6 +768,7 @@ function Class() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Class.extend(Constructor, superclass, args[0]);
|
Class.extend(Constructor, superclass, args[0]);
|
||||||
|
memoize(Constructor, "closure", Class.makeClosure);
|
||||||
update(Constructor, args[1]);
|
update(Constructor, args[1]);
|
||||||
|
|
||||||
Constructor.__proto__ = superclass;
|
Constructor.__proto__ = superclass;
|
||||||
|
|||||||
@@ -421,7 +421,7 @@ var Contexts = Module("contexts", {
|
|||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case "-keys":
|
case "-keys":
|
||||||
let silent = args["-silent"];
|
let silent = args["-silent"];
|
||||||
rhs = events.canonicalKeys(rhs, true);
|
rhs = DOM.Event.canonicalKeys(rhs, true);
|
||||||
var action = function action() {
|
var action = function action() {
|
||||||
events.feedkeys(action.macro(makeParams(this, arguments)),
|
events.feedkeys(action.macro(makeParams(this, arguments)),
|
||||||
noremap, silent);
|
noremap, silent);
|
||||||
|
|||||||
@@ -787,8 +787,9 @@ var DOM = Class("DOM", {
|
|||||||
/**
|
/**
|
||||||
* Creates an actual event from a pseudo-event object.
|
* Creates an actual event from a pseudo-event object.
|
||||||
*
|
*
|
||||||
* The pseudo-event object (such as may be retrieved from events.fromString)
|
* The pseudo-event object (such as may be retrieved from
|
||||||
* should have any properties you want the event to have.
|
* DOM.Event.parse) should have any properties you want the event to
|
||||||
|
* have.
|
||||||
*
|
*
|
||||||
* @param {Document} doc The DOM document to associate this event with
|
* @param {Document} doc The DOM document to associate this event with
|
||||||
* @param {Type} type The type of event (keypress, click, etc.)
|
* @param {Type} type The type of event (keypress, click, etc.)
|
||||||
@@ -834,6 +835,337 @@ var DOM = Class("DOM", {
|
|||||||
return evt;
|
return evt;
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
|
init: function init() {
|
||||||
|
// NOTE: the order of ["Esc", "Escape"] or ["Escape", "Esc"]
|
||||||
|
// matters, so use that string as the first item, that you
|
||||||
|
// want to refer to within dactyl's source code for
|
||||||
|
// comparisons like if (key == "<Esc>") { ... }
|
||||||
|
this.keyTable = {
|
||||||
|
add: ["Plus", "Add"],
|
||||||
|
back_space: ["BS"],
|
||||||
|
count: ["count"],
|
||||||
|
delete: ["Del"],
|
||||||
|
escape: ["Esc", "Escape"],
|
||||||
|
insert: ["Insert", "Ins"],
|
||||||
|
leader: ["Leader"],
|
||||||
|
left_shift: ["LT", "<"],
|
||||||
|
nop: ["Nop"],
|
||||||
|
pass: ["Pass"],
|
||||||
|
return: ["Return", "CR", "Enter"],
|
||||||
|
right_shift: [">"],
|
||||||
|
space: ["Space", " "],
|
||||||
|
subtract: ["Minus", "Subtract"]
|
||||||
|
};
|
||||||
|
|
||||||
|
this.key_key = {};
|
||||||
|
this.code_key = {};
|
||||||
|
this.key_code = {};
|
||||||
|
this.code_nativeKey = {};
|
||||||
|
|
||||||
|
for (let list in values(this.keyTable))
|
||||||
|
for (let v in values(list)) {
|
||||||
|
if (v.length == 1)
|
||||||
|
v = v.toLowerCase();
|
||||||
|
this.key_key[v.toLowerCase()] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let [k, v] in Iterator(Ci.nsIDOMKeyEvent)) {
|
||||||
|
this.code_nativeKey[v] = k.substr(4);
|
||||||
|
|
||||||
|
k = k.substr(7).toLowerCase();
|
||||||
|
let names = [k.replace(/(^|_)(.)/g, function (m, n1, n2) n2.toUpperCase())
|
||||||
|
.replace(/^NUMPAD/, "k")];
|
||||||
|
|
||||||
|
if (names[0].length == 1)
|
||||||
|
names[0] = names[0].toLowerCase();
|
||||||
|
|
||||||
|
if (k in this.keyTable)
|
||||||
|
names = this.keyTable[k];
|
||||||
|
|
||||||
|
this.code_key[v] = names[0];
|
||||||
|
for (let [, name] in Iterator(names)) {
|
||||||
|
this.key_key[name.toLowerCase()] = name;
|
||||||
|
this.key_code[name.toLowerCase()] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HACK: as Gecko does not include an event for <, we must add this in manually.
|
||||||
|
if (!("<" in this.key_code)) {
|
||||||
|
this.key_code["<"] = 60;
|
||||||
|
this.key_code["lt"] = 60;
|
||||||
|
this.code_key[60] = "lt";
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
code_key: Class.Memoize(function (prop) this.init()[prop]),
|
||||||
|
code_nativeKey: Class.Memoize(function (prop) this.init()[prop]),
|
||||||
|
keyTable: Class.Memoize(function (prop) this.init()[prop]),
|
||||||
|
key_code: Class.Memoize(function (prop) this.init()[prop]),
|
||||||
|
key_key: Class.Memoize(function (prop) this.init()[prop]),
|
||||||
|
pseudoKeys: Set(["count", "leader", "nop", "pass"]),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a user-input string of keys into a canonical
|
||||||
|
* representation.
|
||||||
|
*
|
||||||
|
* <C-A> maps to <C-a>, <C-S-a> maps to <C-S-A>
|
||||||
|
* <C- > maps to <C-Space>, <S-a> maps to A
|
||||||
|
* << maps to <lt><lt>
|
||||||
|
*
|
||||||
|
* <S-@> is preserved, as in Vim, to allow untypeable key-combinations
|
||||||
|
* in macros.
|
||||||
|
*
|
||||||
|
* canonicalKeys(canonicalKeys(x)) == canonicalKeys(x) for all values
|
||||||
|
* of x.
|
||||||
|
*
|
||||||
|
* @param {string} keys Messy form.
|
||||||
|
* @param {boolean} unknownOk Whether unknown keys are passed
|
||||||
|
* through rather than being converted to <lt>keyname>.
|
||||||
|
* @default false
|
||||||
|
* @returns {string} Canonical form.
|
||||||
|
*/
|
||||||
|
canonicalKeys: function canonicalKeys(keys, unknownOk) {
|
||||||
|
if (arguments.length === 1)
|
||||||
|
unknownOk = true;
|
||||||
|
return this.parse(keys, unknownOk).map(this.closure.stringify).join("");
|
||||||
|
},
|
||||||
|
|
||||||
|
iterKeys: function iterKeys(keys) iter(function () {
|
||||||
|
let match, re = /<.*?>?>|[^<]/g;
|
||||||
|
while (match = re.exec(keys))
|
||||||
|
yield match[0];
|
||||||
|
}()),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an event string into an array of pseudo-event objects.
|
||||||
|
*
|
||||||
|
* These objects can be used as arguments to {@link #stringify} or
|
||||||
|
* {@link DOM.Event}, though they are unlikely to be much use for other
|
||||||
|
* purposes. They have many of the properties you'd expect to find on a
|
||||||
|
* real event, but none of the methods.
|
||||||
|
*
|
||||||
|
* Also may contain two "special" parameters, .dactylString and
|
||||||
|
* .dactylShift these are set for characters that can never by
|
||||||
|
* typed, but may appear in mappings, for example <Nop> is passed as
|
||||||
|
* dactylString, and dactylShift is set when a user specifies
|
||||||
|
* <S-@> where @ is a non-case-changeable, non-space character.
|
||||||
|
*
|
||||||
|
* @param {string} keys The string to parse.
|
||||||
|
* @param {boolean} unknownOk Whether unknown keys are passed
|
||||||
|
* through rather than being converted to <lt>keyname>.
|
||||||
|
* @default false
|
||||||
|
* @returns {Array[Object]}
|
||||||
|
*/
|
||||||
|
parse: function parse(input, unknownOk) {
|
||||||
|
if (isArray(input))
|
||||||
|
return array.flatten(input.map(function (k) this.parse(k, unknownOk), this));
|
||||||
|
|
||||||
|
if (arguments.length === 1)
|
||||||
|
unknownOk = true;
|
||||||
|
|
||||||
|
let out = [];
|
||||||
|
for (let match in util.regexp.iterate(/<.*?>?>|[^<]|<(?!.*>)/g, input)) {
|
||||||
|
let evt_str = match[0];
|
||||||
|
|
||||||
|
let evt_obj = { ctrlKey: false, shiftKey: false, altKey: false, metaKey: false,
|
||||||
|
keyCode: 0, charCode: 0, type: "keypress" };
|
||||||
|
|
||||||
|
if (evt_str.length == 1) {
|
||||||
|
evt_obj.charCode = evt_str.charCodeAt(0);
|
||||||
|
evt_obj._keyCode = this.key_code[evt_str[0].toLowerCase()];
|
||||||
|
evt_obj.shiftKey = evt_str !== evt_str.toLowerCase();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let [match, modifier, keyname] = evt_str.match(/^<((?:[*12CASM⌘]-)*)(.+?)>$/i) || [false, '', ''];
|
||||||
|
modifier = Set(modifier.toUpperCase());
|
||||||
|
keyname = keyname.toLowerCase();
|
||||||
|
evt_obj.dactylKeyname = keyname;
|
||||||
|
if (/^u[0-9a-f]+$/.test(keyname))
|
||||||
|
keyname = String.fromCharCode(parseInt(keyname.substr(1), 16));
|
||||||
|
|
||||||
|
if (keyname && (unknownOk || keyname.length == 1 || /mouse$/.test(keyname) ||
|
||||||
|
this.key_code[keyname] || Set.has(this.pseudoKeys, keyname))) {
|
||||||
|
evt_obj.globKey ="*" in modifier;
|
||||||
|
evt_obj.ctrlKey ="C" in modifier;
|
||||||
|
evt_obj.altKey ="A" in modifier;
|
||||||
|
evt_obj.shiftKey ="S" in modifier;
|
||||||
|
evt_obj.metaKey ="M" in modifier || "⌘" in modifier;
|
||||||
|
evt_obj.dactylShift = evt_obj.shiftKey;
|
||||||
|
|
||||||
|
if (keyname.length == 1) { // normal characters
|
||||||
|
if (evt_obj.shiftKey)
|
||||||
|
keyname = keyname.toUpperCase();
|
||||||
|
|
||||||
|
evt_obj.dactylShift = evt_obj.shiftKey && keyname.toUpperCase() == keyname.toLowerCase();
|
||||||
|
evt_obj.charCode = keyname.charCodeAt(0);
|
||||||
|
evt_obj.keyCode = this.key_code[keyname.toLowerCase()];
|
||||||
|
}
|
||||||
|
else if (Set.has(this.pseudoKeys, keyname)) {
|
||||||
|
evt_obj.dactylString = "<" + this.key_key[keyname] + ">";
|
||||||
|
}
|
||||||
|
else if (/mouse$/.test(keyname)) { // mouse events
|
||||||
|
evt_obj.type = (/2-/.test(modifier) ? "dblclick" : "click");
|
||||||
|
evt_obj.button = ["leftmouse", "middlemouse", "rightmouse"].indexOf(keyname);
|
||||||
|
delete evt_obj.keyCode;
|
||||||
|
delete evt_obj.charCode;
|
||||||
|
}
|
||||||
|
else { // spaces, control characters, and <
|
||||||
|
evt_obj.keyCode = this.key_code[keyname];
|
||||||
|
evt_obj.charCode = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // an invalid sequence starting with <, treat as a literal
|
||||||
|
out = out.concat(this.parse("<lt>" + evt_str.substr(1)));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: make a list of characters that need keyCode and charCode somewhere
|
||||||
|
if (evt_obj.keyCode == 32 || evt_obj.charCode == 32)
|
||||||
|
evt_obj.charCode = evt_obj.keyCode = 32; // <Space>
|
||||||
|
if (evt_obj.keyCode == 60 || evt_obj.charCode == 60)
|
||||||
|
evt_obj.charCode = evt_obj.keyCode = 60; // <lt>
|
||||||
|
|
||||||
|
evt_obj.modifiers = (evt_obj.ctrlKey && Ci.nsIDOMNSEvent.CONTROL_MASK)
|
||||||
|
| (evt_obj.altKey && Ci.nsIDOMNSEvent.ALT_MASK)
|
||||||
|
| (evt_obj.shiftKey && Ci.nsIDOMNSEvent.SHIFT_MASK)
|
||||||
|
| (evt_obj.metaKey && Ci.nsIDOMNSEvent.META_MASK);
|
||||||
|
|
||||||
|
out.push(evt_obj);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the specified event to a string in dactyl key-code
|
||||||
|
* notation. Returns null for an unknown event.
|
||||||
|
*
|
||||||
|
* @param {Event} event
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
stringify: function stringify(event) {
|
||||||
|
if (isArray(event))
|
||||||
|
return event.map(function (e) this.stringify(e), this).join("");
|
||||||
|
|
||||||
|
if (event.dactylString)
|
||||||
|
return event.dactylString;
|
||||||
|
|
||||||
|
let key = null;
|
||||||
|
let modifier = "";
|
||||||
|
|
||||||
|
if (event.globKey)
|
||||||
|
modifier += "*-";
|
||||||
|
if (event.ctrlKey)
|
||||||
|
modifier += "C-";
|
||||||
|
if (event.altKey)
|
||||||
|
modifier += "A-";
|
||||||
|
if (event.metaKey)
|
||||||
|
modifier += "M-";
|
||||||
|
|
||||||
|
if (/^key/.test(event.type)) {
|
||||||
|
let charCode = event.type == "keyup" ? 0 : event.charCode; // Why? --Kris
|
||||||
|
if (charCode == 0) {
|
||||||
|
if (event.keyCode in this.code_key) {
|
||||||
|
key = this.code_key[event.keyCode];
|
||||||
|
|
||||||
|
if (event.shiftKey && (key.length > 1 || event.ctrlKey || event.altKey || event.metaKey) || event.dactylShift)
|
||||||
|
modifier += "S-";
|
||||||
|
else if (!modifier && key.length === 1)
|
||||||
|
if (event.shiftKey)
|
||||||
|
key = key.toUpperCase();
|
||||||
|
else
|
||||||
|
key = key.toLowerCase();
|
||||||
|
|
||||||
|
if (!modifier && /^[a-z0-9]$/i.test(key))
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// [Ctrl-Bug] special handling of mysterious <C-[>, <C-\\>, <C-]>, <C-^>, <C-_> bugs (OS/X)
|
||||||
|
// (i.e., cntrl codes 27--31)
|
||||||
|
// ---
|
||||||
|
// For more information, see:
|
||||||
|
// [*] Referenced mailing list msg: http://www.mozdev.org/pipermail/pentadactyl/2008-May/001548.html
|
||||||
|
// [*] Mozilla bug 416227: event.charCode in keypress handler has unexpected values on Mac for Ctrl with chars in "[ ] _ \"
|
||||||
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=416227
|
||||||
|
// [*] Mozilla bug 432951: Ctrl+'foo' doesn't seem same charCode as Meta+'foo' on Cocoa
|
||||||
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=432951
|
||||||
|
// ---
|
||||||
|
//
|
||||||
|
// The following fixes are only activated if config.OS.isMacOSX.
|
||||||
|
// Technically, they prevent mappings from <C-Esc> (and
|
||||||
|
// <C-C-]> if your fancy keyboard permits such things<?>), but
|
||||||
|
// these <C-control> mappings are probably pathological (<C-Esc>
|
||||||
|
// certainly is on Windows), and so it is probably
|
||||||
|
// harmless to remove the config.OS.isMacOSX if desired.
|
||||||
|
//
|
||||||
|
else if (config.OS.isMacOSX && event.ctrlKey && charCode >= 27 && charCode <= 31) {
|
||||||
|
if (charCode == 27) { // [Ctrl-Bug 1/5] the <C-[> bug
|
||||||
|
key = "Esc";
|
||||||
|
modifier = modifier.replace("C-", "");
|
||||||
|
}
|
||||||
|
else // [Ctrl-Bug 2,3,4,5/5] the <C-\\>, <C-]>, <C-^>, <C-_> bugs
|
||||||
|
key = String.fromCharCode(charCode + 64);
|
||||||
|
}
|
||||||
|
// a normal key like a, b, c, 0, etc.
|
||||||
|
else if (charCode > 0) {
|
||||||
|
key = String.fromCharCode(charCode);
|
||||||
|
|
||||||
|
if (!/^[a-z0-9]$/i.test(key) && key in this.key_code) {
|
||||||
|
// a named charCode key (<Space> and <lt>) space can be shifted, <lt> must be forced
|
||||||
|
if ((key.match(/^\s$/) && event.shiftKey) || event.dactylShift)
|
||||||
|
modifier += "S-";
|
||||||
|
|
||||||
|
key = this.code_key[this.key_code[key]];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// a shift modifier is only allowed if the key is alphabetical and used in a C-A-M- mapping in the uppercase,
|
||||||
|
// or if the shift has been forced for a non-alphabetical character by the user while :map-ping
|
||||||
|
if (key !== key.toLowerCase() && (event.ctrlKey || event.altKey || event.metaKey) || event.dactylShift)
|
||||||
|
modifier += "S-";
|
||||||
|
if (/^\s$/.test(key))
|
||||||
|
key = let (s = charCode.toString(16)) "U" + "0000".substr(4 - s.length) + s;
|
||||||
|
else if (modifier.length == 0)
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (key == null) {
|
||||||
|
if (event.shiftKey)
|
||||||
|
modifier += "S-";
|
||||||
|
key = this.key_key[event.dactylKeyname] || event.dactylKeyname;
|
||||||
|
}
|
||||||
|
if (key == null)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else if (event.type == "click" || event.type == "dblclick") {
|
||||||
|
if (event.shiftKey)
|
||||||
|
modifier += "S-";
|
||||||
|
if (event.type == "dblclick")
|
||||||
|
modifier += "2-";
|
||||||
|
// TODO: triple and quadruple click
|
||||||
|
|
||||||
|
switch (event.button) {
|
||||||
|
case 0:
|
||||||
|
key = "LeftMouse";
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
key = "MiddleMouse";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
key = "RightMouse";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return "<" + modifier + key + ">";
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
defaults: {
|
defaults: {
|
||||||
load: { bubbles: false },
|
load: { bubbles: false },
|
||||||
submit: { cancelable: true }
|
submit: { cancelable: true }
|
||||||
|
|||||||
@@ -1,98 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
|
|
||||||
<!-- ***** BEGIN LICENSE BLOCK ***** {{{
|
|
||||||
// Copyright (c) 2006-2009 by Martin Stubenschrott <stubenschrott@vimperator.org>
|
|
||||||
//
|
|
||||||
// This work is licensed for reuse under an MIT license. Details are
|
|
||||||
// given in the LICENSE.txt file included with this file.
|
|
||||||
}}} ***** END LICENSE BLOCK ***** -->
|
|
||||||
|
|
||||||
<?xml-stylesheet href="chrome://dactyl/skin/dactyl.css" type="text/css"?>
|
|
||||||
<!DOCTYPE overlay SYSTEM "dactyl.dtd" [
|
|
||||||
<!ENTITY dactyl.content "chrome://dactyl/content/">
|
|
||||||
]>
|
|
||||||
|
|
||||||
<overlay id="dactyl"
|
|
||||||
xmlns:dactyl="http://vimperator.org/namespaces/liberator"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:nc="http://home.netscape.com/NC-rdf#"
|
|
||||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
|
||||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
|
||||||
|
|
||||||
<script type="application/x-javascript;version=1.8" src="&dactyl.content;dactyl-overlay.js"/>
|
|
||||||
|
|
||||||
<window id="&dactyl.mainWindow;">
|
|
||||||
|
|
||||||
<keyset id="mainKeyset">
|
|
||||||
<key id="key_open_vimbar" key=":" oncommand="dactyl.modules.commandline.open(':', '', dactyl.modules.modes.EX);" modifiers=""/>
|
|
||||||
<key id="key_stop" keycode="VK_ESCAPE" oncommand="dactyl.modules.events.onEscape();"/>
|
|
||||||
<!-- other keys are handled inside the event loop in events.js -->
|
|
||||||
</keyset>
|
|
||||||
|
|
||||||
<popupset>
|
|
||||||
<panel id="dactyl-visualbell" dactyl:highlight="Bell"/>
|
|
||||||
</popupset>
|
|
||||||
|
|
||||||
<!--this notifies us also of focus events in the XUL
|
|
||||||
from: http://developer.mozilla.org/en/docs/XUL_Tutorial:Updating_Commands !-->
|
|
||||||
<commandset id="onPentadactylFocus"
|
|
||||||
commandupdater="true"
|
|
||||||
events="focus"
|
|
||||||
oncommandupdate="if (dactyl.modules.events != undefined) dactyl.modules.events.onFocusChange(event);"/>
|
|
||||||
<commandset id="onPentadactylSelect"
|
|
||||||
commandupdater="true"
|
|
||||||
events="select"
|
|
||||||
oncommandupdate="if (dactyl.modules.events != undefined) dactyl.modules.events.onSelectionChange(event);"/>
|
|
||||||
|
|
||||||
<!-- As of Firefox 3.1pre, <iframe>.height changes do not seem to have immediate effect,
|
|
||||||
therefore we need to put them into a <vbox> for which that works just fine -->
|
|
||||||
<vbox class="dactyl-container" hidden="false" collapsed="true">
|
|
||||||
<iframe id="dactyl-multiline-output" src="chrome://dactyl/content/buffer.xhtml"
|
|
||||||
flex="1" hidden="false" collapsed="false"
|
|
||||||
onclick="dactyl.modules.commandline.onMultilineOutputEvent(event)"/>
|
|
||||||
</vbox>
|
|
||||||
|
|
||||||
<vbox class="dactyl-container" hidden="false" collapsed="true">
|
|
||||||
<iframe id="dactyl-completions" src="chrome://dactyl/content/buffer.xhtml"
|
|
||||||
flex="1" hidden="false" collapsed="false"
|
|
||||||
onclick="dactyl.modules.commandline.onMultilineOutputEvent(event)"/>
|
|
||||||
</vbox>
|
|
||||||
|
|
||||||
<stack orient="horizontal" align="stretch" class="dactyl-container" dactyl:highlight="CmdLine">
|
|
||||||
<textbox class="plain" id="dactyl-message" flex="1" readonly="true" dactyl:highlight="Normal"/>
|
|
||||||
<hbox id="dactyl-commandline" hidden="false" collapsed="true" class="dactyl-container" dactyl:highlight="Normal">
|
|
||||||
<label class="plain" id="dactyl-commandline-prompt" flex="0" crop="end" value="" collapsed="true"/>
|
|
||||||
<textbox class="plain" id="dactyl-commandline-command" flex="1" type="timed" timeout="100"
|
|
||||||
oninput="dactyl.modules.commandline.onEvent(event);"
|
|
||||||
onkeyup="dactyl.modules.commandline.onEvent(event);"
|
|
||||||
onfocus="dactyl.modules.commandline.onEvent(event);"
|
|
||||||
onblur="dactyl.modules.commandline.onEvent(event);"/>
|
|
||||||
</hbox>
|
|
||||||
</stack>
|
|
||||||
|
|
||||||
<vbox class="dactyl-container" hidden="false" collapsed="false">
|
|
||||||
<textbox id="dactyl-multiline-input" class="plain" flex="1" rows="1" hidden="false" collapsed="true" multiline="true"
|
|
||||||
onkeypress="dactyl.modules.commandline.onMultilineInputEvent(event);"
|
|
||||||
oninput="dactyl.modules.commandline.onMultilineInputEvent(event);"
|
|
||||||
onblur="dactyl.modules.commandline.onMultilineInputEvent(event);"/>
|
|
||||||
</vbox>
|
|
||||||
|
|
||||||
</window>
|
|
||||||
|
|
||||||
<statusbar id="status-bar" dactyl:highlight="StatusLine">
|
|
||||||
<hbox insertbefore="&dactyl.statusBefore;" insertafter="&dactyl.statusAfter;"
|
|
||||||
id="dactyl-statusline" flex="1" hidden="false" align="center">
|
|
||||||
<textbox class="plain" id="dactyl-statusline-field-url" readonly="false" flex="1" crop="end"/>
|
|
||||||
<label class="plain" id="dactyl-statusline-field-inputbuffer" flex="0"/>
|
|
||||||
<label class="plain" id="dactyl-statusline-field-progress" flex="0"/>
|
|
||||||
<label class="plain" id="dactyl-statusline-field-tabcount" flex="0"/>
|
|
||||||
<label class="plain" id="dactyl-statusline-field-bufferposition" flex="0"/>
|
|
||||||
</hbox>
|
|
||||||
<!-- just hide them since other elements expect them -->
|
|
||||||
<statusbarpanel id="statusbar-display" hidden="true"/>
|
|
||||||
<statusbarpanel id="statusbar-progresspanel" hidden="true"/>
|
|
||||||
</statusbar>
|
|
||||||
|
|
||||||
</overlay>
|
|
||||||
|
|
||||||
<!-- vim: set fdm=marker sw=4 ts=4 et: -->
|
|
||||||
Reference in New Issue
Block a user