Bug 865449 - Make AccessFu more desktop-browser friendly. r=yzen

- Use Speech presenter on everything but mobile/android
- Filter out accessibility events that are chrome related.
- Don't capture key presses on desktop
- Rework TouchAdapter to take mouse events on desktop.
    Generating touch events does not work on desktop since that interface is preffed out by default.
    We lost the ability to do multiple finger gestures with modifier keys, but that was not really used anyway.
This commit is contained in:
Eitan Isaacson 2013-04-25 12:39:16 -07:00
parent b02f33de95
commit 7336ca6c65
4 changed files with 54 additions and 92 deletions

View File

@ -475,12 +475,18 @@ var Input = {
editState: {}, editState: {},
start: function start() { start: function start() {
Utils.win.document.addEventListener('keypress', this, true); // XXX: This is too disruptive on desktop for now.
// Might need to add special modifiers.
if (Utils.MozBuildApp != 'browser') {
Utils.win.document.addEventListener('keypress', this, true);
}
Utils.win.addEventListener('mozAccessFuGesture', this, true); Utils.win.addEventListener('mozAccessFuGesture', this, true);
}, },
stop: function stop() { stop: function stop() {
Utils.win.document.removeEventListener('keypress', this, true); if (Utils.MozBuildApp != 'browser') {
Utils.win.document.removeEventListener('keypress', this, true);
}
Utils.win.removeEventListener('mozAccessFuGesture', this, true); Utils.win.removeEventListener('mozAccessFuGesture', this, true);
}, },

View File

@ -105,6 +105,13 @@ this.EventManager = {
Logger.debug('A11yEvent', Logger.eventToString(aEvent), Logger.debug('A11yEvent', Logger.eventToString(aEvent),
Logger.accessibleToString(aEvent.accessible)); Logger.accessibleToString(aEvent.accessible));
// Don't bother with non-content events in firefox.
if (Utils.MozBuildApp == 'browser' &&
aEvent.eventType != Ci.nsIAccessibleEvent.EVENT_VIRTUALCURSOR_CHANGED &&
aEvent.accessibleDocument != Utils.CurrentContentDoc) {
return;
}
switch (aEvent.eventType) { switch (aEvent.eventType) {
case Ci.nsIAccessibleEvent.EVENT_VIRTUALCURSOR_CHANGED: case Ci.nsIAccessibleEvent.EVENT_VIRTUALCURSOR_CHANGED:
{ {

View File

@ -361,11 +361,11 @@ this.Presentation = {
delete this.presenters; delete this.presenters;
this.presenters = [new VisualPresenter()]; this.presenters = [new VisualPresenter()];
if (Utils.MozBuildApp == 'b2g') { if (Utils.MozBuildApp == 'mobile/android') {
this.presenters.push(new AndroidPresenter());
} else {
this.presenters.push(new SpeechPresenter()); this.presenters.push(new SpeechPresenter());
this.presenters.push(new HapticPresenter()); this.presenters.push(new HapticPresenter());
} else if (Utils.MozBuildApp == 'mobile/android') {
this.presenters.push(new AndroidPresenter());
} }
return this.presenters; return this.presenters;

View File

@ -39,8 +39,8 @@ this.TouchAdapter = {
// maximum distance the mouse could move during a tap in inches // maximum distance the mouse could move during a tap in inches
TAP_MAX_RADIUS: 0.2, TAP_MAX_RADIUS: 0.2,
// The virtual touch ID generated by an Android hover event. // The virtual touch ID generated by a mouse event.
HOVER_ID: 'hover', MOUSE_ID: 'mouse',
start: function TouchAdapter_start() { start: function TouchAdapter_start() {
Logger.info('TouchAdapter.start'); Logger.info('TouchAdapter.start');
@ -62,16 +62,10 @@ this.TouchAdapter = {
target = this.glass; target = this.glass;
} }
target.addEventListener('mousemove', this, true, true); for each (let eventType in this.eventsOfInterest) {
target.addEventListener('mouseenter', this, true, true); target.addEventListener(eventType, this, true, true);
target.addEventListener('mouseleave', this, true, true); }
target.addEventListener('touchend', this, true, true);
target.addEventListener('touchmove', this, true, true);
target.addEventListener('touchstart', this, true, true);
if (Utils.OS != 'Android')
Mouse2Touch.start();
}, },
stop: function TouchAdapter_stop() { stop: function TouchAdapter_stop() {
@ -84,19 +78,34 @@ this.TouchAdapter = {
this.glass.parentNode.removeChild(this.glass); this.glass.parentNode.removeChild(this.glass);
} }
target.removeEventListener('mousemove', this, true, true); for each (let eventType in this.eventsOfInterest) {
target.removeEventListener('mouseenter', this, true, true); target.removeEventListener(eventType, this, true, true);
target.removeEventListener('mouseleave', this, true, true); }
},
target.removeEventListener('touchend', this, true, true); get eventsOfInterest() {
target.removeEventListener('touchmove', this, true, true); delete this.eventsOfInterest;
target.removeEventListener('touchstart', this, true, true);
if (Utils.OS != 'Android') if ('ontouchstart' in Utils.win) {
Mouse2Touch.stop(); this.eventsOfInterest = ['touchstart', 'touchmove', 'touchend'];
if (Utils.MozBuildApp == 'mobile/android') {
this.eventsOfInterest.push.apply(
this.eventsOfInterest, ['mouseenter', 'mousemove', 'mouseleave']);
}
} else {
this.eventsOfInterest = ['mousedown', 'mousemove', 'mouseup'];
}
return this.eventsOfInterest;
}, },
handleEvent: function TouchAdapter_handleEvent(aEvent) { handleEvent: function TouchAdapter_handleEvent(aEvent) {
// Don't bother with chrome mouse events.
if (Utils.MozBuildApp == 'browser' &&
aEvent.view.top instanceof Ci.nsIDOMChromeWindow) {
return;
}
if (this._delayedEvent) { if (this._delayedEvent) {
Utils.win.clearTimeout(this._delayedEvent); Utils.win.clearTimeout(this._delayedEvent);
delete this._delayedEvent; delete this._delayedEvent;
@ -108,13 +117,14 @@ this.TouchAdapter = {
// instead of milliseconds. // instead of milliseconds.
let timeStamp = (Utils.OS == 'Android') ? aEvent.timeStamp : Date.now(); let timeStamp = (Utils.OS == 'Android') ? aEvent.timeStamp : Date.now();
switch (aEvent.type) { switch (aEvent.type) {
case 'mousedown':
case 'mouseenter': case 'mouseenter':
case 'touchstart': case 'touchstart':
for (var i = 0; i < changedTouches.length; i++) { for (var i = 0; i < changedTouches.length; i++) {
let touch = changedTouches[i]; let touch = changedTouches[i];
let touchPoint = new TouchPoint(touch, timeStamp, this._dpi); let touchPoint = new TouchPoint(touch, timeStamp, this._dpi);
let identifier = (touch.identifier == undefined) ? let identifier = (touch.identifier == undefined) ?
this.HOVER_ID : touch.identifier; this.MOUSE_ID : touch.identifier;
this._touchPoints[identifier] = touchPoint; this._touchPoints[identifier] = touchPoint;
this._lastExploreTime = timeStamp + this.SWIPE_MAX_DURATION; this._lastExploreTime = timeStamp + this.SWIPE_MAX_DURATION;
} }
@ -128,7 +138,7 @@ this.TouchAdapter = {
for (var i = 0; i < changedTouches.length; i++) { for (var i = 0; i < changedTouches.length; i++) {
let touch = changedTouches[i]; let touch = changedTouches[i];
let identifier = (touch.identifier == undefined) ? let identifier = (touch.identifier == undefined) ?
this.HOVER_ID : touch.identifier; this.MOUSE_ID : touch.identifier;
let touchPoint = this._touchPoints[identifier]; let touchPoint = this._touchPoints[identifier];
if (touchPoint) if (touchPoint)
touchPoint.update(touch, timeStamp); touchPoint.update(touch, timeStamp);
@ -138,12 +148,13 @@ this.TouchAdapter = {
this._lastExploreTime = timeStamp; this._lastExploreTime = timeStamp;
} }
break; break;
case 'mouseup':
case 'mouseleave': case 'mouseleave':
case 'touchend': case 'touchend':
for (var i = 0; i < changedTouches.length; i++) { for (var i = 0; i < changedTouches.length; i++) {
let touch = changedTouches[i]; let touch = changedTouches[i];
let identifier = (touch.identifier == undefined) ? let identifier = (touch.identifier == undefined) ?
this.HOVER_ID : touch.identifier; this.MOUSE_ID : touch.identifier;
let touchPoint = this._touchPoints[identifier]; let touchPoint = this._touchPoints[identifier];
if (touchPoint) { if (touchPoint) {
touchPoint.update(touch, timeStamp); touchPoint.update(touch, timeStamp);
@ -155,6 +166,7 @@ this.TouchAdapter = {
} }
aEvent.preventDefault(); aEvent.preventDefault();
aEvent.stopImmediatePropagation();
}, },
cleanupTouches: function cleanupTouches() { cleanupTouches: function cleanupTouches() {
@ -239,13 +251,13 @@ this.TouchAdapter = {
// to single taps. // to single taps.
if (Utils.MozBuildApp == 'mobile/android' && if (Utils.MozBuildApp == 'mobile/android' &&
Utils.AndroidSdkVersion >= 14 && Utils.AndroidSdkVersion >= 14 &&
aDetails.touches[0] != this.HOVER_ID) { aDetails.touches[0] != this.MOUSE_ID) {
if (aDetails.touches.length == 1) { if (aDetails.touches.length == 1) {
if (aDetails.type == 'tap') { if (aDetails.type == 'tap') {
emitDelay = 50; emitDelay = 50;
aDetails.type = 'doubletap'; aDetails.type = 'doubletap';
} else { } else {
aDetails.touches.push(this.HOVER_ID); aDetails.touches.push(this.MOUSE_ID);
} }
} }
} }
@ -370,66 +382,3 @@ TouchPoint.prototype = {
return this.getDistanceToCoord(this.startX, this.startY); return this.getDistanceToCoord(this.startX, this.startY);
} }
}; };
var Mouse2Touch = {
_MouseToTouchMap: {
mousedown: 'touchstart',
mouseup: 'touchend',
mousemove: 'touchmove'
},
start: function Mouse2Touch_start() {
Utils.win.addEventListener('mousedown', this, true, true);
Utils.win.addEventListener('mouseup', this, true, true);
Utils.win.addEventListener('mousemove', this, true, true);
},
stop: function Mouse2Touch_stop() {
Utils.win.removeEventListener('mousedown', this, true, true);
Utils.win.removeEventListener('mouseup', this, true, true);
Utils.win.removeEventListener('mousemove', this, true, true);
},
handleEvent: function Mouse2Touch_handleEvent(aEvent) {
if (aEvent.buttons == 0)
return;
let name = this._MouseToTouchMap[aEvent.type];
let evt = Utils.win.document.createEvent("touchevent");
let points = [Utils.win.document.createTouch(
Utils.win, aEvent.target, 0,
aEvent.pageX, aEvent.pageY, aEvent.screenX, aEvent.screenY,
aEvent.clientX, aEvent.clientY, 1, 1, 0, 0)];
// Simulate another touch point at a 5px offset when ctrl is pressed.
if (aEvent.ctrlKey)
points.push(Utils.win.document.createTouch(
Utils.win, aEvent.target, 1,
aEvent.pageX + 5, aEvent.pageY + 5,
aEvent.screenX + 5, aEvent.screenY + 5,
aEvent.clientX + 5, aEvent.clientY + 5,
1, 1, 0, 0));
// Simulate another touch point at a -5px offset when alt is pressed.
if (aEvent.altKey)
points.push(Utils.win.document.createTouch(
Utils.win, aEvent.target, 2,
aEvent.pageX - 5, aEvent.pageY - 5,
aEvent.screenX - 5, aEvent.screenY - 5,
aEvent.clientX - 5, aEvent.clientY - 5,
1, 1, 0, 0));
let touches = Utils.win.document.createTouchList(points);
if (name == "touchend") {
let empty = Utils.win.document.createTouchList();
evt.initTouchEvent(name, true, true, Utils.win, 0,
false, false, false, false, empty, empty, touches);
} else {
evt.initTouchEvent(name, true, true, Utils.win, 0,
false, false, false, false, touches, touches, touches);
}
aEvent.target.dispatchEvent(evt);
aEvent.preventDefault();
aEvent.stopImmediatePropagation();
}
};