Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1968)

Unified Diff: chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js

Issue 1295213003: Make cvox2 output feedback more robust when focusing a text field. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@plundblad_fix
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js
index 6abdb980da3fb97047fd01d0c1fa8e98aa49325b..0c552d39b1d90fae1c76746e1204bfc5dfd2a04f 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js
@@ -65,6 +65,23 @@ Background = function() {
/** @type {!ClassicCompatibility} @private */
this.compat_ = new ClassicCompatibility();
+ /** @type {Array<Object>} A queue of incoming events. @private */
+ this.eventQueue_ = [];
Peter Lundblad 2015/08/20 08:30:05 I suggest putting the event queue into its own cla
+
+ /**
+ * @type {?number}
+ * The window.setTimeout timer ID of the event queue timer.
+ * @private
+ */
+ this.eventQueueTimerId_ = null;
Peter Lundblad 2015/08/20 08:30:05 Since your code already relies on timer ids being
+
+ /**
+ * @type {number}
+ * How long to hold events in the event queue before executing them.
+ * @const
+ */
+ this.EVENT_QUEUE_DELAY_MS = 10;
David Tseng 2015/08/19 17:19:25 nit: make private.
Peter Lundblad 2015/08/20 08:30:05 Put constants outside of the constructor, directly
+
// Manually bind all functions to |this|.
for (var func in this) {
if (typeof(this[func]) == 'function')
@@ -88,6 +105,12 @@ Background = function() {
valueChanged: this.onValueChanged
};
+ /**
+ * The object that speaks changes to an editable text field.
+ * @type {?cvox.ChromeVoxEditableTextBase}
Peter Lundblad 2015/08/20 08:30:05 Document when this is null.
+ */
+ this.editableTextHandler_ = null;
+
chrome.automation.getDesktop(this.onGotDesktop);
// Handle messages directed to the Next background page.
@@ -123,7 +146,7 @@ Background.prototype = {
onGotDesktop: function(desktop) {
// Register all automation event listeners.
for (var eventType in this.listeners_)
- desktop.addEventListener(eventType, this.listeners_[eventType], true);
+ desktop.addEventListener(eventType, this.addToEventQueue_, true);
// Register a tree change observer.
chrome.automation.addTreeChangeObserver(this.onTreeChange);
@@ -401,6 +424,59 @@ Background.prototype = {
},
/**
+ * Add an event to the event queue so that we can avoid ignore
David Tseng 2015/08/19 17:19:25 avoid or ignore
+ * transient states - for example if focus moves to one node and
+ * then immediately another, or if a node gains focus and
+ * immediately changes its selection.
+ *
+ * @param {Object} evt
+ */
David Tseng 2015/08/19 17:19:25 nit: @private
+ addToEventQueue_: function(evt) {
+ evt.enqueueTime = new Date();
Peter Lundblad 2015/08/20 08:30:05 Should we extend the automation api with a time fi
+ this.eventQueue_.push(evt);
+ if (!this.eventQueueTimerId_) {
+ this.eventQueueTimerId_ = window.setTimeout(
+ this.executeNextEventFromQueue_, this.EVENT_QUEUE_DELAY_MS);
+ }
+ },
+
+ /**
+ * Filter duplicates from the event queue, then pop the first item
+ * off and if it's time to execute it, do so, otherwise set the timer
+ * to wake up again.
David Tseng 2015/08/19 17:19:25 nit: @private
+ */
+ executeNextEventFromQueue_: function() {
Peter Lundblad 2015/08/20 08:30:05 nit: s/execute/handle/ ?
+ this.eventQueueTimerId_ = null;
+
+ if (this.eventQueue_.length == 0) {
+ return;
+ }
David Tseng 2015/08/19 17:19:25 nit: remove braces.
+
+ // Assuming the queue is in increasing order of enqueue time, remove all except the
+ // last item of each type.
+ var lastTimeForEventType = {};
Peter Lundblad 2015/08/20 08:30:05 Why not just store the object reference instead of
+ this.eventQueue_.forEach(function(evt) {
+ lastTimeForEventType[evt.type] = evt.enqueueTime;
+ });
+ this.eventQueue_ = this.eventQueue_.filter(function(evt) {
+ return evt.enqueueTime == lastTimeForEventType[evt.type];
David Tseng 2015/08/19 17:19:25 Any issues doing this generically? For example, do
+ });
+
+ while (this.eventQueue_.length) {
+ var now = new Date();
+ var delta = now - this.eventQueue_[0].enqueueTime;
+ if (delta < this.EVENT_QUEUE_DELAY_MS) {
+ this.eventQueueTimerId_ = window.setTimeout(
+ this.executeNextEventFromQueue_, this.EVENT_QUEUE_DELAY_MS - delta);
+ return;
+ }
+
+ var evt = this.eventQueue_.shift();
+ this.listeners_[evt.type](evt);
+ }
+ },
+
+ /**
* Provides all feedback once ChromeVox's focus changes.
* @param {Object} evt
*/
@@ -454,6 +530,11 @@ Background.prototype = {
Dir.FORWARD,
AutomationPredicate.focused) || node;
}
+
+ if (evt.target.role == 'textField' || evt.target.role == 'textBox') {
David Tseng 2015/08/19 17:19:25 nit: please use RoleType.textField and RoleType.te
+ this.createEditableTextHandlerIfNeeded_(evt.target);
+ }
+
this.onEventDefault({target: node, type: 'focus'});
},
@@ -511,23 +592,14 @@ Background.prototype = {
this.currentRange_ = cursors.Range.fromNode(evt.target);
}
+ this.createEditableTextHandlerIfNeeded_(evt.target);
var textChangeEvent = new cvox.TextChangeEvent(
evt.target.value,
evt.target.textSelStart,
evt.target.textSelEnd,
true); // triggered by user
- if (!this.editableTextHandler ||
- evt.target != this.currentRange_.start.node) {
- this.editableTextHandler =
- new cvox.ChromeVoxEditableTextBase(
- textChangeEvent.value,
- textChangeEvent.start,
- textChangeEvent.end,
- evt.target.state['protected'],
- cvox.ChromeVox.tts);
- }
+ this.editableTextHandler_.changed(textChangeEvent);
- this.editableTextHandler.changed(textChangeEvent);
new Output().withBraille(
this.currentRange_, null, evt.type)
.go();
@@ -689,7 +761,23 @@ Background.prototype = {
}.bind(this));
this.mode_ = mode;
- }
+ },
+
+ /**
+ * Create an editable text handler for the given node if needed.
+ * @param {Object} node
David Tseng 2015/08/19 17:19:25 s/Object/AutomationNode
+ */
David Tseng 2015/08/19 17:19:25 @private
+ createEditableTextHandlerIfNeeded_: function(node) {
+ if (!this.editableTextHandler_ || node != this.currentRange_.start.node) {
+ this.editableTextHandler_ =
+ new cvox.ChromeVoxEditableTextBase(
+ node.value,
+ node.textSelStart,
+ node.textSelEnd,
+ node.state['protected'],
+ cvox.ChromeVox.tts);
+ }
+ },
};
/** @type {Background} */

Powered by Google App Engine
This is Rietveld 408576698