Bug 802415 - Report virtual cursor position on selected tab when tab changes, or when focus moves to content area. r=davidb
authorEitan Isaacson <eitan@monotonous.org>
Fri, 19 Oct 2012 10:06:08 -0700
changeset 110925 a79ae6b8454775ce7dffef60c9df71fad3782743
parent 110924 4693be1c6bef109e841bbea9fd54990800f81b2a
child 110926 114ea5032eb04be4d5d5bb003595c5faaab33980
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersdavidb
bugs802415
milestone19.0a1
Bug 802415 - Report virtual cursor position on selected tab when tab changes, or when focus moves to content area. r=davidb
accessible/src/jsat/AccessFu.jsm
accessible/src/jsat/EventManager.jsm
accessible/src/jsat/content-script.js
--- a/accessible/src/jsat/AccessFu.jsm
+++ b/accessible/src/jsat/AccessFu.jsm
@@ -93,17 +93,19 @@ var AccessFu = {
 
     Input.attach(this.chromeWin);
     Output.attach(this.chromeWin);
     this.touchAdapter.attach(this.chromeWin);
 
     Services.obs.addObserver(this, 'remote-browser-frame-shown', false);
     Services.obs.addObserver(this, 'Accessibility:NextObject', false);
     Services.obs.addObserver(this, 'Accessibility:PreviousObject', false);
+    Services.obs.addObserver(this, 'Accessibility:Focus', false);
     this.chromeWin.addEventListener('TabOpen', this);
+    this.chromeWin.addEventListener('TabSelect', this);
   },
 
   /**
    * Disable AccessFu and return to default interaction mode.
    */
   _disable: function _disable() {
     if (!this._enabled)
       return;
@@ -114,20 +116,22 @@ var AccessFu = {
 
     this.chromeWin.document.removeChild(this.stylesheet);
     for each (let mm in Utils.getAllMessageManagers(this.chromeWin))
       mm.sendAsyncMessage('AccessFu:Stop');
 
     Input.detach();
 
     this.chromeWin.removeEventListener('TabOpen', this);
+    this.chromeWin.removeEventListener('TabSelect', this);
 
     Services.obs.removeObserver(this, 'remote-browser-frame-shown');
     Services.obs.removeObserver(this, 'Accessibility:NextObject');
     Services.obs.removeObserver(this, 'Accessibility:PreviousObject');
+    Services.obs.removeObserver(this, 'Accessibility:Focus');
   },
 
   _enableOrDisable: function _enableOrDisable() {
     try {
       if (this._activatePref == ACCESSFU_ENABLE ||
           this._systemPref && this._activatePref == ACCESSFU_AUTO)
         this._enable();
       else
@@ -179,16 +183,23 @@ var AccessFu = {
         this._enableOrDisable();
         break;
       case 'Accessibility:NextObject':
         Input.moveCursor('moveNext', 'Simple', 'gesture');
         break;
       case 'Accessibility:PreviousObject':
         Input.moveCursor('movePrevious', 'Simple', 'gesture');
         break;
+      case 'Accessibility:Focus':
+        this._focused = JSON.parse(aData);
+        if (this._focused) {
+          let mm = Utils.getMessageManager(Utils.getCurrentBrowser(this.chromeWin));
+          mm.sendAsyncMessage('AccessFu:VirtualCursor',
+                              {action: 'whereIsIt', move: true});
+        }
         break;
       case 'nsPref:changed':
         if (aData == 'activate') {
           this._activatePref = this.prefsBranch.getIntPref('activate');
           this._enableOrDisable();
         }
         break;
       case 'remote-browser-frame-shown':
@@ -210,21 +221,38 @@ var AccessFu = {
         }
         break;
       }
       case 'TabOpen':
       {
         this._loadFrameScript(Utils.getMessageManager(aEvent.target));
         break;
       }
+      case 'TabSelect':
+      {
+        if (this._focused) {
+          let mm = Utils.getMessageManager(Utils.getCurrentBrowser(this.chromeWin));
+          // We delay this for half a second so the awesomebar could close,
+          // and we could use the current coordinates for the content item.
+          // XXX TODO figure out how to avoid magic wait here.
+          this.chromeWin.setTimeout(
+            function () {
+              mm.sendAsyncMessage('AccessFu:VirtualCursor', {action: 'whereIsIt'});
+            }, 500);
+        }
+        break;
+      }
     }
   },
 
   // So we don't enable/disable twice
-  _enabled: false
+  _enabled: false,
+
+  // Layerview is focused
+  _focused: false
 };
 
 var Output = {
   attach: function attach(aWindow) {
     this.chromeWin = aWindow;
   },
 
   Speech: function Speech(aDetails, aBrowser) {
--- a/accessible/src/jsat/EventManager.jsm
+++ b/accessible/src/jsat/EventManager.jsm
@@ -239,16 +239,27 @@ var EventManager = {
         "AccessFu:Present",
         [aPresenterFunc(p) for each (p in this.presenters)].
           filter(function(d) {return !!d;}));
     } catch (x) {
       Logger.error(x);
     }
   },
 
+  presentVirtualCursorPosition: function presentVirtualCursorPosition(aVirtualCursor) {
+    let presenterContext =
+      new PresenterContext(aVirtualCursor.position, null);
+
+    this.present(
+      function(p) {
+        return p.pivotChanged(presenterContext, Ci.nsIAccessiblePivot.REASON_NONE);
+      }
+    );
+  },
+
   onStateChange: function onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
     let tabstate = '';
 
     let loadingState = Ci.nsIWebProgressListener.STATE_TRANSFERRING |
       Ci.nsIWebProgressListener.STATE_IS_DOCUMENT;
     let loadedState = Ci.nsIWebProgressListener.STATE_STOP |
       Ci.nsIWebProgressListener.STATE_IS_NETWORK;
 
--- a/accessible/src/jsat/content-script.js
+++ b/accessible/src/jsat/content-script.js
@@ -49,16 +49,25 @@ function virtualCursorControl(aMessage) 
         let acc = Utils.AccRetrieval.
           getAccessibleFor(content.document.activeElement);
         moved = vc.moveNext(rule, acc, true);
       }
       break;
     case 'moveToPoint':
       moved = vc.moveToPoint(rule, details.x, details.y, true);
       break;
+    case 'whereIsIt':
+      if (!forwardMessage(vc, aMessage)) {
+        if (!vc.position && aMessage.json.move)
+          vc.moveFirst(TraversalRules.Simple);
+        else
+          EventManager.presentVirtualCursorPosition(vc);
+      }
+
+      break;
     default:
       break;
     }
 
     if (moved == true) {
       forwardMessage(vc, aMessage);
     } else if (moved == false && details.action != 'moveToPoint') {
       if (origin == 'parent') {