Bug 810359 - Introduce haptic feedback. r=davidb
authorEitan Isaacson <eitan@monotonous.org>
Mon, 12 Nov 2012 15:46:09 -0800
changeset 113033 543413e0df7007b2b516f401cbfaef7d9589c7df
parent 113032 908a6c66f03dcb807889e19de3818368cd357ad5
child 113034 ae60a01fc2626590b5d01976f25ab22c58228ffc
push id23848
push useremorley@mozilla.com
push dateTue, 13 Nov 2012 16:29:34 +0000
treeherdermozilla-central@d56d537a1843 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdavidb
bugs810359
milestone19.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 810359 - Introduce haptic feedback. r=davidb
accessible/src/jsat/AccessFu.jsm
accessible/src/jsat/EventManager.jsm
accessible/src/jsat/Presenters.jsm
--- a/accessible/src/jsat/AccessFu.jsm
+++ b/accessible/src/jsat/AccessFu.jsm
@@ -296,16 +296,20 @@ var Output = {
     for each (let androidEvent in aDetails) {
       androidEvent.type = 'Accessibility:Event';
       if (androidEvent.bounds)
         androidEvent.bounds = this._adjustBounds(androidEvent.bounds, aBrowser);
       this._bridge.handleGeckoMessage(JSON.stringify({gecko: androidEvent}));
     }
   },
 
+  Haptic: function Haptic(aDetails, aBrowser) {
+    this.chromeWin.navigator.vibrate(aDetails.pattern);
+  },
+
   _adjustBounds: function(aJsonBounds, aBrowser) {
     let bounds = new Rect(aJsonBounds.left, aJsonBounds.top,
                           aJsonBounds.right - aJsonBounds.left,
                           aJsonBounds.bottom - aJsonBounds.top);
     let vp = Utils.getViewport(this.chromeWin) || { zoom: 1.0, offsetY: 0 };
     let browserOffset = aBrowser.getBoundingClientRect();
 
     return bounds.translate(browserOffset.left, browserOffset.top).
--- a/accessible/src/jsat/EventManager.jsm
+++ b/accessible/src/jsat/EventManager.jsm
@@ -21,16 +21,17 @@ this.EventManager = {
   start: function start(aSendMsgFunc) {
     try {
       if (!this._started) {
         this.sendMsgFunc = aSendMsgFunc || function() {};
         this.presenters = [new VisualPresenter()];
 
         if (Utils.MozBuildApp == 'b2g') {
           this.presenters.push(new SpeechPresenter());
+          this.presenters.push(new HapticPresenter());
         } else if (Utils.MozBuildApp == 'mobile/android') {
           this.presenters.push(new AndroidPresenter());
         }
 
         Logger.info('EventManager.start', Utils.MozBuildApp, [p.type for each(p in this.presenters)].join(', '));
 
         this._started = true;
         Services.obs.addObserver(this, 'accessible-event', false);
--- a/accessible/src/jsat/Presenters.jsm
+++ b/accessible/src/jsat/Presenters.jsm
@@ -12,16 +12,17 @@ const Cr = Components.results;
 Cu.import('resource://gre/modules/accessibility/Utils.jsm');
 Cu.import('resource://gre/modules/accessibility/UtteranceGenerator.jsm');
 Cu.import('resource://gre/modules/Geometry.jsm');
 
 this.EXPORTED_SYMBOLS = ['VisualPresenter',
                          'AndroidPresenter',
                          'DummyAndroidPresenter',
                          'SpeechPresenter',
+                         'HapticPresenter',
                          'PresenterContext'];
 
 /**
  * The interface for all presenter classes. A presenter could be, for example,
  * a speech output module, or a visual cursor indicator.
  */
 function Presenter() {}
 
@@ -106,17 +107,17 @@ Presenter.prototype = {
    */
   editingModeChanged: function editingModeChanged(aIsEditing) {}
 };
 
 /**
  * Visual presenter. Draws a box around the virtual cursor's position.
  */
 
-this.VisualPresenter = function VisualPresenter() {}
+this.VisualPresenter = function VisualPresenter() {};
 
 VisualPresenter.prototype = {
   __proto__: Presenter.prototype,
 
   type: 'Visual',
 
   /**
    * The padding in pixels between the object and the highlight border.
@@ -174,17 +175,17 @@ VisualPresenter.prototype = {
     return null;
   }
 };
 
 /**
  * Android presenter. Fires Android a11y events.
  */
 
-this.AndroidPresenter = function AndroidPresenter() {}
+this.AndroidPresenter = function AndroidPresenter() {};
 
 AndroidPresenter.prototype = {
   __proto__: Presenter.prototype,
 
   type: 'Android',
 
   // Android AccessibilityEvent type constants.
   ANDROID_VIEW_CLICKED: 0x01,
@@ -327,17 +328,17 @@ AndroidPresenter.prototype = {
     };
   }
 };
 
 /**
  * A speech presenter for direct TTS output
  */
 
-this.SpeechPresenter = function SpeechPresenter() {}
+this.SpeechPresenter = function SpeechPresenter() {};
 
 SpeechPresenter.prototype = {
   __proto__: Presenter.prototype,
 
   type: 'Speech',
 
   pivotChanged: function SpeechPresenter_pivotChanged(aContext, aReason) {
     if (!aContext.accessible)
@@ -368,16 +369,34 @@ SpeechPresenter.prototype = {
           {method: 'speak', data: output.join(' '), options: {enqueue: true}}
         ]
       }
     };
   }
 };
 
 /**
+ * A haptic presenter
+ */
+
+this.HapticPresenter = function HapticPresenter() {};
+
+HapticPresenter.prototype = {
+  __proto__: Presenter.prototype,
+
+  type: 'Haptic',
+
+  PIVOT_CHANGE_PATTHERN: [20],
+
+  pivotChanged: function HapticPresenter_pivotChanged(aContext, aReason) {
+    return { type: this.type, details: { pattern: this.PIVOT_CHANGE_PATTHERN } };
+  }
+};
+
+/**
  * PresenterContext: An object that generates and caches context information
  * for a given accessible and its relationship with another accessible.
  */
 this.PresenterContext = function PresenterContext(aAccessible, aOldAccessible) {
   this._accessible = aAccessible;
   this._oldAccessible =
     this._isDefunct(aOldAccessible) ? null : aOldAccessible;
 }