Bug 898008 - Use 'wheel' event for scrolling. r=maxli
authorEitan Isaacson <eitan@monotonous.org>
Fri, 26 Jul 2013 08:18:12 -0700
changeset 140165 7c565590d6713593dffea789d5fc6df954b794dc
parent 140164 155ab662755e07b1a582381ff0ff286d13df3de1
child 140166 00da124c775d4c4501a4813891bceb2f4bf9035a
push id1945
push userryanvm@gmail.com
push dateSat, 27 Jul 2013 02:27:26 +0000
treeherderfx-team@4874fa438b1c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmaxli
bugs898008
milestone25.0a1
Bug 898008 - Use 'wheel' event for scrolling. r=maxli
accessible/src/jsat/AccessFu.jsm
accessible/src/jsat/content-script.js
--- a/accessible/src/jsat/AccessFu.jsm
+++ b/accessible/src/jsat/AccessFu.jsm
@@ -196,16 +196,19 @@ this.AccessFu = {
         this._output(aMessage.json, aMessage.target);
         break;
       case 'AccessFu:Input':
         this.Input.setEditState(aMessage.json);
         break;
       case 'AccessFu:ActivateContextMenu':
         this.Input.activateContextMenu(aMessage.json);
         break;
+      case 'AccessFu:DoScroll':
+        this.Input.doScroll(aMessage.json);
+        break;
     }
   },
 
   _output: function _output(aPresentationData, aBrowser) {
     for each (let presenter in aPresentationData) {
       if (!presenter)
         continue;
 
@@ -235,23 +238,25 @@ this.AccessFu = {
     }
   },
 
   _addMessageListeners: function _addMessageListeners(aMessageManager) {
     aMessageManager.addMessageListener('AccessFu:Present', this);
     aMessageManager.addMessageListener('AccessFu:Input', this);
     aMessageManager.addMessageListener('AccessFu:Ready', this);
     aMessageManager.addMessageListener('AccessFu:ActivateContextMenu', this);
+    aMessageManager.addMessageListener('AccessFu:DoScroll', this);
   },
 
   _removeMessageListeners: function _removeMessageListeners(aMessageManager) {
     aMessageManager.removeMessageListener('AccessFu:Present', this);
     aMessageManager.removeMessageListener('AccessFu:Input', this);
     aMessageManager.removeMessageListener('AccessFu:Ready', this);
     aMessageManager.removeMessageListener('AccessFu:ActivateContextMenu', this);
+    aMessageManager.removeMessageListener('AccessFu:DoScroll', this);
   },
 
   _handleMessageManager: function _handleMessageManager(aMessageManager) {
     if (this._enabled) {
       this._addMessageListeners(aMessageManager);
     }
     this._loadFrameScript(aMessageManager);
   },
@@ -663,26 +668,26 @@ var Input = {
         break;
       case 'swiperight1':
         this.moveCursor('moveNext', 'Simple', 'gestures');
         break;
       case 'swipeleft1':
         this.moveCursor('movePrevious', 'Simple', 'gesture');
         break;
       case 'swiperight2':
-        this.scroll(-1, true);
+        this.sendScrollMessage(-1, true);
         break;
       case 'swipedown2':
-        this.scroll(-1);
+        this.sendScrollMessage(-1);
         break;
       case 'swipeleft2':
-        this.scroll(1, true);
+        this.sendScrollMessage(1, true);
         break;
       case 'swipeup2':
-        this.scroll(1);
+        this.sendScrollMessage(1);
         break;
       case 'explore2':
         Utils.CurrentBrowser.contentWindow.scrollBy(
           -aGesture.deltaX, -aGesture.deltaY);
         break;
       case 'swiperight3':
         this.moveCursor('moveNext', this.quickNavMode.current, 'gesture');
         break;
@@ -815,34 +820,52 @@ var Input = {
     mm.sendAsyncMessage('AccessFu:Activate', {offset: offset});
   },
 
   sendContextMenuMessage: function sendContextMenuMessage() {
     let mm = Utils.getMessageManager(Utils.CurrentBrowser);
     mm.sendAsyncMessage('AccessFu:ContextMenu', {});
   },
 
-  activateContextMenu: function activateContextMenu(aMessage) {
+  activateContextMenu: function activateContextMenu(aDetails) {
     if (Utils.MozBuildApp === 'mobile/android') {
-      let p = AccessFu.adjustContentBounds(aMessage.bounds, Utils.CurrentBrowser,
+      let p = AccessFu.adjustContentBounds(aDetails.bounds, Utils.CurrentBrowser,
                                            true, true).center();
       Services.obs.notifyObservers(null, 'Gesture:LongPress',
                                    JSON.stringify({x: p.x, y: p.y}));
     }
   },
 
   setEditState: function setEditState(aEditState) {
     this.editState = aEditState;
   },
 
+  // XXX: This is here for backwards compatability with screen reader simulator
+  // it should be removed when the extension is updated on amo.
   scroll: function scroll(aPage, aHorizontal) {
+    this.sendScrollMessage(aPage, aHorizontal);
+  },
+
+  sendScrollMessage: function sendScrollMessage(aPage, aHorizontal) {
     let mm = Utils.getMessageManager(Utils.CurrentBrowser);
     mm.sendAsyncMessage('AccessFu:Scroll', {page: aPage, horizontal: aHorizontal, origin: 'top'});
   },
 
+  doScroll: function doScroll(aDetails) {
+    let horizontal = aDetails.horizontal;
+    let page = aDetails.page;
+    let p = AccessFu.adjustContentBounds(aDetails.bounds, Utils.CurrentBrowser,
+                                         true, true).center();
+    let wu = Utils.win.QueryInterface(Ci.nsIInterfaceRequestor).
+      getInterface(Ci.nsIDOMWindowUtils);
+    wu.sendWheelEvent(p.x, p.y,
+                      horizontal ? page : 0, horizontal ? 0 : page, 0,
+                      Utils.win.WheelEvent.DOM_DELTA_PAGE, 0, 0, 0, 0);
+  },
+
   get keyMap() {
     delete this.keyMap;
     this.keyMap = {
       a: ['moveNext', 'Anchor'],
       A: ['movePrevious', 'Anchor'],
       b: ['moveNext', 'Button'],
       B: ['movePrevious', 'Button'],
       c: ['moveNext', 'Combobox'],
--- a/accessible/src/jsat/content-script.js
+++ b/accessible/src/jsat/content-script.js
@@ -301,90 +301,27 @@ function presentCaretChange(aText, aOldO
   if (aOldOffset !== aNewOffset) {
     let msg = Presentation.textSelectionChanged(aText, aNewOffset, aNewOffset,
                                                 aOldOffset, aOldOffset, true);
     sendAsyncMessage('AccessFu:Present', msg);
   }
 }
 
 function scroll(aMessage) {
-  let vc = Utils.getVirtualCursor(content.document);
-
-  function tryToScroll() {
-    let horiz = aMessage.json.horizontal;
-    let page = aMessage.json.page;
-
-    // Search up heirarchy for scrollable element.
-    let acc = vc.position;
-    while (acc) {
-      let elem = acc.DOMNode;
-
-      // This is inspired by IndieUI events. Once they are
-      // implemented, it should be easy to transition to them.
-      // https://dvcs.w3.org/hg/IndieUI/raw-file/tip/src/indie-ui-events.html#scrollrequest
-      let uiactions = elem.getAttribute ? elem.getAttribute('uiactions') : '';
-      if (uiactions && uiactions.split(' ').indexOf('scroll') >= 0) {
-        let evt = elem.ownerDocument.createEvent('CustomEvent');
-        let details = horiz ? { deltaX: page * elem.clientWidth } :
-          { deltaY: page * elem.clientHeight };
-        evt.initCustomEvent(
-          'scrollrequest', true, true,
-          ObjectWrapper.wrap(details, elem.ownerDocument.defaultView));
-        if (!elem.dispatchEvent(evt))
-          return;
-      }
-
-      // We will do window scrolling next.
-      if (elem == content.document)
-        break;
-
-      if (!horiz && elem.clientHeight < elem.scrollHeight) {
-        let s = content.getComputedStyle(elem);
-        if (s.overflowY == 'scroll' || s.overflowY == 'auto') {
-          elem.scrollTop += page * elem.clientHeight;
-          return true;
-        }
-      }
-
-      if (horiz) {
-        if (elem.clientWidth < elem.scrollWidth) {
-          let s = content.getComputedStyle(elem);
-          if (s.overflowX == 'scroll' || s.overflowX == 'auto') {
-            elem.scrollLeft += page * elem.clientWidth;
-            return true;
-          }
-        }
-      }
-      acc = acc.parent;
-    }
-
-    // Scroll window.
-    if (!horiz && content.scrollMaxY &&
-        ((page > 0 && content.scrollY < content.scrollMaxY) ||
-         (page < 0 && content.scrollY > 0))) {
-      content.scroll(0, content.innerHeight * page + content.scrollY);
-      return true;
-    } else if (horiz && content.scrollMaxX &&
-               ((page > 0 && content.scrollX < content.scrollMaxX) ||
-                (page < 0 && content.scrollX > 0))) {
-      content.scroll(content.innerWidth * page + content.scrollX);
-      return true;
-    }
-
-    return false;
+  function sendScrollCoordinates(aAccessible) {
+    let bounds = Utils.getBounds(aAccessible);
+    sendAsyncMessage('AccessFu:DoScroll',
+                     { bounds: bounds,
+                       page: aMessage.json.page,
+                       horizontal: aMessage.json.horizontal });
   }
 
-  if (aMessage.json.origin != 'child' &&
-      forwardToChild(aMessage, scroll, vc.position)) {
-    return;
-  }
-
-  if (!tryToScroll()) {
-    // Failed to scroll anything in this document. Try in parent document.
-    forwardToParent(aMessage);
+  let position = Utils.getVirtualCursor(content.document).position;
+  if (!forwardToChild(aMessage, scroll, position)) {
+    sendScrollCoordinates(position);
   }
 }
 
 addMessageListener(
   'AccessFu:Start',
   function(m) {
     Logger.debug('AccessFu:Start');
     if (m.json.buildApp)