v1.20.1: Updated touch support to improve tablet operation

This commit is contained in:
Jeff Parsons 2015-10-31 15:22:01 -07:00
commit b0bac10944
141 changed files with 839 additions and 775 deletions

View file

@ -3194,6 +3194,21 @@ Video.prototype.captureTouch = function(nTouchConfig)
// this.log("touch events captured");
this.nTouchConfig = nTouchConfig;
this.xTouch = this.yTouch = this.timeTouch = -1;
/*
* As long as fTouchDefault is false, we call preventDefault() on every touch event, to prevent
* the page from moving/scrolling while the canvas is processing touch events. However, there must
* also be exceptions to permit the soft keyboard to activate; see processTouchEvent() for details.
*/
this.fTouchDefault = false;
/*
* I also need to come up with some rules for when the simulated mouse's primary button stays down.
* Let's try setting a timeout handler whenever a touchstart is received, which we'll immediately cancel
* as soon as a touchmove or touchend event is received, and if the timeout handler fires, we'll set
* fLongTouch to true.
*/
this.hLongTouch = null;
this.fLongTouch = false;
this.onLongTouch = function onLongTouch() { video.startLongTouch(); };
}
}
};
@ -3286,15 +3301,6 @@ Video.prototype.processTouchEvent = function(event, fStart)
var xTouch, yTouch;
// if (!event) event = window.event;
/*
* My thinking here is that if the canvas does NOT yet have focus, then we should actually SKIP
* the usual preventDefault() call, so that everything the user has come to expect (eg, activation of
* the soft keyboard) will work as before.
*
* The process of touching the canvas means it should ultimately receive focus, and as long as it
* retains focus, preventDefault() will always be called.
*/
if (this.fHasFocus) event.preventDefault();
/*
* Touch coordinates (that is, the pageX and pageY properties) are relative to the page, so to make
@ -3311,6 +3317,7 @@ Video.prototype.processTouchEvent = function(event, fStart)
var xTouchOffset = 0;
var yTouchOffset = 0;
var eCurrent = this.canvasScreen;
do {
if (!isNaN(eCurrent.offsetLeft)) {
xTouchOffset += eCurrent.offsetLeft;
@ -3364,17 +3371,47 @@ Video.prototype.processTouchEvent = function(event, fStart)
}
} else {
if (this.mouse) {
/*
* As long as fTouchDefault is false, we call preventDefault() on every touch event, to keep
* the page stable. However, we must allow some touch event(s) to perform their default action,
* otherwise the soft keyboard can never be activated. So if a touchstart occurs at least 1/2
* second (500ms) after the last touchstart, with no intervening touchmove events, fTouchDefault
* is allowed to become true.
*/
var fTouchDefault = this.fTouchDefault;
var timeDelta = event.timeStamp - this.timeTouch;
if (fStart === true) {
this.fTouchDefault = (timeDelta > 500);
this.timeTouch = event.timeStamp;
this.hLongTouch = setTimeout(this.onLongTouch, 500);
} else {
if (this.hLongTouch != null) {
clearTimeout(this.hLongTouch);
this.hLongTouch = null;
}
}
if (fStart === undefined) {
this.fTouchDefault = false;
}
if (DEBUG) {
this.log("processTouchEvent(" + (fStart? "touchStart" : (fStart === false? "touchEnd" : "touchMove")) + "," + timeDelta + "ms," + fTouchDefault + ")");
}
if (!fTouchDefault) {
event.preventDefault();
}
if (fStart === false) {
var timeDelta = event.timeStamp - this.timeTouch;
this.println("processTouchEvent(false," + timeDelta + ")");
/*
* NOTE: 200ms is merely my initial stab at a reasonable number of milliseconds to interpret a
* start/end touch sequence as a "tap"; I also make no note of any intervening move events (ie,
* events where fStart is undefined), and perhaps I should....
*/
if (this.endLongTouch()) {
return;
}
if (timeDelta < 200) {
this.mouse.clickMouse(Mouse.BUTTON.LEFT, true);
this.mouse.clickMouse(Mouse.BUTTON.LEFT, false);
@ -3400,6 +3437,33 @@ Video.prototype.processTouchEvent = function(event, fStart)
}
};
/**
* startLongTouch()
*
* @this {Video}
*/
Video.prototype.startLongTouch = function()
{
this.fLongTouch = true;
this.mouse.clickMouse(Mouse.BUTTON.LEFT, true);
};
/**
* endLongTouch()
*
* @this {Video}
* @return {boolean} true if long touch was active, false if not
*/
Video.prototype.endLongTouch = function()
{
if (this.fLongTouch) {
this.mouse.clickMouse(Mouse.BUTTON.LEFT, false);
this.fLongTouch = false;
return true;
}
return false;
};
/**
* powerUp(data, fRepower)
*

View file

@ -2948,14 +2948,14 @@ X86.opSTOSb = function()
* isn't a rock-solid implementation of the errata (for example, the ADDRESS override on the next
* instruction, if it exists, may or may not be the first prefix byte), but it's close enough.
*
* Note that we carefully monkey with maskAddr only AFTER updating ECX, because this errata affects
* only EDI in the case of STOS. The other instructions mentioned below monkey with different
* registers, so read the errata carefully.
* Note that we carefully alter with maskAddr only AFTER updating ECX, because this errata affects
* only EDI in the case of STOS. The other instructions mentioned below trash different registers,
* so read the errata carefully.
*
* TODO: Extend this errata to STOSW, as well as MOVSB, MOVSW, INSB, and INSW. Also, verify the
* extent to which this errata existed on earlier 80386 steppings (I'm currently assuming A0).
* extent to which this errata existed on earlier 80386 steppings (I'm currently assuming A0-B1).
*/
if (this.stepping >= X86.STEPPING_80386_A0 && this.stepping <= X86.STEPPING_80386_B1) {
if (this.stepping >= X86.STEPPING_80386_A0 && this.stepping <= X86.STEPPING_80386_B2) {
if (!(this.opPrefixes & X86.OPFLAG.ADDRSIZE) != (this.getByte(this.regLIP) != X86.OPCODE.AS)) {
maskAddr ^= (0xffff0000|0);
}