author | Kershaw Chang <kechang@mozilla.com> |
Tue, 15 Jul 2014 02:16:00 +0200 | |
changeset 194344 | b6ca88f40b7964d62ca2f2d91cc9998c4914c60f |
parent 194343 | d56e8ef026a035fd5e6c69369d00255710d7ab3c |
child 194345 | c12579b0b8561454443c5bbdb560c18ffa65ccd8 |
push id | 27144 |
push user | kwierso@gmail.com |
push date | Wed, 16 Jul 2014 21:35:16 +0000 |
treeherder | mozilla-central@4024d8019701 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | blassey |
bugs | 1032724 |
milestone | 33.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
|
toolkit/modules/SpatialNavigation.jsm | file | annotate | diff | comparison | revisions | |
toolkit/modules/tests/mochitest/test_spatial_navigation.html | file | annotate | diff | comparison | revisions |
--- a/toolkit/modules/SpatialNavigation.jsm +++ b/toolkit/modules/SpatialNavigation.jsm @@ -285,55 +285,38 @@ function _getBestToFocus(nodes, key, cur if (nodeMid.y <= (currentlyFocusedMid.y + currentlyFocusedRect.height / 2)) { continue; } break; } // Initialize best to the first viable value: if (!best) { - best = nodes[i]; - bestDist = _spatialDistance(best, currentlyFocused); + bestDist = _spatialDistanceOfCorner(currentlyFocused, nodes[i], key); + if (bestDist >= 0) { + best = nodes[i]; + } continue; } // Of the remaining nodes, pick the one closest to the currently focused // node. - let curDist = _spatialDistance(nodes[i], currentlyFocused); - if (curDist > bestDist) { + let curDist = _spatialDistanceOfCorner(currentlyFocused, nodes[i], key); + if ((curDist > bestDist) || curDist === -1) { continue; } + else if (curDist === bestDist) { + let midCurDist = _spatialDistance(currentlyFocused, nodes[i]); + let midBestDist = _spatialDistance(currentlyFocused, best); + if (midCurDist > midBestDist) + continue; + } - bestMid = _getMidpoint(best); - switch (key) { - case PrefObserver['keyCodeLeft']: - if (nodeMid.x > bestMid.x) { - best = nodes[i]; - bestDist = curDist; - } - break; - case PrefObserver['keyCodeRight']: - if (nodeMid.x < bestMid.x) { - best = nodes[i]; - bestDist = curDist; - } - break; - case PrefObserver['keyCodeUp']: - if (nodeMid.y > bestMid.y) { - best = nodes[i]; - bestDist = curDist; - } - break; - case PrefObserver['keyCodeDown']: - if (nodeMid.y < bestMid.y) { - best = nodes[i]; - bestDist = curDist; - } - break; - } + best = nodes[i]; + bestDist = curDist; } return best; } // Returns the midpoint of a node. function _getMidpoint(node) { let mid = {}; let box = node.getBoundingClientRect(); @@ -371,47 +354,144 @@ function _getSearchRect(currentlyFocused newRect.top = currentlyFocusedRect.top; newRect.right = currentlyFocusedRect.right; newRect.bottom = currentlyFocusedRect.bottom; newRect.width = currentlyFocusedRect.width; newRect.height = currentlyFocusedRect.height; switch (key) { case PrefObserver['keyCodeLeft']: + newRect.right = newRect.left; + newRect.left = cssPageRect.left; + newRect.width = newRect.right - newRect.left; + + newRect.bottom = cssPageRect.bottom; + newRect.top = cssPageRect.top; + newRect.height = newRect.bottom - newRect.top; + break; + + case PrefObserver['keyCodeRight']: + newRect.left = newRect.right; + newRect.right = cssPageRect.right; + newRect.width = newRect.right - newRect.left; + + newRect.bottom = cssPageRect.bottom; + newRect.top = cssPageRect.top; + newRect.height = newRect.bottom - newRect.top; + break; + + case PrefObserver['keyCodeUp']: + newRect.bottom = newRect.top; + newRect.top = cssPageRect.top; + newRect.height = newRect.bottom - newRect.top; + + newRect.right = cssPageRect.right; newRect.left = cssPageRect.left; newRect.width = newRect.right - newRect.left; break; - case PrefObserver['keyCodeRight']: - newRect.right = cssPageRect.right; - newRect.width = newRect.right - newRect.left; - break; - - case PrefObserver['keyCodeUp']: - newRect.top = cssPageRect.top; - newRect.height = newRect.bottom - newRect.top; - break; - case PrefObserver['keyCodeDown']: + newRect.top = newRect.bottom; newRect.bottom = cssPageRect.bottom; newRect.height = newRect.bottom - newRect.top; + + newRect.right = cssPageRect.right; + newRect.left = cssPageRect.left; + newRect.width = newRect.right - newRect.left; break; } return newRect; } // Gets the distance between two points a and b. function _spatialDistance(a, b) { let mida = _getMidpoint(a); let midb = _getMidpoint(b); return Math.round(Math.pow(mida.x - midb.x, 2) + Math.pow(mida.y - midb.y, 2)); } +// Get the distance between the corner of two nodes +function _spatialDistanceOfCorner(from, to, key) { + let fromRect = from.getBoundingClientRect(); + let toRect = to.getBoundingClientRect(); + let fromMid = _getMidpoint(from); + let toMid = _getMidpoint(to); + let hDistance = 0; + let vDistance = 0; + + switch (key) { + case PrefObserver['keyCodeLeft']: + // Make sure the "to" node is really at the left side of "from" node by + // 1. Check the mid point + // 2. The right border of "to" node must be less than the "from" node + if ((fromMid.x - toMid.x) < 0 || toRect.right >= fromRect.right) + return -1; + hDistance = Math.abs(fromRect.left - toRect.right); + if (toRect.bottom <= fromRect.top) { + vDistance = fromRect.top - toRect.bottom; + } + else if (fromRect.bottom <= toRect.top) { + vDistance = toRect.top - fromRect.bottom; + } + else { + vDistance = 0; + } + break; + + case PrefObserver['keyCodeRight']: + if ((toMid.x - fromMid.x) < 0 || toRect.left <= fromRect.left) + return -1; + hDistance = Math.abs(toRect.left - fromRect.right); + if (toRect.bottom <= fromRect.top) { + vDistance = fromRect.top - toRect.bottom; + } + else if (fromRect.bottom <= toRect.top) { + vDistance = toRect.top - fromRect.bottom; + } + else { + vDistance = 0; + } + break; + + case PrefObserver['keyCodeUp']: + if ((fromMid.y - toMid.y) < 0 || toRect.bottom >= fromRect.bottom) + return -1; + vDistance = Math.abs(fromRect.top - toRect.bottom); + if (fromRect.right <= toRect.left) { + hDistance = toRect.left - fromRect.right; + } + else if (toRect.right <= fromRect.left) { + hDistance = fromRect.left - toRect.right; + } + else { + hDistance = 0; + } + break; + + case PrefObserver['keyCodeDown']: + if ((toMid.y - fromMid.y) < 0 || toRect.top <= fromRect.top) + return -1; + vDistance = Math.abs(toRect.top - fromRect.bottom); + if (fromRect.right <= toRect.left) { + hDistance = toRect.left - fromRect.right; + } + else if (toRect.right <= fromRect.left) { + hDistance = fromRect.left - toRect.right; + } + else { + hDistance = 0; + } + break; + } + return Math.round(Math.pow(hDistance, 2) + + Math.pow(vDistance, 2)); +} + // Snav preference observer var PrefObserver = { register: function() { this.prefService = Cc["@mozilla.org/preferences-service;1"] .getService(Ci.nsIPrefService); this._branch = this.prefService.getBranch("snav."); this._branch.QueryInterface(Ci.nsIPrefBranch2); @@ -519,9 +599,9 @@ var PrefObserver = { } catch(e) { this.keyCodeReturn = Ci.nsIDOMKeyEvent.DOM_VK_RETURN; } break; } } }; -PrefObserver.register(); +PrefObserver.register(); \ No newline at end of file
--- a/toolkit/modules/tests/mochitest/test_spatial_navigation.html +++ b/toolkit/modules/tests/mochitest/test_spatial_navigation.html @@ -34,45 +34,43 @@ https://bugzilla.mozilla.org/show_bug.cg console.log(left); console.log(right); center.focus(); is(center.id, document.activeElement.id, "How did we call focus on center and it did" + " not become the active element?"); synthesizeKey("VK_UP", { }); - is(top.id, document.activeElement.id, + is(document.activeElement.id, top.id, "Spatial navigation up key is not handled correctly."); center.focus(); synthesizeKey("VK_DOWN", { }); - is(bottom.id, document.activeElement.id, + is(document.activeElement.id, bottom.id, "Spatial navigation down key is not handled correctly."); center.focus(); synthesizeKey("VK_RIGHT", { }); - is(right.id, document.activeElement.id, + is(document.activeElement.id, right.id, "Spatial navigation right key is not handled correctly."); center.focus(); synthesizeKey("VK_LEFT", { }); - is(left.id, document.activeElement.id, + is(document.activeElement.id, left.id, "Spatial navigation left key is not handled correctly."); SimpleTest.finish(); } </script> </head> <body onload="Test();"> <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=698437">Mozilla Bug 698437</a> <p id="display"></p> <div id="content"> - <p> This is a <a id="top" href="#">really</a> long sentence </p> - <p> <a id="left" href="#">This</a> is a - <a id="center" href="#">really</a> long - <a id="right" href="#">sentence</a> </p> - <p> This is a <a id="bottom" href="#">really</a> long sentence </p> + <button id="lefttop">1</button><button id="top">2</button><button id="righttop">3</button><br> + <button id="left">4</button><button id="center">5</button><button id="right">6</button><br> + <button id="leftbottom">7</button><button id="bottom">8</button><button id="rightbottom">9</button><br> </div> <pre id="test"> </pre> </body> </html>