mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2025-12-28 20:32:27 +01:00
Implement 'timeout' and 'timeoutlen'.
--HG-- branch : key-processing
This commit is contained in:
@@ -11,12 +11,14 @@
|
||||
var ProcessorStack = Class("ProcessorStack", {
|
||||
init: function (mode, hives, keyModes) {
|
||||
this.main = mode.main;
|
||||
this._actions = [];
|
||||
this.actions = [];
|
||||
this.buffer = "";
|
||||
this.events = [];
|
||||
|
||||
this.processors = keyModes.map(function (m) hives.map(function (h) KeyProcessor(m, h)))
|
||||
.flatten().array;
|
||||
this.ownsBuffer = !this.processors.some(function (p) p.main.ownsBuffer);
|
||||
|
||||
for (let [i, input] in Iterator(this.processors)) {
|
||||
let params = input.main.params;
|
||||
@@ -31,9 +33,70 @@ var ProcessorStack = Class("ProcessorStack", {
|
||||
}
|
||||
},
|
||||
|
||||
notify: function () {
|
||||
this.execute(Events.KILL, true);
|
||||
},
|
||||
|
||||
execute: function execute(result, force) {
|
||||
|
||||
if (force && this.actions.length)
|
||||
this.processors.length = 0;
|
||||
|
||||
if (this.ownsBuffer)
|
||||
statusline.updateInputBuffer(this.processors.length ? this.buffer : "");
|
||||
|
||||
if (this.processors.length) {
|
||||
result = Events.KILL;
|
||||
if (this.actions.length && options["timeout"])
|
||||
this.timer = services.Timer(this, options["timeoutlen"], services.Timer.TYPE_ONE_SHOT);
|
||||
}
|
||||
else if (this.actions.length) {
|
||||
if (this._actions.length == 0) {
|
||||
dactyl.beep();
|
||||
events.feedingKeys = false;
|
||||
}
|
||||
|
||||
for (var res = this.actions[0]; callable(res);)
|
||||
res = res();
|
||||
result = res === Events.PASS ? Events.PASS : Events.KILL;
|
||||
}
|
||||
else if (result !== Events.KILL && !this.actions.length &&
|
||||
this.processors.some(function (p) !p.main.passUnknown)) {
|
||||
result = Events.KILL;
|
||||
dactyl.beep();
|
||||
events.feedingKeys = false;
|
||||
}
|
||||
else if (result === undefined)
|
||||
result = Events.PASS;
|
||||
|
||||
if (result !== Events.PASS)
|
||||
Events.kill(this.events[this.events.length - 1]);
|
||||
|
||||
if (result === Events.PASS || result === Events.ABORT)
|
||||
this.events.filter(function (e) e.getPreventDefault())
|
||||
.forEach(function (event, i) {
|
||||
let elem = event.originalTarget;
|
||||
if (event.originalTarget) {
|
||||
let doc = elem.ownerDocument || elem.document || elem;
|
||||
let evt = events.create(doc, event.type, event);
|
||||
events.dispatch(elem, evt, { skipmap: true, isMacro: true, isReplay: true });
|
||||
}
|
||||
else if (i > 0)
|
||||
events.events.keypress.call(events, event);
|
||||
});
|
||||
|
||||
if (force && this.processors.length === 0)
|
||||
events.processor = null;
|
||||
|
||||
return this.processors.length == 0;
|
||||
},
|
||||
|
||||
process: function process(event) {
|
||||
function dbg() {}
|
||||
|
||||
if (this.timer)
|
||||
this.timer.cancel();
|
||||
|
||||
let key = events.toString(event);
|
||||
this.events.push(event);
|
||||
|
||||
@@ -70,9 +133,7 @@ var ProcessorStack = Class("ProcessorStack", {
|
||||
dbg("ACTIONS: " + actions.length + " " + this.actions.length);
|
||||
dbg("PROCESSORS:", processors);
|
||||
|
||||
if (!processors.some(function (p) p.main.ownsBuffer))
|
||||
statusline.updateInputBuffer(processors.length ? this.buffer : "");
|
||||
|
||||
this._actions = actions;
|
||||
this.actions = actions.concat(this.actions);
|
||||
|
||||
if (result === Events.KILL)
|
||||
@@ -87,43 +148,7 @@ var ProcessorStack = Class("ProcessorStack", {
|
||||
|
||||
this.processors = processors;
|
||||
|
||||
if (processors.length)
|
||||
result = Events.KILL;
|
||||
else if (this.actions.length) {
|
||||
if (actions.length == 0) {
|
||||
dactyl.beep();
|
||||
events.feedingKeys = false;
|
||||
}
|
||||
|
||||
for (var res = this.actions[0]; callable(res);)
|
||||
res = res();
|
||||
result = res === Events.PASS ? Events.PASS : Events.KILL;
|
||||
}
|
||||
else if (result !== Events.KILL && !this.actions.length &&
|
||||
processors.some(function (p) !p.main.passUnknown)) {
|
||||
result = Events.KILL;
|
||||
dactyl.beep();
|
||||
events.feedingKeys = false;
|
||||
}
|
||||
else if (result === undefined)
|
||||
result = Events.PASS;
|
||||
|
||||
if (result !== Events.PASS)
|
||||
Events.kill(event);
|
||||
|
||||
if (result === Events.PASS || result === Events.ABORT)
|
||||
this.events.filter(function (e) e.getPreventDefault())
|
||||
.forEach(function (event, i) {
|
||||
let elem = event.originalTarget;
|
||||
if (event.originalTarget) {
|
||||
let doc = elem.ownerDocument || elem.document || elem;
|
||||
let evt = events.create(doc, event.type, event);
|
||||
events.dispatch(elem, evt, { skipmap: true, isMacro: true, isReplay: true });
|
||||
}
|
||||
else if (i > 0)
|
||||
events.events.keypress.call(events, event);
|
||||
});
|
||||
return this.processors.length == 0;
|
||||
return this.execute(result, options["timeout"] && options["timeoutlen"] === 0)
|
||||
}
|
||||
});
|
||||
|
||||
@@ -871,10 +896,7 @@ var Events = Module("events", {
|
||||
|
||||
isContentNode: function isContentNode(node) {
|
||||
let win = (node.ownerDocument || node).defaultView || node;
|
||||
for (; win; win = win.parent != win && win.parent)
|
||||
if (win == content)
|
||||
return true;
|
||||
return false;
|
||||
return XPCNativeWrapper(win).top == content;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -883,39 +905,24 @@ var Events = Module("events", {
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
waitForPageLoad: function () {
|
||||
waitForPageLoad: function (time) {
|
||||
util.threadYield(true); // clear queue
|
||||
|
||||
if (buffer.loaded == 1)
|
||||
if (buffer.loaded)
|
||||
return true;
|
||||
|
||||
const maxWaitTime = 25;
|
||||
dactyl.echo("Waiting for page to load...", commandline.DISALLOW_MULTILINE);
|
||||
|
||||
const maxWaitTime = (time || 25);
|
||||
let start = Date.now();
|
||||
let end = start + (maxWaitTime * 1000); // maximum time to wait - TODO: add option
|
||||
let now;
|
||||
while (now = Date.now(), now < end) {
|
||||
util.threadYield();
|
||||
let end = start + (maxWaitTime * 1000);
|
||||
|
||||
if (!events.feedingKeys)
|
||||
return false;
|
||||
|
||||
if (buffer.loaded > 0) {
|
||||
util.sleep(250);
|
||||
break;
|
||||
}
|
||||
else
|
||||
dactyl.echo("Waiting for page to load...", commandline.DISALLOW_MULTILINE);
|
||||
}
|
||||
util.waitFor(function () !events.feedingKeys || buffer.loaded || Date.now() > end);
|
||||
commandline.clear();
|
||||
|
||||
// TODO: allow macros to be continued when page does not fully load with an option
|
||||
if (!buffer.loaded)
|
||||
dactyl.echoerr("Page did not load completely in " + maxWaitTime + " seconds. Macro stopped.");
|
||||
|
||||
// sometimes the input widget had focus when replaying a macro
|
||||
// maybe this call should be moved somewhere else?
|
||||
// dactyl.focusContent(true);
|
||||
|
||||
return buffer.loaded;
|
||||
},
|
||||
|
||||
@@ -1368,14 +1375,15 @@ var Events = Module("events", {
|
||||
},
|
||||
{ count: true });
|
||||
|
||||
mappings.add([modes.MAIN],
|
||||
mappings.add([modes.COMMAND],
|
||||
["<A-m>l", "<wait-for-page-load>"], "Wait for the current page to finish loading before continuing macro playback",
|
||||
function () {
|
||||
if (!events.waitForPageLoad()) {
|
||||
function ({ count }) {
|
||||
if (events.feedingKeys && !events.waitForPageLoad(count)) {
|
||||
util.interrupted = true;
|
||||
throw Error("Interrupted");
|
||||
}
|
||||
});
|
||||
},
|
||||
{ count: true });
|
||||
},
|
||||
options: function () {
|
||||
options.add(["passkeys", "pk"],
|
||||
@@ -1396,9 +1404,18 @@ var Events = Module("events", {
|
||||
return values;
|
||||
}
|
||||
});
|
||||
|
||||
options.add(["strictfocus", "sf"],
|
||||
"Prevent scripts from focusing input elements without user intervention",
|
||||
"boolean", true);
|
||||
|
||||
options.add(["timeout", "to"],
|
||||
"Whether to execute a shorter key command after a timeout when a longer command exists",
|
||||
"boolean", true);
|
||||
|
||||
options.add(["timeoutlen", "tm"],
|
||||
"Maximum time to wait for a longer key command when a shorter command exists",
|
||||
"number", 1000);
|
||||
},
|
||||
sanitizer: function () {
|
||||
sanitizer.addItem("macros", {
|
||||
|
||||
Reference in New Issue
Block a user